Nvim :help pages, generated
from source
using the tree-sitter-vimdoc parser.
CmdAtom.lhs is the high-level user input collected during an action,
including getchar() input. This is signficant: it reflects the semantic
intent. CmdAtom.keys reveals the low-level internal commands that were
produced.lhs) RESOLUTION (keys)changed=false).
x "dl" Translated builtin.
,d "dl" Mapping :nnoremap ,d x.
@q "dl" Macro @q = "x".
<F6> "dlw" Composite :nnoremap <F6> xw:
type='mapping', subatoms "dl" and "w"
concat to the composite keys.
,Dw "dw" Incomplete mapping: ended mid-
operation (:nnoremap ,D d),
captures its continuation ("w").
ds) ":call …<NL>)" "Payload" mapping (e.g. vim-surround
"ds'" reads getchar()).
]q nil Lua mapping.
V<C-E>d "" Unreplayable: viewport-dependent
Visual sequence; lhs is only
a hint/label.keys (mode "n"), or lhs (mode "m") if keys=nil.
local function replay(a)
vim.api.nvim_feedkeys(a.keys or a.lhs, a.keys and 'n' or 'm', false)
endmoved=true).
local last ---@type vim.event.cmdatom.data?
vim.api.nvim_create_autocmd('CmdAtom', {
callback = function(ev)
-- Skip edits, and the "," mapping itself.
local motion = ev.data.moved or ev.match == 'motion'
if motion and not (ev.data.changed or ev.data.lhs == ',') then
last = ev.data
end
end,
})
vim.keymap.set('n', ',', function()
-- CmdAtom is deferred; schedule the replay, in case "," follows a motion.
vim.schedule(function()
if last then
vim.api.nvim_feedkeys(last.keys or last.lhs, last.keys and 'n' or 'm', false)
end
end)
end)
local last ---@type vim.event.cmdatom.data?
local maxseq = {} ---@type table<integer, integer>
vim.api.nvim_create_autocmd('CmdAtom', {
callback = function(ev)
local is_redo_or_undo = ev.data.changed and (ev.data.undoseq or 0) <= (maxseq[ev.buf] or 0)
maxseq[ev.buf] = vim.fn.undotree(ev.buf).seq_last
if ev.data.changed and not is_redo_or_undo and ev.data.lhs ~= '.' then
last = ev.data
end
end,
})
vim.keymap.set('n', '.', function()
-- CmdAtom is deferred; schedule the replay, in case "." follows an edit.
vim.schedule(function()
if last then
vim.api.nvim_feedkeys(last.keys or last.lhs, last.keys and 'n' or 'm', false)
end
end)
end)<Enter> saves it. "<Space>"
without a count replays the macro.
-- Track the last 20 atoms.
local atom_ring = {} ---@type vim.event.cmdatom.data[]
vim.api.nvim_create_autocmd('CmdAtom', {
callback = function(ev)
-- Skip this mapping itself, and cmdwin edits.
if ev.data.lhs ~= ' ' and vim.fn.getcmdwintype() == '' then
atom_ring[#atom_ring + 1] = ev.data
if #atom_ring > 20 then
table.remove(atom_ring, 1)
end
end
end,
})
-- [count]<space> shows a cmdwin where the user can edit/save the last [count] atoms as a "macro".
-- <space> (no count) replays it.
vim.keymap.set('n', '<Space>', function()
local count = vim.v.count
-- CmdAtom is deferred; schedule it so pending events land in the ring first.
vim.schedule(function()
count = math.min(count, #atom_ring)
if count == 0 then -- Replay the saved macro.
for _, step in ipairs(vim.g.atom_macro or {}) do
vim.api.nvim_feedkeys(vim.keycode(step.keys or step.lhs), step.keys and 'n' or 'm', false)
end
return
end
local parts = {}
for i = #atom_ring - count + 1, #atom_ring do
local a = atom_ring[i]
local keys = a.keys or ('%s%s'):format(a.count or '', a.lhs)
local field = a.keys and 'keys' or 'lhs'
parts[#parts + 1] = ('{%s=%q},'):format(field, vim.fn.keytrans(keys))
end
local cmd = ('lua vim.g.atom_macro = { %s }'):format(table.concat(parts, ' '))
-- Draft it on the cmdline; CTRL-F opens the cmdwin to edit it.
vim.api.nvim_feedkeys((':%s%s'):format(cmd, vim.keycode('<C-f>')), 'n', false)
end)
end)
local seen = {} ---@type table<integer, table>
vim.api.nvim_create_autocmd('CmdAtom', {
callback = function(ev)
local seq = ev.data.undoseq
if not seq then
return
end
local s = seen[ev.buf] or {}
seen[ev.buf] = s
-- Note: g- :earlier may cross undo-tree branches, "best effort" in that case.
if s.prev and seq < s.prev and s[seq + 1] then
vim.api.nvim_win_set_cursor(0, s[seq + 1]) -- Undo: first abandoned state.
elseif s.prev and seq > s.prev and s[seq] then
vim.api.nvim_win_set_cursor(0, s[seq]) -- Redo: revisiting a known seq.
elseif ev.data.changed and not s[seq] then
s[seq] = ev.data.pos -- New edit.
end
s.prev = seq
end,
}){pattern} matches.{pattern} does NOT match.:g/^Obsolete/d _Using the underscore after
:d avoids clobbering registers or the clipboard.
This also makes it faster.{pattern}, you can use any other
single byte character, but not an alphabetic character, '\', '"', '|' or '!'.
This is useful if you want to include a '/' in the search pattern or
replacement string.:g/found/v/notfound/{cmd}
This first finds all lines containing "found", but only executes {cmd} when
there is no match for "notfound".:normal command::g/pat/normal {commands}
Make sure that {commands} ends with a whole command, otherwise Vim will wait
for you to type the rest of the command for each match. The screen will not
have been updated, so you don't know what you are doing. See :normal.:g/pat/s//PAT/gThis replaces all occurrences of "pat" with "PAT". The same can be done with:
:%s/pat/PAT/gWhich is two characters shorter!
{0-9a-zA-Z"}
(uppercase to append). The 'q' command is disabled
while executing a register, and it doesn't work inside
a mapping and :normal.{0-9a-z".=*+} [count]
times. Note that register '%' (name of the current
file) and '#' (name of the alternate file) cannot be
used.
The register is executed like a mapping, that means
that the difference between 'wildchar' and 'wildcharm'
applies, and undo might not be synced in the same way.
For "@=" you are prompted to enter an expression. The
result of the expression is then executed.
See also @:.{Visual}@{0-9a-z".=*+} In linewise Visual mode, execute the contents of the
{Visual}@@ register for each selected line.
See visual-repeat, default-mappings.{Visual}Q In linewise Visual mode, repeat the last recorded
register for each selected line.
See visual-repeat, default-mappings.{0-9a-z".=*+} as an
Ex command. First set cursor at line [addr] (default
is current line). When the last line in the register
does not have a <CR> it will be added automatically
when the 'e' flag is present in 'cpoptions'.
For ":@=" the last used expression is used. The
result of evaluating the expression is executed as an
Ex command.
Mappings are not recognized in these commands.
When the line-continuation character (\) is present
at the beginning of a line in a linewise register,
then it is combined with the previous line. This is
useful for yanking and executing parts of a Vim
script.