= 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 nestable punctuation character (`(`, `[`,
`{`, or `<`), and then all the text up to and including its matching opposite
(`)`, `]`, `}`, or `>`). It doesn't matter which character is used, but
`{}` are most common. For example, the command `echo %val{session}` will
echo the ID of the current Kakoune session.

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. So:

* `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, even if
the expansion contains whitespace or other special characters. 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`

When turned into environment variables, list-type options, `$kak_reg_x`, and
"quoted list" values will be shell-quoted so the shell doesn't get confused
about how many items the list contains. You will need to apply `eval` to get
back the original values. For example, if you want to process the contents
of each selection, you can do something like:

----
eval set -- $kak_selections
while [ $# -gt 0 ]; do
    # ...do a thing with $1...
    shift
done
----

The `eval` command will take the expanded `$kak_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`>>).

== 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 scope_ +
    full path of the file or same as `%val{bufname}` when there’s no
    associated file

*%val{buf_line_count}*::
    _in buffer 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 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_ +
    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_ +
    column of the main cursor (in characters), the fourth component of
    `%val{selection_desc}`

*%val{cursor_char_value}*::
    _in window scope_ +
    unicode value of the codepoint under the main cursor

*%val{cursor_column}*::
    _in window scope_ +
    column of the main cursor (in bytes)

*%val{cursor_line}*::
    _in window scope_ +
    line of the main cursor, the third component of `%val{selection_desc}`

*%val{history_id}*::
    _in buffer 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 scope_ +
    `true` if the buffer has modifications not saved, otherwise `false`

*%val{register}*::
    _in `map` command <keys> parameter_ +
    current register when the mapping was triggered

*%val{runtime}*::
    directory containing the kak support files, determined from Kakoune's
    binary location

*%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 anchor column, _c_ is the cursor
    line (like `%val{cursor_line}`), _d_ is the cursor column (like
    `%val{cursor_char_column}`), and all are 1-based decimal integers

*%val{selections_desc}*::
    _in window scope_ +
    unquoted list of the ranges of all selections, in the same format as
    `%val{selection_desc}`

*%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 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{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

Values in the above list that do not mention a context are available
everywhere. Values that mention "buffer scope" are also available in window
scope.

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.
