e0d33f51b3
Whenever a new history node is committed after some undo steps, instead of creating a new branch in the undo graph, we first append the inverse modifications starting from the end of the undo list up to the current position before adding the new node. For example let's assume that the undo history is A-B-C, that a single undo has been done (bringing us to state B) and that a new change D is committed. Instead of creating a new branch starting at B, we add the inverse of C (noted ^C) at the end, and D afterwards. This results in the undo history A-B-C-^C-D. Since C-^C collapses to a null change, this is equivalent to A-B-D but without having lost the C branch of the history. If a new change is committed while no undo has been done, the new history node is simply appended to the list, as was the case previously. This results in a simplification of the user interaction, as two bindings are now sufficient to walk the entire undo history, as opposed to needing extra bindings to switch branches whenever they occur. The <a-u> and <a-U> bindings are now free. It also simplifies the implementation, as the graph traversal and branching code are not needed anymore. The parent and child of a node are now respectively the previous and the next elements in the list, so there is no need to store their ID as part of the node. Only the committing of an undo group is slightly more complex, as inverse history nodes need to be added depending on the current position in the undo list. The following article was the initial motivation for this change: https://github.com/zaboople/klonk/blob/master/TheGURQ.md
430 lines
15 KiB
Plaintext
430 lines
15 KiB
Plaintext
= Expansions
|
||
|
||
While parsing a command (see <<command-parsing#,`:doc command-parsing`>>),
|
||
Kakoune recognises certain patterns and will replace them with their
|
||
associated value before executing the command. These patterns are called
|
||
expansions.
|
||
|
||
Every expansion consists of a `%`, followed by the expansion _type_ (one
|
||
or more alphabetic characters), a quoting character, and then all the text
|
||
up to and including its matching character.
|
||
|
||
If a nestable punctuation character (`(`, `[`, `{`, or `<`) is used as the
|
||
opening quoting character, the expansion will end at its matching opposite
|
||
(`)`, `]`, `}`, or `>`). Nested pairs of the braces used in the expansion are
|
||
allowed, but they must be balanced. Braces other than the ones used in the
|
||
expansion need not be balanced, however. For example, `%{nest{ed} non[nested}`
|
||
is valid and expands to `nest{ed} non[nested`.
|
||
|
||
If any other character is used, the expansion will end at the next occurrence of
|
||
that character. The quoting character can be escaped inside the expansion if it
|
||
is doubled-up. For example, `%|abc||def|` expands to the text `abc|def`.
|
||
|
||
It doesn't matter which character is used, but `{}` are most common.
|
||
|
||
There are 2 types of quoting which can be used to group together words separated
|
||
by whitespace into a single argument or prevent expansions from expanding:
|
||
|
||
"double quoted strings"::
|
||
Double quoted strings are mainly for grouping multiple `%` expansions or
|
||
`%` expansions and regular text as a single argument. `%` and `"` can be
|
||
escaped by doubling the characters (i.e. `%%` and `""`).
|
||
|
||
'single quoted strings'::
|
||
Expansions are not processed inside single quoted strings. Single quotes can
|
||
be escaped by doubling up (i.e. `''`).
|
||
|
||
Expansions are processed when unquoted and anywhere inside double-quoted
|
||
strings, but not inside unquoted words, inside single-quoted strings, or
|
||
inside %-strings or other expansions (see
|
||
<<command-parsing#typed-expansions, `:doc command-parsing typed-expansions`>>
|
||
for full details). For example:
|
||
|
||
* `echo %val{session}` echoes the current session ID
|
||
|
||
* `echo x%val{session}x` echoes the literal text `x%val{session}x`
|
||
|
||
* `echo '%val{session}'` echoes the literal text `%val{session}`
|
||
|
||
* `echo "x%val{session}x"` echoes the current session ID, surrounded by `x`
|
||
|
||
* `echo %{%val{session}}` echoes the the literal text `%val{session}`
|
||
|
||
* `echo %sh{ echo %val{session} }` echoes the literal text `%val{session}`
|
||
|
||
Like "variable expansion" and "command substitution" in shell programming,
|
||
Kakoune expansions can expand to multiple "words" - that is, separate
|
||
arguments on the resulting command-line. However, unlike shell programming,
|
||
Kakoune expansions cannot _accidentally_ expand to multiple words because they
|
||
contain whitespace or other special characters. Only expansions which
|
||
semantically contain a list of values (list-type options, registers, selections,
|
||
etc.) expand to multiple arguments. While in shell-programming it's good
|
||
practice to always wrap expansions in double-quotes, in Kakoune it's perfectly
|
||
safe to leave expansions unquoted.
|
||
|
||
== Argument expansions
|
||
|
||
Expansions with the type `arg` can only be used inside the "commands" parameter
|
||
of the `define-command` command (See <<commands#declaring-new-commands,`:doc
|
||
commands declaring-new-commands`>>).
|
||
|
||
The following expansions are available:
|
||
|
||
*%arg{n}*::
|
||
(where _n_ is a decimal number) +
|
||
expands to argument number _n_ of the current command
|
||
|
||
*%arg{@}*::
|
||
expands to all the arguments of the current command, as individual words
|
||
|
||
== Option expansions
|
||
|
||
Expansions with the type `opt` expand to the value associated with the named
|
||
option in the current scope (See <<options#,`:doc options`>>).
|
||
|
||
For example, `%opt{BOM}` expands to `utf8` or to `none`, according to the
|
||
current state of the `BOM` option.
|
||
|
||
== Register expansions
|
||
|
||
Expansions with the type `reg` expand to the contents of the named
|
||
register. For registers named after symbols (like the search register
|
||
`/`), the expansion can use either the symbol or the alphabetic name (See
|
||
<<registers#,`:doc registers`>>).
|
||
|
||
For example, `%reg{/}` expands to the content of the `/` register, and so does
|
||
`%reg{slash}`.
|
||
|
||
== Shell expansions
|
||
|
||
Expansions with the type `sh` are executed as shell-scripts, and whatever
|
||
the script prints to standard output replaces the expansion. For example,
|
||
the command `echo %sh{date}` will echo the output of the `date` command.
|
||
|
||
TIP: If a shell expansion writes to standard error, that output is appended to
|
||
Kakoune's `\*debug*` buffer. If you're trying to debug a shell expansion,
|
||
check the debug buffer with `:buffer \*debug*` to see if anything shows up.
|
||
|
||
Because Kakoune does not expand expansions inside the text of an expansion,
|
||
you can't use normal expansions inside `%sh{}`. Instead, Kakoune can export
|
||
expansions as environment variables to make them available to the shell.
|
||
Here's how expansion patterns map to variable names:
|
||
|
||
*%arg{n}*::
|
||
(where _n_ is a decimal number) +
|
||
becomes `$_n_`. For example, `%arg{3}` becomes `$3`.
|
||
|
||
*%arg{@}*::
|
||
becomes `$@`
|
||
|
||
*%opt{x}*::
|
||
becomes `$kak_opt_x`
|
||
|
||
*%reg{x}*::
|
||
(where _x_ is the alphabetic name of a register) +
|
||
`$kak_reg_x` contains all the selections in register _x_ +
|
||
`$kak_main_reg_x` contains only the main selection
|
||
|
||
*%val{x}*::
|
||
becomes `$kak_x`
|
||
|
||
Values can be quoted with a shell compatible quoting by using `$kak_quoted_`
|
||
as a prefix, this is mostly useful for list-type options and registers, as
|
||
it allows to correctly work with lists where elements might contains
|
||
whitespaces:
|
||
|
||
----
|
||
eval set -- "$kak_quoted_selections"
|
||
while [ $# -gt 0 ]; do
|
||
# ... do a thing with $1 ...
|
||
shift
|
||
done
|
||
----
|
||
|
||
The `eval` command will take the expanded `$kak_quoted_selections`
|
||
and unquote them, then execute the resulting `set` command, which sets
|
||
the shell's argument variables to the items from `$kak_selections`. The
|
||
`while` loop with `shift` iterates through the arguments one by one.
|
||
|
||
Only variables actually mentioned in the body of the shell expansion will
|
||
be exported into the shell's environment. For example:
|
||
|
||
----
|
||
echo %sh{ env | grep ^kak_ }
|
||
----
|
||
|
||
... will find none of Kakoune's special environment variables, but:
|
||
|
||
----
|
||
echo %sh{ env | grep ^kak_ # kak_session }
|
||
----
|
||
|
||
... will find the `$kak_session` variable because it was mentioned by name
|
||
in a comment, even though it wasn't directly used.
|
||
|
||
TIP: These environment variables are also available in other contexts where
|
||
Kakoune uses a shell command, such as the `|`, `!` or `$` normal mode commands
|
||
(See <<keys#,`:doc keys`>>).
|
||
|
||
=== Command and Response fifo
|
||
|
||
Inside shell expansions, `$kak_command_fifo` refers to a named pipe that
|
||
accepts Kakoune commands to be executed as soon as the fifo is closed. This
|
||
named pipe can be opened and closed multiple times which makes it possible
|
||
to interleave shell and Kakoune commands. `$kak_response_fifo` refers to
|
||
a named pipe that can be used to return data from Kakoune.
|
||
|
||
----
|
||
%sh{
|
||
echo "write $kak_response_fifo" > $kak_command_fifo
|
||
content="$(cat $kak_response_fifo)"
|
||
}
|
||
----
|
||
|
||
This also makes it possible to pass data bigger than the system environment
|
||
size limit.
|
||
|
||
== File expansions
|
||
|
||
Expansions with the type `file` will expand to the content of the filename
|
||
given in argument as read from the host filesystem.
|
||
|
||
For example, this command stores the entire content of `/etc/passwd` into the
|
||
`a` register.
|
||
|
||
----
|
||
set-register a %file{/etc/passwd}
|
||
----
|
||
|
||
== Value expansions
|
||
|
||
Expansions with the type `val` give access to Kakoune internal data that is
|
||
not stored in an option or a register. Some value expansions can only be used
|
||
in certain contexts, like `%val{hook_param}` that expands to the parameter
|
||
string of the currently-executing hook, and is not available outside a hook.
|
||
|
||
The following expansions are supported (with required context _in italics_):
|
||
|
||
*%val{buffile}*::
|
||
_in buffer, window scope_ +
|
||
full path of the file or same as `%val{bufname}` when there’s no
|
||
associated file
|
||
|
||
*%val{buf_line_count}*::
|
||
_in buffer, window scope_ +
|
||
number of lines in the current buffer
|
||
|
||
*%val{buflist}*::
|
||
quoted list of the names of currently-open buffers (as seen in
|
||
`%val{bufname}`)
|
||
|
||
*%val{bufname}*::
|
||
_in buffer, window scope_ +
|
||
name of the current buffer
|
||
|
||
*%val{client_env_X}*::
|
||
_in window scope_ +
|
||
value of the `$X` environment variable in the client displaying the current
|
||
window (e.g. `%val{client_env_SHELL}` is `$SHELL` in the client's
|
||
environment)
|
||
|
||
*%val{client_list}*::
|
||
unquoted list of the names of clients (as seen in `%val{client}`)
|
||
connected to the current session
|
||
|
||
*%val{client}*::
|
||
_in window scope_ +
|
||
name of the client displaying the current window
|
||
|
||
*%val{client_pid}*::
|
||
_in window scope_ +
|
||
process id of the client displaying the current window
|
||
|
||
*%val{config}*::
|
||
directory containing the user configuration
|
||
|
||
*%val{count}*::
|
||
_in `map` command <keys> parameter and `<a-;>` from object menu_ +
|
||
current count when the mapping was triggered, defaults to 0 if no
|
||
count given
|
||
|
||
*%val{cursor_byte_offset}*::
|
||
_in window scope_ +
|
||
offset of the main cursor from the beginning of the buffer (in bytes)
|
||
|
||
*%val{cursor_char_column}*::
|
||
_in window scope_ +
|
||
1-based offset from the start of the line to the cursor position in
|
||
Unicode codepoints, which may differ from visible columns if the document
|
||
contains full-width codepoints (which occupy two columns) or zero-width
|
||
codepoints
|
||
|
||
*%val{cursor_display_column}*::
|
||
_in window scope_ +
|
||
1-based offset from the start of the line to the cursor position in
|
||
display column, taking into account tabs and character width.
|
||
|
||
*%val{cursor_char_value}*::
|
||
_in window scope_ +
|
||
unicode value of the codepoint under the main cursor
|
||
|
||
*%val{cursor_column}*::
|
||
_in window scope_ +
|
||
1-based offset from the start of the line to the first byte of the
|
||
character under the main cursor (in bytes), the fourth component of
|
||
`%val{selection_desc}`
|
||
|
||
*%val{cursor_line}*::
|
||
_in window scope_ +
|
||
line of the main cursor, the third component of `%val{selection_desc}`
|
||
|
||
*%val{error}*::
|
||
_in `try` command's <on_error_commands> parameter_ +
|
||
the text of the error that cancelled execution of the <commands> parameter
|
||
(or the previous <on_error_commands> parameter)
|
||
|
||
*%val{history}*::
|
||
_in buffer, window scope_ +
|
||
the full change history of the buffer, as a list of
|
||
`committed modification0 modification1 ...` entries.
|
||
_committed_ is a count in seconds from Kakoune's steady clock's epoch of
|
||
the creation of the history entry, and each _modification_ is presented
|
||
as in `%val{uncommitted_modifications}`.
|
||
Boundaries in the list can be identified knowing that _committed_ is a
|
||
plain integer, and each _modification_ starts with `+` or `-`.
|
||
|
||
*%val{history_id}*::
|
||
_in buffer, window scope_ +
|
||
history id of the current buffer, an integer value which refers to a
|
||
specific buffer version in the undo tree (see also `%val{timestamp}`)
|
||
|
||
*%val{hook_param_capture_n}*::
|
||
_in `hook` command <command> parameter_ +
|
||
text captured by capture group _n_, if the executing hook's filter regex
|
||
used capture groups
|
||
|
||
*%val{hook_param}*::
|
||
_in `hook` command <command> parameter_ +
|
||
the complete parameter string of the executing hook
|
||
|
||
*%val{modified}*::
|
||
_in buffer, window scope_ +
|
||
`true` if the buffer has modifications not saved, otherwise `false`
|
||
|
||
*%val{object_flags}*::
|
||
_for commands executed from the object menu's `<a-;>` only_ +
|
||
a pipe-separted list of words including `inner` if the user wants
|
||
an inner selection, `to_begin` if the user wants to select to the
|
||
beginning, and `to_end` if the user wants to select to the end
|
||
|
||
*%val{register}*::
|
||
_in `map` command <keys> parameter and `<a-;>` from the object menu_ +
|
||
current register when the mapping was triggered
|
||
|
||
*%val{runtime}*::
|
||
the directory containing the kak support files, which is determined from
|
||
Kakoune's binary location if `$KAKOUNE_RUNTIME` is not set
|
||
|
||
*%val{select_mode}*::
|
||
_for commands executed from the object menu's `<a-;>` only_ +
|
||
`replace` if the new selection should replace the existing, `extend`
|
||
otherwise
|
||
|
||
*%val{selection}*::
|
||
_in window scope_ +
|
||
content of the main selection
|
||
|
||
*%val{selections}*::
|
||
_in window scope_ +
|
||
quoted list of the contents of all selections
|
||
|
||
*%val{selection_desc}*::
|
||
_in window scope_ +
|
||
range of the main selection, represented as `a.b,c.d` where _a_ is the
|
||
anchor line, _b_ is the number of bytes from the start of the line to the
|
||
anchor, _c_ is the cursor line (like `%val{cursor_line}`), _d_ is
|
||
the number of bytes from the start of the line to the cursor (like
|
||
`%val{cursor_column}`), and all are 1-based decimal integers
|
||
|
||
*%val{selections_char_desc}*::
|
||
_in window scope_ +
|
||
unquoted list of the ranges of all selections, in the same format as
|
||
`%val{selection_desc}`, except that the columns are in codepoints rather
|
||
than bytes
|
||
|
||
*%val{selections_display_column_desc}*::
|
||
_in window scope_ +
|
||
unquoted list of the ranges of all selections, in the same format as
|
||
`%val{selection_desc}`, except that the columns are in display columns rather
|
||
than bytes
|
||
|
||
*%val{selections_desc}*::
|
||
_in window scope_ +
|
||
unquoted list of the ranges of all selections, in the same format as
|
||
`%val{selection_desc}`
|
||
|
||
*%val{selection_length}*::
|
||
_in window scope_ +
|
||
length (in codepoints) of the main selection
|
||
|
||
*%val{selections_length}*::
|
||
_in window scope_ +
|
||
unquoted list of the lengths (in codepoints) of the selections
|
||
|
||
*%val{selection_count}*::
|
||
_in window scope_ +
|
||
the number of selections
|
||
|
||
*%val{session}*::
|
||
name of the current session
|
||
|
||
*%val{source}*::
|
||
_in `.kak` file_ +
|
||
path of the file currently getting executed (through the source command)
|
||
|
||
*%val{text}*::
|
||
_in `prompt` command <command> parameter_ +
|
||
the text entered by the user in response to the `prompt` command
|
||
|
||
*%val{timestamp}*::
|
||
_in buffer, window scope_ +
|
||
timestamp of the current buffer, an integer that increments each time the
|
||
buffer is modified, including undoing and redoing previous modifications
|
||
(see also `%val{history_id}`)
|
||
|
||
*%val{uncommitted_modifications}*::
|
||
_in buffer, window scope_ +
|
||
a list of quoted insertions (in the format `+line.column|text`) and
|
||
deletions (`-line.column|text`) not yet saved to the history (e.g. typing
|
||
in insert mode before pressing `<esc>`), where _line_ is the 1-based line
|
||
of the change, _column_ is the 1-based _byte_ of the change start (see
|
||
`%val{cursor_column}`), and _text_ is the content of the insertion or
|
||
deletion (see also `%val{history}`)
|
||
|
||
*%val{user_modes}*::
|
||
unquoted list of user modes.
|
||
|
||
*%val{version}*::
|
||
version of the current Kakoune server (git hash or release name)
|
||
|
||
*%val{window_height}*::
|
||
_in window scope_ +
|
||
height of the current Kakoune window
|
||
|
||
*%val{window_width}*::
|
||
_in window scope_ +
|
||
width of the current Kakoune window
|
||
|
||
*%val{window_range}*::
|
||
_in window scope_ +
|
||
list of coordinates and dimensions of the buffer-space
|
||
available on the current window, in the following format:
|
||
`<coord_y> <coord_x> <height> <width>`
|
||
|
||
Values in the above list that do not mention a context are available
|
||
everywhere.
|
||
|
||
A value described as a "quoted list" will follow the rules of Kakoune string
|
||
quoting (See <<command-parsing#,`:doc command-parsing`>>). An "unquoted list"
|
||
cannot contain any special characters that would require quoting.
|