Skip to content

Latest commit

 

History

History
572 lines (435 loc) · 14.9 KB

File metadata and controls

572 lines (435 loc) · 14.9 KB
sidebar_position 5

Configuration

Klunok can be configured with the Lua programming language. Settings are global Lua variables assigned in a file. (If you want to use an auxiliary variable with a name that is guaranteed not to clash with any future settings, begin the name with aux or custom). If the file is within directories that are monitored by Klunok, the settings are automatically reloaded when the file is written to. Here is an example of the content of the configuration file:

debounce_seconds = 5
editors['emacs-28.2'] = true

The file is passed to Klunok via the -c command-line option, like this:

klunok -c ~/.config/klunok.lua

This page documents the available settings, their types, and default values.

Configuration parsing code is extracted from this page to ensure that the documentation is always up to date. This imposes a certain structure on this page. Lua code blocks titled pre-config are executed before the passed configuration file. These blocks assign static default values to some settings. You can use these values in your configuration file, like this:

debounce_seconds = debounce_seconds * 2
prefix_var = prefix .. '/volatile'

Lua code blocks titled post-config are executed after the passed configuration file. These blocks invoke the declare function. The invocations specify the name of a setting, its dynamically computed default value and its type. Here is a sample invocation:

declare('prefix_var', prefix .. '/var', is_string)

This invocation means that a setting called prefix_var must be a string, and if it's not set in the configuration file, its value is dynamically computed as the string /var concatenated to the value of the prefix setting. The declare function is defined below:

function declare(name, default, assertion)
  if _G[name] == nil and default ~= nil then
    _G[name] = default
  else
    assertion(name)
  end
end

Setting types

The functions below check that a setting is of the right type. They are used as the third argument to the declare function.

is_string accepts only strings. Strings in Lua are enclosed in double or single quotes, like "this" or 'this'.

function is_string(name)
  assert(type(_G[name]) == 'string', name .. ' must be a string')
end

is_nil_or_string accepts nil and strings. nil in Lua is a representation of the absence of a value. nil is not the same as an empty string ''. The description of a setting of this type will specify what exactly nil represents in the context of the setting.

function is_nil_or_string(name)
  assert(_G[name] == nil or type(_G[name]) == 'string', name .. ' must be nil or a string')
end

is_positive accepts integers greater than or equal to zero.

function is_positive(name)
  local value = _G[name]
  assert(
    type(value) == 'number' and math.floor(value) == value and value >= 0,
    name .. ' must be a positive integer'
  )
end

is_set_of_strings accepts Lua tables with string keys. Working with settings of this type usually means setting individual keys to true or nil. For example, to add the string 'abc' to the set xyz, you can write xyz.abc = true. To remove 'abc' from xyz, you can write xyz.abc = nil. If the key contains characters that are not letters, for example string '/@', you can add the key as xyz['/@'] = true and remove it as xyz['/@'] = nil.

function is_set_of_strings(name)
  local value = _G[name]
  assert(type(value) == 'table', name .. ' must be a table')
  for key, _ in pairs(value) do
    assert(type(key) == 'string', name .. ' must contain only string keys')
  end
end

Changing the paths that Klunok writes to

prefix

Prefix used by default for all of the paths that Klunok writes to.

prefix = '/var/klunok'
prefix = 'klunok'
declare('prefix', nil, is_string)

prefix_var

Prefix used by default for non-store paths that Klunok writes to.

declare('prefix_var', prefix .. '/var', is_string)

store_root

Root of the store. This is where the backed up versions of files that you edit are placed.

declare('store_root', prefix .. '/store', is_string)

queue_path

Path to the queue. The queue is a directory that contains symbolic links to files that you edit. Klunok uses the queue for debouncing.

declare('queue_path', prefix_var .. '/queue', is_string)

journal_path

Path to the journal. The journal is a file where Klunok records various events, for example a file being backed up. See the other events here. If nil, Klunok does not write journal events anywhere. Specifying nil is more efficient than '/dev/null'.

journal_path = '/dev/stderr' -- write the events to the terminal
declare('journal_path', prefix_var .. '/journal', is_nil_or_string)

offset_store_root

Root of an auxiliary store used for keeping track of offsets of history_paths.

declare('offset_store_root', prefix_var .. '/offsets', is_string)

working_copy_link_name

If not empty, a symbolic link with this name plus the original file extension will be kept in the store alongside the backed-up versions and will point to the original file.

declare('working_copy_link_name', '', is_string)

Debouncing

Debouncing means delaying copying until some time passes without any further modifications.

debounce_seconds

The delay, in seconds, before a file is copied to the store after the last modification.

debounce_seconds = 60
declare('debounce_seconds', nil, is_positive)

Timestamps and versions

These settings use the strftime special characters.

journal_timestamp_pattern

Pattern of timestamps in the journal.

journal_timestamp_pattern = '%Y-%m-%d-%H-%M'
declare('journal_timestamp_pattern', nil, is_string)

version_pattern

Pattern of file versions in the store.

declare('version_pattern', 'v' .. journal_timestamp_pattern, is_string)

Controlling which files are copied to the store and how

By default, a file is copied to the store only if it's written to by an editor application and it's not hidden. A file is hidden if its name or the name of one of its ancestor directories begins with a dot, for example .config, unless that whole path segment is listed in ignored_leading_dots.

Relative paths are interpreted relative to the common parent of directories monitored via the -w command line option. For example, if Klunok is invoked as klunok -w /home/nazar/src -w /home/nazar/.config/nvim -w /home/nazar/.config/klunok, relative paths are interpreted relative to /home/nazar.

history_paths, excluded_paths, included_paths and cluded_paths can be paths not only to files, but also to directories. If a path is a directory, the setting applies to each file in the directory and its descendants. More specific paths override less specific ones. For example, let's consider this configuration:

excluded_paths['/home/nazar'] = true
included_paths['/home/nazar/src'] = true
excluded_paths['/home/nazar/src/secret.txt'] = true
included_paths['/home/nazar/.config/klunok'] = true

With this configuration:

  • /home/nazar/file.txt is excluded;
  • /home/nazar/src/file.txt is included;
  • /home/nazar/src/project/file.txt is included;
  • /home/nazar/src/secret.txt is excluded;
  • /home/nazar/.config/file.txt is excluded because the .config directory is hidden;
  • /home/nazar/.config/klunok/file.txt is included;
  • /home/nazar/.config/klunok/.file.txt is excluded.

ignored_leading_dots

Path segments whose leading dot does not make a path hidden. This applies only to exact segment names, not prefixes. For example, if .github is listed here, then .github/workflows/ci.yml is not hidden, but .github/.env is still hidden because .env is not listed.

ignored_leading_dots['.custom-hidden'] = true
ignored_leading_dots = {
  ['.clang-format'] = true,
  ['.clang-format-ignore'] = true,
  ['.clang-tidy'] = true,
  ['.clangd'] = true,
  ['.dockerignore'] = true,
  ['.editorconfig'] = true,
  ['.gitattributes'] = true,
  ['.github'] = true,
  ['.gitignore'] = true,
  ['.gitlab'] = true,
  ['.gitlab-ci.yml'] = true,
  ['.mailmap'] = true,
  ['.pre-commit-config.yaml'] = true,
  ['.pre-commit-config.yml'] = true,
  ['.prettierignore'] = true,
  ['.prettierrc'] = true,
  ['.prettierrc.cjs'] = true,
  ['.prettierrc.js'] = true,
  ['.prettierrc.json'] = true,
  ['.prettierrc.json5'] = true,
  ['.prettierrc.mjs'] = true,
  ['.prettierrc.toml'] = true,
  ['.prettierrc.yaml'] = true,
  ['.prettierrc.yml'] = true,
}
declare('ignored_leading_dots', nil, is_set_of_strings)

editors

Filenames of executables that are considered editors. By default, only files edited by these applications are copied to the store. If you have problems registering an application as an editor, please read the editors section.

editors.ed = true
editors['emacs-28.3'] = true
editors.code = nil -- do not treat "code" as an editor
editors = {
  atom = true,
  code = true,
  codium = true,
  gedit = true,
  howl = true,
  hx = true,
  inkscape = true,
  kak = true,
  kate = true,
  kwrite = true,
  micro = true,
  nano = true,
  nvim = true,
  pluma = true,
  rsession = true,
  sublime_text = true,
  vi = true,
  vim = true,
  xed = true,
  ['gnome-text-editor'] = true,
  ['notepadqq-bin'] = true,
  ['soffice.bin'] = true,
  ['vim.basic'] = true,
  ['vim.tiny'] = true,
  ['.gedit-wrapped'] = true,
  ['.gnome-text-editor-wrapped'] = true,
  ['.howl-wrapped'] = true,
  ['.hx-wrapped'] = true,
  ['.inkscape-wrapped'] = true,
  ['.kate-wrapped'] = true,
  ['.kwrite-wrapped'] = true,
  ['.pluma-wrapped'] = true,
  ['.xed-wrapped'] = true,
}
declare('editors', nil, is_set_of_strings)

history_paths

Paths that are assumed to be always appended to. Only changes will be stored as new versions. These paths are copied to the store regardless of the application that writes to them and hence regardless of the editors setting.

history_paths['/home/nazar/.bash_history'] = true
history_paths = {}
declare('history_paths', nil, is_set_of_strings)

excluded_paths

Paths that are never copied to the store.

excluded_paths = {}
declare('excluded_paths', nil, is_set_of_strings)

included_paths

Paths that are copied to the store regardless of the application that writes to them, and hence regardless of the editors setting.

included_paths = {}
declare('included_paths', nil, is_set_of_strings)

cluded_paths

Paths that are copied to the store only if they are written to by an editor application. Editor applications are defined in the editors setting.

This is the default, so this setting is mainly useful to:

  • override history_paths, excluded_paths and included_paths;
  • include files in hidden directories if the files themselves are not hidden, for example specifying cluded_paths['/home/nazar/.config'] = true will allow /home/nazar/.config/klunok.lua to be copied when written to by an editor application, but /home/nazar/.config/.klunok.lua and /home/nazar/.config/.klunok/config.lua will not be copied.
cluded_paths = {}
declare('cluded_paths', nil, is_set_of_strings)

Projects

See the projects section.

project_roots

Roots of projects.

project_roots['/home/nazar/src/klunok'] = true
project_roots = {}
declare('project_roots', nil, is_set_of_strings)

project_parents

Directories that contain roots of projects.

project_parents['/home/nazar/src'] = true
project_parents = {}
declare('project_parents', nil, is_set_of_strings)

project_store_root

Root of the project store.

declare('project_store_root', prefix .. '/projects', is_string)

unstable_project_store_root

Root of the unstable project store.

declare('unstable_project_store_root', prefix_var .. '/projects', is_string)

Performance tuning

These settings control the trade-off between RAM usage and performance. Tinkering with these settings cannot impact Klunok in any other way.

queue_size_guess

Guess of the maximum queue size.

declare('queue_size_guess', debounce_seconds * 2, is_positive)

path_length_guess

Guess of the maximum length of the majority of the paths in the system.

path_length_guess = 1024
declare('path_length_guess', nil, is_positive)

max_pid_guess

Guess of the maximum PID (process ID) in the system while Klunok is running.

max_pid_guess = 2^15
declare('max_pid_guess', nil, is_positive)

elf_interpreter_count_guess

Guess of how many ELF interpreters there are in the system.

elf_interpreter_count_guess = 1
declare('elf_interpreter_count_guess', nil, is_positive)

Events

If a setting from this section is nil, the corresponding event is not logged to the journal. Otherwise, the corresponding event is logged to the journal with the provided prefix. If the prefix is not an empty string, it is separated from the rest of the logged line by a tab.

event_queue_head_stored = ''
declare('event_open_exec_not_editor', nil, is_nil_or_string)
declare('event_open_exec_editor', nil, is_nil_or_string)
declare('event_close_write_ignored', event_close_write_not_by_editor, is_nil_or_string)
declare('event_close_write_not_ignored', event_close_write_by_editor, is_nil_or_string)
declare('event_queue_head_deleted', nil, is_nil_or_string)
declare('event_queue_head_forbidden', nil, is_nil_or_string)
declare('event_queue_head_stored', nil, is_nil_or_string)