Home Explore Blog CI



neovim

5th chunk of `runtime/doc/map.txt`
726cbddcf7dc08ff234801d187af16df3b61ee11c0f32e3e0000000100000fa3
 from before executing "f!",
because "x" is evaluated before "f!" is executed.
This can be solved by inserting <Ignore> before the character that is
expression-mapped: >
	nmap ! f!<Ignore>x

Be very careful about side effects!  The expression is evaluated while
obtaining characters, you may very well make the command dysfunctional.
Therefore the following is blocked for <expr> mappings:
- Changing the buffer text |textlock|.
- Editing another buffer.
- The |:normal| command.
- Moving the cursor is allowed, but it is restored afterwards.
- If the cmdline is changed, the old text and cursor position are restored.
If you want the mapping to do any of these let the returned characters do
that, or use a |<Cmd>| mapping instead.

You can use getchar(), it consumes typeahead if there is any. E.g., if you
have these mappings: >
  inoremap <expr> <C-L> nr2char(getchar())
  inoremap <expr> <C-L>x "foo"
If you now type CTRL-L nothing happens yet, Vim needs the next character to
decide what mapping to use.  If you type 'x' the second mapping is used and
"foo" is inserted.  If you type any other key the first mapping is used,
getchar() gets the typed key and returns it.

Here is an example that inserts a list number that increases: >
	let counter = 0
	inoremap <expr> <C-L> ListItem()
	inoremap <expr> <C-R> ListReset()

	func ListItem()
	  let g:counter += 1
	  return g:counter .. '. '
	endfunc

	func ListReset()
	  let g:counter = 0
	  return ''
	endfunc

CTRL-L inserts the next number, CTRL-R resets the count.  CTRL-R returns an
empty string, so that nothing is inserted.

Note that using 0x80 as a single byte before other text does not work, it will
be seen as a special key.

						*<Cmd>* *:map-cmd*
The <Cmd> pseudokey begins a "command mapping", which executes the command
directly without changing modes.  Where you might use ":...<CR>" in the
{rhs} of a mapping, you can instead use "<Cmd>...<CR>".
Example: >
	noremap x <Cmd>echo mode(1)<CR>
<
This is more flexible than `:<C-U>` in Visual and Operator-pending mode, or
`<C-O>:` in Insert mode, because the commands are executed directly in the
current mode, instead of always going to Normal mode.  Visual mode is
preserved, so tricks with |gv| are not needed.  Commands can be invoked
directly in Command-line mode (which would otherwise require timer hacks).
Example of using <Cmd> halfway Insert mode: >
	nnoremap <F3> aText <Cmd>echo mode(1)<CR> Added<Esc>

Unlike <expr> mappings, there are no special restrictions on the <Cmd>
command: it is executed as if an (unrestricted) |autocommand| was invoked
or an async event was processed.

Note:
- Because <Cmd> avoids mode-changes (unlike ":") it does not trigger
  |CmdlineEnter| and |CmdlineLeave| events. This helps performance.
- For the same reason, |keycodes| like <C-R><C-W> are interpreted as plain,
  unmapped keys.
- The command is not echo'ed, no need for <silent>.
- The {rhs} is not subject to abbreviations nor to other mappings, even if the
  mapping is recursive.
- In Visual mode you can use `line('v')` and `col('v')` to get one end of the
  Visual area, the cursor is at the other end.

							*E1255* *E1136*
<Cmd> commands must terminate, that is, they must be followed by <CR> in the
{rhs} of the mapping definition.  |Command-line| mode is never entered.  To use
a literal <CR> in the {rhs}, use |<lt>|.


1.3 MAPPING AND MODES					*:map-modes*
		*mapmode-nvo* *mapmode-n* *mapmode-v* *mapmode-o* *mapmode-t*

There are seven sets of mappings
- For Normal mode: When typing commands.
- For Visual mode: When typing commands while the Visual area is highlighted.
- For Select mode: like Visual mode but typing text replaces the selection.
- For Operator-pending mode: When an operator is pending (after "d", "y", "c",
  etc.).  See below: |omap-info|.
- For Insert mode.  These are also used in Replace mode.
- For Command-line mode: When entering a ":" or "/" command.
- For Terminal mode: When typing in a |:terminal| buffer.

Special case: While typing

Title: Vim Mapping: Considerations for Side Effects, getchar(), and <Cmd> Mappings
Summary
This section discusses potential side effects of expressions in mappings and limitations due to restrictions. It introduces `getchar()` to consume typeahead, allowing dynamic mapping behavior. The `<Cmd>` pseudokey allows executing commands directly in the current mode without changing modes, providing more flexibility than `:<C-U>` or `<C-O>:`. `<Cmd>` mappings are not subject to abbreviations or other mappings and must terminate with `<CR>`. Finally, it outlines the different modes for which mappings can be defined.