Files
neovim-config/docs/cheatsheet/curated/motions.json
T
rootiest 6e1c6d081a docs: add generated Vim keymap cheatsheet
Interactive single-file cheatsheet of every built-in key and this
config's live keymaps, generated by docs/cheatsheet/gen_cheatsheet.py
from $VIMRUNTIME/doc/index.txt, a headless dump of the config
(dump.lua) and curated plugin/config notes (curated/*.json).
2026-10-03 23:39:28 -04:00

251 lines
52 KiB
JSON

{
"entries": [
{"k": "i(", "m": ["x", "o"], "d": "Inside (…) parentheses, leaving out whitespace next to the brackets", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "Opening bracket leaves out the whitespace just inside the brackets (<code>di(</code> on <code>( a )</code> gives <code>( )</code>), closing bracket (<code>i)</code>) includes it (<code>di)</code> gives <code>()</code>). Unlike Vim's built-in, it also works when the cursor is <em>before</em> the pair: mini.ai takes the pair covering the cursor, else the next one (first on the cursor line, then within 50 lines)."},
{"k": "i)", "m": ["x", "o"], "d": "Inside (…) parentheses, including whitespace next to the brackets", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "a(", "m": ["x", "o"], "d": "Around (…) including the parentheses (same as a))", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "<code>2a(</code>, or typing <code>a(</code> again in Visual mode, selects the next enclosing pair."},
{"k": "a)", "m": ["x", "o"], "d": "Around (…) including the parentheses (same as a()", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i[", "m": ["x", "o"], "d": "Inside […] brackets, leaving out whitespace next to the brackets", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i]", "m": ["x", "o"], "d": "Inside […] brackets, including whitespace next to the brackets", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "a[", "m": ["x", "o"], "d": "Around […] including the brackets (same as a])", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i{", "m": ["x", "o"], "d": "Inside {…} braces, leaving out whitespace next to the braces", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i}", "m": ["x", "o"], "d": "Inside {…} braces, including whitespace next to the braces", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "a{", "m": ["x", "o"], "d": "Around {…} including the braces (same as a})", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i<", "m": ["x", "o"], "d": "Inside <…> angle brackets, leaving out whitespace next to them", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i>", "m": ["x", "o"], "d": "Inside <…> angle brackets, including whitespace next to them", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "a<", "m": ["x", "o"], "d": "Around <…> including the angle brackets (same as a>)", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "ib", "m": ["x", "o"], "d": "Inside the nearest (), [] or {} block", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "e": 1, "n": "Vim's built-in <code>ib</code> only knows <code>()</code>; mini.ai's <code>b</code> is an alias for <code>)</code>, <code>]</code> and <code>}</code> (edge whitespace included) and searches cover-or-next."},
{"k": "ab", "m": ["x", "o"], "d": "Around the nearest (), [] or {} block, brackets included", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i\"", "m": ["x", "o"], "d": "Inside \"…\" double quotes", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "mini.ai matches balanced quote pairs and searches 50 lines (cover, else next). Built-in <code>i\"</code> only looked at the cursor line."},
{"k": "a\"", "m": ["x", "o"], "d": "Around \"…\" including the quotes, without trailing whitespace", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "Differs from Vim's built-in <code>a\"</code>, which also takes the whitespace after the closing quote."},
{"k": "i'", "m": ["x", "o"], "d": "Inside '…' single quotes", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "a'", "m": ["x", "o"], "d": "Around '…' including the quotes, without trailing whitespace", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i`", "m": ["x", "o"], "d": "Inside `…` backticks", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "a`", "m": ["x", "o"], "d": "Around `…` including the backticks, without trailing whitespace", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "iq", "m": ["x", "o"], "d": "Inside the nearest quotes of any kind: '…', \"…\" or `…`", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "sl": "in quote"},
{"k": "aq", "m": ["x", "o"], "d": "Around the nearest quotes of any kind, quotes included", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "if", "m": ["x", "o"], "d": "Inside a function call: the arguments between its parentheses", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "e": 1, "sl": "in call", "n": "A function call is a name made of letters, digits, <code>_</code> or <code>.</code> followed by balanced <code>()</code>, e.g. <code>vim.fn.getline(1)</code>. Pattern-based, so a <code>)</code> inside a string can confuse it."},
{"k": "af", "m": ["x", "o"], "d": "Around a function call, name and parentheses included", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "ia", "m": ["x", "o"], "d": "Inside an argument: just the argument, no comma or edge whitespace", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "Arguments live inside <code>()</code>, <code>[]</code> or <code>{}</code>, separated by commas; commas inside nested brackets or <code>\"…\"</code>/<code>'…'</code> strings are ignored (not inside <code>`…`</code>)."},
{"k": "aa", "m": ["x", "o"], "d": "Around an argument plus one adjacent comma, so daa leaves a valid list", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "e": 1, "sl": "arg", "n": "First argument takes the comma on its right; middle and last arguments take the comma on their left. On the first argument the following space stays: <code>daa</code> turns <code>f(a, b)</code> into <code>f( b)</code>."},
{"k": "it", "m": ["x", "o"], "d": "Inside a tag pair: the content between <x> and </x>", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "Replaces Vim's built-in <code>it</code>/<code>at</code> with a pattern match, so same-name nested tags (<code>&lt;a&gt;&lt;a&gt;&lt;/a&gt;&lt;/a&gt;</code>) can mis-match."},
{"k": "at", "m": ["x", "o"], "d": "Around a tag pair, opening and closing tags included", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i?", "m": ["x", "o"], "d": "Inside custom edges: prompts for the left and right strings", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "Edges are literal strings, not patterns. Dot-repeat reuses the answers without asking again."},
{"k": "a?", "m": ["x", "o"], "d": "Around custom edges (prompted), edges included", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "ig", "m": ["x", "o"], "d": "Entire buffer (custom textobject from lua/plugins.lua)", "s": "config", "cat": "Text object", "e": 1, "sl": "buffer", "n": "Defined in <code>Config.plugins.mini_ai.custom_textobjects.g</code>: charwise from line 1, column 1 to the end of the last line. <code>ig</code> and <code>ag</code> are identical. Try <code>yig</code>, <code>=ig</code>, <code>cig</code>, <code>vig</code>."},
{"k": "ag", "m": ["x", "o"], "d": "Entire buffer (same as ig)", "s": "config", "cat": "Text object"},
{"k": "i{punct}", "m": ["x", "o"], "d": "Between two {punct} characters, e.g. i_ i, i* i/ i- i<Space>", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "Any id that is not a Latin letter and not defined above works as a separator, e.g. <code>ci_</code> in <code>foo_bar_baz</code>. Digits count too."},
{"k": "a{punct}", "m": ["x", "o"], "d": "Like i{punct} plus the run of separators on its right", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "i{letter}", "m": ["x", "o"], "d": "Letters mini.ai doesn't define (w W s p B) fall back to Vim's text objects", "s": "mini.ai", "cat": "Text object", "n": "So <code>iw</code>, <code>aW</code>, <code>is</code>, <code>ap</code>, <code>iB</code>, <code>aB</code> behave exactly as in stock Vim."},
{"k": "iN{id}", "m": ["x", "o"], "d": "Inside the next {id} textobject, e.g. ciN( diN\" viNq", "s": "mini.ai", "cat": "Text object", "h": "MiniAi.config", "e": 1, "sl": "in next", "n": "Uses search method <code>next</code>: always the one after the cursor, even if the cursor is inside one."},
{"k": "aN{id}", "m": ["x", "o"], "d": "Around the next {id} textobject, e.g. daN) yaNf", "s": "mini.ai", "cat": "Text object", "h": "MiniAi.config"},
{"k": "il{id}", "m": ["x", "o"], "d": "Inside the previous (last) {id} textobject, e.g. cil\"", "s": "mini.ai", "cat": "Text object", "h": "MiniAi.config"},
{"k": "al{id}", "m": ["x", "o"], "d": "Around the previous (last) {id} textobject", "s": "mini.ai", "cat": "Text object", "h": "MiniAi.config"},
{"k": "[count]i{id}", "m": ["x", "o"], "d": "The [count]-th enclosing textobject, e.g. d2i) empties the outer parens", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects"},
{"k": "{Visual}i{id}", "m": ["x"], "d": "Repeat i{id}/a{id} while selected to grow to the next enclosing one", "s": "mini.ai", "cat": "Text object", "h": "MiniAi-builtin-textobjects", "n": "E.g. <code>vi)</code> then <code>i)</code> again, or <code>va\"a\"</code>. The current selection is the reference, so the result never equals it."},
{"k": "g[{id}", "m": ["n", "x", "o"], "d": "Move to the left edge of the a{id} textobject, e.g. g[( g[f g[\"", "s": "mini.ai", "cat": "Motion", "h": "MiniAi.move_cursor()"},
{"k": "g]{id}", "m": ["n", "x", "o"], "d": "Move to the right edge of the a{id} textobject, e.g. g]) g]t", "s": "mini.ai", "cat": "Motion", "h": "MiniAi.move_cursor()"},
{"k": "sa{motion}{char}", "m": ["n"], "d": "Add surrounding {char} around {motion} or textobject", "s": "mini.surround", "cat": "Surround", "h": "MiniSurround-builtin-surroundings", "e": 1, "sl": "surround", "n": "<code>sa</code> is an operator, so any motion or text object works, including mini.ai ones (<code>saif\"</code>, <code>saaa]</code>). Dot-repeatable."},
{"k": "saiw)", "m": ["n"], "d": "Surround the word with parentheses: (word)", "s": "mini.surround", "cat": "Surround"},
{"k": "saiw(", "m": ["n"], "d": "Surround the word with padded parentheses: ( word )", "s": "mini.surround", "cat": "Surround"},
{"k": "saiw\"", "m": ["n"], "d": "Surround the word with double quotes", "s": "mini.surround", "cat": "Surround"},
{"k": "saiwf", "m": ["n"], "d": "Wrap the word in a function call; prompts for the name: name(word)", "s": "mini.surround", "cat": "Surround"},
{"k": "saiwt", "m": ["n"], "d": "Wrap the word in a tag; prompts for it, e.g. div class=\"x\"", "s": "mini.surround", "cat": "Surround", "n": "The prompt takes the tag name plus attributes; the closing tag uses only the name."},
{"k": "saiw?", "m": ["n"], "d": "Surround the word with custom text (prompts for left and right)", "s": "mini.surround", "cat": "Surround"},
{"k": "sa$\"", "m": ["n"], "d": "Quote from the cursor to the end of the line", "s": "mini.surround", "cat": "Surround"},
{"k": "[count]sa{motion}{char}", "m": ["n"], "d": "Repeat the surrounding [count] times, e.g. 2saiw) gives ((word))", "s": "mini.surround", "cat": "Surround", "h": "MiniSurround-count-with-actions"},
{"k": "{Visual}sa{char}", "m": ["x"], "d": "Surround the selection with {char}", "s": "mini.surround", "cat": "Surround"},
{"k": "sd{char}", "m": ["n"], "d": "Delete the surrounding {char} around the cursor", "s": "mini.surround", "cat": "Surround", "h": "MiniSurround-builtin-surroundings", "e": 1, "sl": "del surr", "n": "Search method is <code>cover</code> (it must enclose the cursor) within 20 lines. Add <code>n</code>/<code>l</code> after <code>sd</code> to target the next/previous one instead."},
{"k": "sd'", "m": ["n"], "d": "Delete the surrounding single quotes", "s": "mini.surround", "cat": "Surround"},
{"k": "sdq", "m": ["n"], "d": "Delete the nearest surrounding quotes of any kind", "s": "mini.surround", "cat": "Surround"},
{"k": "sdb", "m": ["n"], "d": "Delete the nearest surrounding (), [] or {}", "s": "mini.surround", "cat": "Surround"},
{"k": "sdf", "m": ["n"], "d": "Remove a function call but keep its arguments: f(x) → x", "s": "mini.surround", "cat": "Surround"},
{"k": "sdt", "m": ["n"], "d": "Remove the surrounding tag pair, keeping the content", "s": "mini.surround", "cat": "Surround"},
{"k": "sd(", "m": ["n"], "d": "Delete parentheses and the whitespace just inside them", "s": "mini.surround", "cat": "Surround"},
{"k": "sr{old}{new}", "m": ["n"], "d": "Replace surrounding {old} with {new}", "s": "mini.surround", "cat": "Surround", "h": "MiniSurround-builtin-surroundings", "e": 1, "sl": "repl surr"},
{"k": "sr)]", "m": ["n"], "d": "Replace (…) with […]", "s": "mini.surround", "cat": "Surround"},
{"k": "sr'\"", "m": ["n"], "d": "Replace single quotes with double quotes", "s": "mini.surround", "cat": "Surround"},
{"k": "srtt", "m": ["n"], "d": "Change the surrounding tag (prompts for the new one)", "s": "mini.surround", "cat": "Surround"},
{"k": "sr)tdiv<CR>", "m": ["n"], "d": "Replace parentheses with a <div> tag pair", "s": "mini.surround", "cat": "Surround"},
{"k": "sf{char}", "m": ["n", "x", "o"], "d": "Move the cursor to the right part of surrounding {char}", "s": "mini.surround", "cat": "Surround"},
{"k": "sF{char}", "m": ["n", "x", "o"], "d": "Move the cursor to the left part of surrounding {char}", "s": "mini.surround", "cat": "Surround"},
{"k": "sh{char}", "m": ["n"], "d": "Flash-highlight the surrounding {char} for 500 ms", "s": "mini.surround", "cat": "Surround"},
{"k": "sdn{char}", "m": ["n"], "d": "Delete the next {char} surrounding (after the cursor)", "s": "mini.surround", "cat": "Surround", "n": "The <code>n</code> (next) and <code>l</code> (last/previous) suffixes work after <code>sd</code>, <code>sr</code>, <code>sf</code>, <code>sF</code> and <code>sh</code>: <code>srn)]</code>, <code>sfl\"</code>, <code>shnt</code>."},
{"k": "sdl{char}", "m": ["n"], "d": "Delete the previous (last) {char} surrounding", "s": "mini.surround", "cat": "Surround"},
{"k": "[count]sd{char}", "m": ["n"], "d": "Act on the [count]-th enclosing surrounding: 2sd) on (a(b(c)b)a) gives (ab(c)ba)", "s": "mini.surround", "cat": "Surround", "h": "MiniSurround-count-with-actions"},
{"k": "(", "m": ["n", "x"], "d": "Surround id: find () and drop inner spaces; add pads with spaces: ( x )", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)", "n": "Same for <code>[</code>, <code>{</code>, <code>&lt;</code>."},
{"k": ")", "m": ["n", "x"], "d": "Surround id: () with no padding, inner spaces kept", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)", "n": "Same for <code>]</code>, <code>}</code>, <code>&gt;</code>."},
{"k": "b", "m": ["n", "x"], "d": "Surround id: finds any of (), [], {}; adds ()", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)"},
{"k": "q", "m": ["n", "x"], "d": "Surround id: finds any quote ' \" `; adds \"…\"", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)", "n": "Not balanced, unlike mini.ai's <code>q</code>: with the cursor on <code>x</code> in <code>\"a\" x \"b\"</code>, <code>sdq</code> strips the quotes around <code>\" x \"</code>."},
{"k": "t", "m": ["n", "x"], "d": "Surround id: finds a same-name tag pair; when adding, prompts for the tag", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)"},
{"k": "f", "m": ["n", "x"], "d": "Surround id: finds name(…); when adding, prompts for the function name", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)"},
{"k": "?", "m": ["n", "x"], "d": "Surround id: interactive, prompts for left and right parts", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)"},
{"k": "{other}", "m": ["n", "x"], "d": "Surround id: any other char surrounds with itself, e.g. * _ | $", "s": "mini.surround", "cat": "Surround", "ctx": "Surround id (after sa/sd/sr/sf/sh)"},
{"k": "\\(", "m": ["i"], "d": "No auto-pair right after a backslash: \\( types only (", "s": "config", "cat": "Pairs", "n": "Applies to every opener and quote (lua/smart_pairs.lua <code>should_pair</code>)."},
{"k": "({text}", "m": ["i"], "d": "Opener before text types only the opener (wrapping existing text)", "s": "config", "cat": "Pairs", "e": 1, "n": "smart_pairs only inserts the pair when nothing but whitespace follows the cursor, or the next char is a closing <code>)</code> <code>]</code> <code>}</code>. Also blocks pairing before a quote or comma, e.g. typing <code>(</code> inside an empty <code>\"\"</code>."},
{"k": "don't", "m": ["i"], "d": "A quote right after a letter or digit is typed alone (apostrophes, closing quotes)", "s": "config", "cat": "Pairs"},
{"k": "\"\"\"", "m": ["i"], "d": "A quote right after the same quote is typed alone, so \"\"\" docstrings work", "s": "config", "cat": "Pairs"},
{"k": "```", "m": ["i"], "d": "On a blank line: create a fenced code block pair, cursor after the opener", "s": "config", "cat": "Pairs", "ctx": "Markdown buffers", "e": 1, "n": "Type <code>`</code> three times: the first pairs to <code>``</code>, the second steps over, the third turns the line into <code>```</code> with a twin <code>```</code> below. Only when the next line is blank, the buffer ends, or the next line closes the block you're in. Type the language name right away."},
{"k": "````", "m": ["i"], "d": "Each extra ` lengthens both fences while the closer is untouched", "s": "config", "cat": "Pairs", "ctx": "Markdown buffers"},
{"k": "~~~", "m": ["i"], "d": "Tilde fences work the same way (a lone ~ is never paired)", "s": "config", "cat": "Pairs", "ctx": "Markdown buffers"},
{"k": "```", "m": ["i"], "d": "Inside a code block, a fence that can't close it (shorter, or ~ vs `) pairs as nested", "s": "config", "cat": "Pairs", "ctx": "Inside a Markdown code block", "n": "If the new run is long enough to close the enclosing block, it is not paired; growing a nested pair to that length collapses it into the block's closer."},
{"k": "<BS>", "m": ["i"], "d": "At the end of an untouched fence pair: shrink both; below 3 the closer goes", "s": "config", "cat": "Pairs", "ctx": "Markdown buffers"},
{"k": "<CR>", "m": ["i"], "d": "Between (), [] or {}: put the closer on its own line, cursor between", "s": "mini.pairs", "cat": "Pairs", "n": "Quotes are registered with <code>cr = false</code>, so <kbd>Enter</kbd> between <code>\"\"</code> is a plain newline."},
{"k": "f", "m": ["n", "x", "o"], "d": "After f/F: next match in that motion's direction (no new {char})", "s": "flash", "cat": "Motion", "ctx": "Right after f/F/t/T (highlights visible)", "n": "Flash's clever-f style <code>char_actions</code>: the lowercase motion key is <em>next</em>, the uppercase one <em>prev</em>. After <code>Fx</code> that means <kbd>f</kbd> keeps going left and <kbd>F</kbd> goes right. Ends once the highlights go away (cursor moved by something else, <kbd>Esc</kbd>, Insert mode, leaving the buffer)."},
{"k": "F", "m": ["n", "x", "o"], "d": "After f/F: match in the opposite direction (no new {char})", "s": "flash", "cat": "Motion", "ctx": "Right after f/F/t/T (highlights visible)"},
{"k": "t", "m": ["n", "x", "o"], "d": "After t/T: next match in that motion's direction (no new {char})", "s": "flash", "cat": "Motion", "ctx": "Right after f/F/t/T (highlights visible)"},
{"k": "T", "m": ["n", "x", "o"], "d": "After t/T: match in the opposite direction (no new {char})", "s": "flash", "cat": "Motion", "ctx": "Right after f/F/t/T (highlights visible)"},
{"k": "<Esc>", "m": ["n", "x"], "d": "Clear the Flash f/t highlights", "s": "flash", "cat": "Motion", "ctx": "Right after f/F/t/T (highlights visible)"},
{"k": "[count]f{char}", "m": ["n", "x", "o"], "d": "Jump to the [count]-th {char} on the line (also with F t T ; ,)", "s": "flash", "cat": "Motion"},
{"k": "s", "m": ["n"], "d": "Flash: label every visible result; type a label to move the selection there", "s": "snacks", "cat": "Find & pick", "ctx": "Snacks picker", "n": "Picker input window, Normal mode (<code>picker.win.input.keys</code> in lua/plugins.lua). Runs <code>flash.jump</code> with pattern <code>^</code> restricted to the <code>snacks_picker_list</code> window; picking a label moves the list cursor, it does not confirm."},
{"k": "<M-s>", "m": ["n", "i"], "d": "Flash: label every visible result; type a label to move the selection there", "s": "snacks", "cat": "Find & pick", "ctx": "Snacks picker"},
{"k": "{char1}{char2}", "m": ["n", "x", "o"], "d": "Type the first two chars of the target; labels preview after the first", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap-usage", "n": "If the closest match is unlabeled you are already there (autojump) and the remaining labels are \"safe\" keys you would not type next (<code>sfnut/SFNLHMUGTZ?</code>); any other key just runs as a normal command. Case-sensitive here ('ignorecase' is off). In Operator-pending mode with several matches you always pick a label."},
{"k": "{label}", "m": ["n", "x", "o"], "d": "Jump to the target showing that label", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump"},
{"k": "<Space>", "m": ["n", "x", "o"], "d": "After the 2 chars: show the next group of labels (too many matches)", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap.opts.keys", "n": "Labels of later groups show dimmed/concealed until you switch to them."},
{"k": "<BS>", "m": ["n", "x", "o"], "d": "Back to the previous group of labels", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap.opts.keys"},
{"k": "<CR>", "m": ["n", "x", "o"], "d": "As the first key: repeat the previous Leap search (so <CR><CR> re-leaps)", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap-repeat"},
{"k": "{char}<CR>", "m": ["n", "x", "o"], "d": "Jump straight to the closest {char} (one-char shortcut)", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap-shortcut"},
{"k": "{char}<Space>", "m": ["n", "x", "o"], "d": "Target {char} followed by a space, a tab or the end of the line", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap-till-eol"},
{"k": "<Space><Space>", "m": ["n", "x", "o"], "d": "Target an empty line or an end-of-line position", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap-to-eol"},
{"k": "(", "m": ["n", "x", "o"], "d": "Equivalence classes: ( [ { match each other, ) ] } too, and ' \" ` too", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap.opts.equivalence_classes", "n": "Space also stands for Tab and end of line. Typing any member matches the whole class."},
{"k": "<Esc>", "m": ["n", "x", "o"], "d": "Cancel the Leap", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump"},
{"k": "gcip", "m": ["n"], "d": "Toggle comment on the current paragraph", "s": "neovim", "cat": "Comment", "h": "gc-default"},
{"k": "[count]gcc", "m": ["n"], "d": "Toggle comment on [count] lines from the cursor", "s": "neovim", "cat": "Comment", "h": "gcc-default"},
{"k": "gcgc", "m": ["n"], "d": "Uncomment the whole comment block under the cursor", "s": "neovim", "cat": "Comment", "h": "o_gc-default"},
{"k": "dgc", "m": ["n"], "d": "Delete the comment block under the cursor", "s": "neovim", "cat": "Comment", "h": "o_gc-default"},
{"k": "a%", "m": ["o"], "d": "In Operator-pending mode a% is mini.ai's 'between % signs', not matchit's", "s": "mini.ai", "cat": "Text object", "n": "matchit only maps <code>a%</code> in Visual mode, so <code>da%</code> goes through mini.ai's <code>a</code> with <code>%</code> as a separator id. For matchit's group use <code>va%</code>, which stops on the first character of the closing word (<code>e</code> of <code>end</code>)."}
],
"map_desc": [
{"s": "flash", "m": "*", "k": "f", "d": "Flash: jump to the next {char} on this line", "cat": "Motion", "e": 1, "sl": "find→", "n": "flash.nvim char mode (lua/plugins.lua: <code>modes.char.multi_line = false</code>): never leaves the cursor line or wraps, no jump labels. All matches on the line light up and the window is dimmed until the cursor moves. Press <kbd>f</kbd> again for the next match. Each jump sets the <code>'</code> mark, so <kbd>`</kbd><kbd>`</kbd> jumps back (<kbd>Ctrl-O</kbd> can't: the jumplist keeps one entry per line). Inclusive with operators, like Vim."},
{"s": "flash", "m": "*", "k": "F", "d": "Flash: jump to the previous {char} on this line", "cat": "Motion", "e": 1, "sl": "←find", "n": "Right after <code>Fx</code>, <kbd>F</kbd> moves to the <em>right</em> and <kbd>f</kbd> keeps going left (flash's clever-f mapping: lowercase = next in the motion's direction)."},
{"s": "flash", "m": "*", "k": "t", "d": "Flash: jump till before the next {char} on this line", "cat": "Motion", "e": 1, "sl": "till→", "n": "Repeat with <kbd>t</kbd> (next) or <kbd>T</kbd> (opposite) while highlighted."},
{"s": "flash", "m": "*", "k": "T", "d": "Flash: jump till after the previous {char} on this line", "cat": "Motion", "sl": "←till"},
{"s": "flash", "m": "*", "k": ";", "d": "Flash: repeat the last f/F/t/T in the same direction", "cat": "Motion", "e": 1, "sl": "rep ft", "n": "Works any time later (not only while highlighted). After a yank (<code>yf.</code>) flash auto-hides its highlights."},
{"s": "flash", "m": "*", "k": ",", "d": "Flash: repeat the last f/F/t/T in the opposite direction", "cat": "Motion", "sl": "ft rep←"},
{"s": "config", "m": "*", "k": "<CR>", "d": "Leap: jump anywhere in this window (2 chars, then a label)", "cat": "Motion", "e": 1, "sl": "leap", "force": true, "n": "<code>&lt;Plug&gt;(leap)</code>, lua/keymaps.lua. Bidirectional in the current window, closest targets first; inclusive with operators (<code>d&lt;CR&gt;ab</code>). Replaces Vim's <kbd>Enter</kbd> = <em>next line</em> (use <kbd>+</kbd> or <kbd>j</kbd>). Being a global Normal map it also takes over <kbd>Enter</kbd> in the quickfix/location list and the command-line window. No traversal and [count] is ignored (bidirectional mode). Dot-repeat of Leap operations needs vim-repeat, which isn't installed."},
{"s": "config", "m": "n", "k": "S", "d": "Leap from window: jump to a spot in another window (2 chars + label)", "cat": "Motion", "e": 1, "sl": "leap win", "force": true, "n": "<code>&lt;Plug&gt;(leap-from-window)</code>, Normal mode only: targets every other focusable, non-floating window in the tab and moves you there. Replaces Vim's <kbd>S</kbd> (use <kbd>cc</kbd>). Visual <kbd>S</kbd> is unchanged."},
{"s": "mini.ai", "m": "*", "k": "a", "d": "Around textobject: a + id (mini.ai), e.g. af aa aq ab a)", "cat": "Text object", "e": 1, "sl": "around", "force": true, "n": "Waits for one id character (reminder after 1 s). Search method <code>cover_or_next</code> within <code>n_lines = 50</code>: the textobject covering the cursor, else the next one (first on the cursor line). Unknown letters fall back to Vim's built-ins (<code>aw</code>, <code>ap</code>, …)."},
{"s": "mini.ai", "m": "*", "k": "i", "d": "Inside textobject: i + id (mini.ai), e.g. if ia iq ib i) ig", "cat": "Text object", "e": 1, "sl": "inside", "force": true},
{"s": "mini.ai", "m": "*", "k": "aN", "d": "Around the next textobject: aN + id, e.g. daN)", "cat": "Text object", "sl": "a next"},
{"s": "mini.ai", "m": "*", "k": "iN", "d": "Inside the next textobject: iN + id, e.g. ciN\"", "cat": "Text object", "sl": "i next"},
{"s": "mini.ai", "m": "*", "k": "al", "d": "Around the previous (last) textobject: al + id", "cat": "Text object", "sl": "a last"},
{"s": "mini.ai", "m": "*", "k": "il", "d": "Inside the previous (last) textobject: il + id", "cat": "Text object", "sl": "i last"},
{"s": "mini.ai", "m": "*", "k": "g[", "d": "Move to the left edge of an a{id} textobject, e.g. g[(", "cat": "Motion", "sl": "obj start", "force": true},
{"s": "mini.ai", "m": "*", "k": "g]", "d": "Move to the right edge of an a{id} textobject, e.g. g])", "cat": "Motion", "sl": "obj end", "force": true, "n": "Replaces Vim's <code>g]</code> (<code>:tselect</code> on the tag under the cursor); use <code>:tselect</code> or <code>g&lt;C-]&gt;</code> instead."},
{"s": "mini.surround", "m": "*", "k": "s", "d": "Disabled by mini.surround (it's the sa/sd/sr/sf/sh prefix); use cl", "cat": "Surround", "sl": "surr…", "force": true, "n": "mini.surround maps a bare <code>s</code> to <code>&lt;Nop&gt;</code> in Normal, Visual and Operator-pending mode. Built-in <code>s</code> = <code>cl</code>; Visual <code>s</code> = <code>c</code>."},
{"s": "mini.surround", "m": "n", "k": "sa", "d": "Add surrounding: sa{motion}{char}, e.g. saiw)", "cat": "Surround", "sl": "surr add", "force": true},
{"s": "mini.surround", "m": "x", "k": "sa", "d": "Add surrounding to the selection: sa{char}", "cat": "Surround", "sl": "surr add", "force": true},
{"s": "mini.surround", "m": "n", "k": "sd", "d": "Delete surrounding: sd{char}, e.g. sd\" sdf sdt", "cat": "Surround", "sl": "surr del", "force": true},
{"s": "mini.surround", "m": "n", "k": "sdn", "d": "Delete the next surrounding: sdn{char}", "cat": "Surround", "sl": "del next"},
{"s": "mini.surround", "m": "n", "k": "sdl", "d": "Delete the previous surrounding: sdl{char}", "cat": "Surround", "sl": "del prev"},
{"s": "mini.surround", "m": "n", "k": "sr", "d": "Replace surrounding: sr{old}{new}, e.g. sr)] sr'\"", "cat": "Surround", "sl": "surr repl", "force": true},
{"s": "mini.surround", "m": "n", "k": "srn", "d": "Replace the next surrounding: srn{old}{new}", "cat": "Surround", "sl": "repl next"},
{"s": "mini.surround", "m": "n", "k": "srl", "d": "Replace the previous surrounding: srl{old}{new}", "cat": "Surround", "sl": "repl prev"},
{"s": "mini.surround", "m": "*", "k": "sf", "d": "Find surrounding: move to its right part, sf{char}", "cat": "Surround", "sl": "surr →", "force": true},
{"s": "mini.surround", "m": "*", "k": "sfn", "d": "Find the next surrounding's right part: sfn{char}", "cat": "Surround", "sl": "next →"},
{"s": "mini.surround", "m": "*", "k": "sfl", "d": "Find the previous surrounding's right part: sfl{char}", "cat": "Surround", "sl": "prev →"},
{"s": "mini.surround", "m": "*", "k": "sF", "d": "Find surrounding: move to its left part, sF{char}", "cat": "Surround", "sl": "← surr", "force": true},
{"s": "mini.surround", "m": "*", "k": "sFn", "d": "Find the next surrounding's left part: sFn{char}", "cat": "Surround", "sl": "← next"},
{"s": "mini.surround", "m": "*", "k": "sFl", "d": "Find the previous surrounding's left part: sFl{char}", "cat": "Surround", "sl": "← prev"},
{"s": "mini.surround", "m": "n", "k": "sh", "d": "Highlight surrounding for 500 ms: sh{char}", "cat": "Surround", "sl": "surr hl", "force": true},
{"s": "mini.surround", "m": "n", "k": "shn", "d": "Highlight the next surrounding: shn{char}", "cat": "Surround", "sl": "hl next"},
{"s": "mini.surround", "m": "n", "k": "shl", "d": "Highlight the previous surrounding: shl{char}", "cat": "Surround", "sl": "hl prev"},
{"s": "config", "m": "i", "k": "(", "d": "Smart pair (): only if the rest of the line is blank or starts with ) ] }", "cat": "Pairs", "e": 1, "sl": "( )", "force": true, "n": "lua/smart_pairs.lua gates mini.pairs: never after <code>\\</code>; otherwise types just <code>(</code>. Disable all pairing with <code>vim.g.minipairs_disable</code> or <code>vim.b.minipairs_disable</code>."},
{"s": "config", "m": "i", "k": "[", "d": "Smart pair []: only if the rest of the line is blank or starts with ) ] }", "cat": "Pairs", "sl": "[ ]", "force": true},
{"s": "config", "m": "i", "k": "{", "d": "Smart pair {}: only if the rest of the line is blank or starts with ) ] }", "cat": "Pairs", "sl": "{ }", "force": true},
{"s": "config", "m": "i", "k": "\"", "d": "Smart quote: step over a \" right after the cursor, else pair if allowed", "cat": "Pairs", "sl": "\" \"", "force": true, "n": "Pairs only when the rest of the line is blank or starts with <code>)</code> <code>]</code> <code>}</code>, and not after a letter, digit, backslash or another <code>\"</code>."},
{"s": "config", "m": "i", "k": "'", "d": "Smart quote: step over a ' right after the cursor, else pair if allowed", "cat": "Pairs", "sl": "' '", "force": true, "n": "Never pairs after a letter or digit, so <code>don't</code> and <code>it's</code> type normally."},
{"s": "config", "m": "i", "k": "`", "d": "Smart backtick: step over a ` right after the cursor, else pair if allowed", "cat": "Pairs", "sl": "` `", "force": true},
{"s": "config", "m": "i", "k": "`", "ctx": "markdown buffers", "d": "Markdown backtick: the 3rd ` on a blank line opens a ``` fence pair", "cat": "Pairs", "sl": "```", "force": true, "n": "More backticks lengthen both fences; otherwise behaves like the smart backtick pair."},
{"s": "config", "m": "i", "k": "~", "ctx": "markdown buffers", "d": "Markdown tilde: the 3rd ~ on a blank line opens a ~~~ fence pair", "cat": "Pairs", "sl": "~~~", "force": true},
{"s": "config", "m": "i", "k": "<BS>", "ctx": "markdown buffers", "d": "Markdown backspace: shrink an untouched fence pair, else mini.pairs <BS>", "cat": "Pairs", "sl": "fence ⌫", "force": true},
{"s": "mini.pairs", "m": "i", "k": ")", "d": "Close (): step over a ) right after the cursor, else type it", "cat": "Pairs", "sl": ")", "force": true},
{"s": "mini.pairs", "m": "i", "k": "]", "d": "Close []: step over a ] right after the cursor, else type it", "cat": "Pairs", "sl": "]", "force": true},
{"s": "mini.pairs", "m": "i", "k": "}", "d": "Close {}: step over a } right after the cursor, else type it", "cat": "Pairs", "sl": "}", "force": true},
{"s": "mini.pairs", "m": "i", "k": "<BS>", "d": "Backspace; inside an empty pair (), [], {}, \"\", '', `` delete both", "cat": "Pairs", "sl": "⌫ pair", "force": true},
{"s": "mini.pairs", "m": "i", "k": "<CR>", "d": "Newline; between (), [] or {} put the closer on its own line", "cat": "Pairs", "sl": "⏎ pair", "force": true},
{"s": "neovim", "m": "n", "k": "gc", "d": "Toggle comment over {motion}, e.g. gcip gcj gcap", "cat": "Comment", "e": 1, "sl": "comment", "force": true, "n": "Neovim's built-in commenting, uses <code>'commentstring'</code> (treesitter-aware for injected languages)."},
{"s": "neovim", "m": "x", "k": "gc", "d": "Toggle comment on the selected lines", "cat": "Comment", "sl": "comment", "force": true},
{"s": "neovim", "m": "n", "k": "gcc", "d": "Toggle comment on the current line ([count] lines)", "cat": "Comment", "e": 1, "sl": "comment ln", "force": true},
{"s": "neovim", "m": "o", "k": "gc", "d": "Comment block textobject: contiguous commented lines (gcgc, dgc)", "cat": "Comment", "sl": "cmt obj", "force": true},
{"s": "neovim", "m": "x", "k": "]n", "d": "Select the next treesitter node (replaces the selection)", "cat": "Visual", "sl": "node→", "force": true, "n": "Neovim 0.12 incremental selection. Its <code>an</code>/<code>in</code> (parent/child) are shadowed by mini.ai here."},
{"s": "neovim", "m": "x", "k": "[n", "d": "Select the previous treesitter node (replaces the selection)", "cat": "Visual", "sl": "←node", "force": true},
{"s": "neovim", "m": "x", "k": "]N", "d": "Extend the selection over the next treesitter node", "cat": "Visual", "sl": "node+→", "force": true},
{"s": "neovim", "m": "x", "k": "[N", "d": "Extend the selection over the previous treesitter node", "cat": "Visual", "sl": "←node+", "force": true},
{"s": "matchit", "m": "*", "k": "%", "d": "Jump to the matching bracket or keyword (if/else/end, tags…)", "cat": "Motion", "e": 1, "sl": "match", "force": true, "n": "matchit extends <code>%</code> with <code>b:match_words</code>: cycles forward through groups like <code>if</code> → <code>else</code> → <code>end</code>."},
{"s": "matchit", "m": "*", "k": "g%", "d": "Cycle backwards through matching keywords", "cat": "Motion", "sl": "match←", "force": true},
{"s": "matchit", "m": "*", "k": "[%", "d": "Go back to the [count]-th unmatched group word (e.g. if, or else from its branch)", "cat": "Motion", "sl": "[match", "force": true},
{"s": "matchit", "m": "*", "k": "]%", "d": "Go to the [count]-th next unmatched group word (e.g. else, end)", "cat": "Motion", "sl": "match]", "force": true},
{"s": "matchit", "m": "x", "k": "a%", "d": "Select the enclosing group, from its opener to the first char of the closer", "cat": "Text object", "sl": "a match", "force": true, "n": "Visual mode only. Per matchit's docs only the first character of the closing word is selected (<code>va%d</code> on an <code>if … end</code> block leaves <code>nd</code>), and a [count] is ignored. In Operator-pending mode <code>a%</code> is mini.ai's separator textobject instead."},
{"s": "focusline.nvim", "m": "n", "k": "zz", "d": "Scroll so the cursor line sits 30% from the top (not centred)", "cat": "Scroll & view", "e": 1, "sl": "focus", "force": true, "n": "focusline.nvim (<code>focus_target = \"30%\"</code>) runs the real <code>zz</code>, then scrolls with <kbd>Ctrl-E</kbd>/<kbd>Ctrl-Y</kbd> to put the line at 30% of the window height. Near the top of the buffer it just shows line 1 at the top. Normal mode only: Visual <code>zz</code> still centres."},
{"s": "focusline.nvim", "m": "n", "k": "z,", "d": "Put the cursor line 30% from the top of the window", "cat": "Scroll & view", "sl": "focus", "force": true, "n": "<code>z,</code> is not a Vim command; focusline adds it, so it only does the 30% repositioning."},
{"s": "focusline.nvim", "m": "n", "k": "<C-D>", "d": "Scroll half a page down, then put the cursor line 30% from the top", "cat": "Scroll & view", "e": 1, "sl": "½pg↓ 30%", "force": true, "n": "A [count] is passed to the real <code>&lt;C-D&gt;</code> (it sets <code>'scroll'</code>)."},
{"s": "focusline.nvim", "m": "n", "k": "<C-U>", "d": "Scroll half a page up, then put the cursor line 30% from the top", "cat": "Scroll & view", "sl": "½pg↑ 30%", "force": true},
{"s": "config", "m": "*", "k": "]]", "d": "Jump to the next LSP reference of the word under the cursor (Snacks words)", "cat": "LSP & diagnostics", "e": 1, "sl": "next ref", "force": true, "n": "<code>Snacks.words.jump</code> (lua/keymaps.lua) over the LSP document highlights; sets a jumplist entry and opens folds. Replaces Vim's <code>]]</code> section motion in Normal mode; Markdown buffers override it with heading jumps."},
{"s": "config", "m": "*", "k": "[[", "d": "Jump to the previous LSP reference of the word under the cursor (Snacks words)", "cat": "LSP & diagnostics", "sl": "prev ref", "force": true},
{"s": "ftplugin", "m": "n", "k": "]]", "d": "Jump to the next Markdown heading (treesitter)", "cat": "Motion", "sl": "next hdg", "force": true, "n": "From <code>$VIMRUNTIME/ftplugin/markdown.lua</code>; buffer-local, so it beats the global Snacks words <code>]]</code>."},
{"s": "ftplugin", "m": "n", "k": "[[", "d": "Jump to the previous Markdown heading (treesitter)", "cat": "Motion", "sl": "prev hdg", "force": true},
{"s": "ftplugin", "m": "x", "k": "]]", "d": "Extend the selection to the next Markdown heading", "cat": "Motion", "sl": "next hdg", "force": true},
{"s": "ftplugin", "m": "x", "k": "[[", "d": "Extend the selection to the previous Markdown heading", "cat": "Motion", "sl": "prev hdg", "force": true},
{"s": "neovim", "m": "x", "k": "an", "d": "Select the parent (outer) node: treesitter, or LSP selection range", "cat": "Visual", "sl": "parent node", "n": "Repeat to keep growing the selection. mini.ai's \"next\" objects moved to <kbd>aN</kbd>/<kbd>iN</kbd> so this stays reachable", "force": true},
{"s": "neovim", "m": "x", "k": "in", "d": "Select the child (inner) node: treesitter, or LSP selection range", "cat": "Visual", "sl": "child node", "force": true},
{"s": "neovim", "m": "o", "k": "an", "d": "Operate on the parent (outer) node", "cat": "Text object", "sl": "parent node", "force": true},
{"s": "neovim", "m": "o", "k": "in", "d": "Operate on the child (inner) node", "cat": "Text object", "sl": "child node", "force": true}
],
"builtin": {
"v_ab": {"n": "Handled by mini.ai here: <code>b</code> matches any of <code>()</code>, <code>[]</code>, <code>{}</code>, and it works from outside the pair (cover-or-next search)."},
"v_ib": {"n": "Handled by mini.ai here: <code>b</code> matches any of <code>()</code>, <code>[]</code>, <code>{}</code>, and it works from outside the pair (cover-or-next search)."},
"v_a(": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one (within 50 lines)."},
"v_a)": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one (within 50 lines)."},
"v_i(": {"n": "Handled by mini.ai: <code>i(</code> leaves out the whitespace just inside the brackets, <code>i)</code> includes it; searches forward if not inside a pair."},
"v_i)": {"n": "Handled by mini.ai: includes the whitespace just inside the brackets (<code>i(</code> leaves it out); searches forward if not inside a pair."},
"v_a[": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one."},
"v_a]": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one."},
"v_i[": {"n": "Handled by mini.ai: <code>i[</code> leaves out inner edge whitespace, <code>i]</code> includes it."},
"v_i]": {"n": "Handled by mini.ai: includes inner edge whitespace (<code>i[</code> leaves it out)."},
"v_a{": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one."},
"v_a}": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one."},
"v_i{": {"n": "Handled by mini.ai: <code>i{</code> leaves out inner edge whitespace, <code>i}</code> includes it."},
"v_i}": {"n": "Handled by mini.ai: includes inner edge whitespace (<code>i{</code> leaves it out)."},
"v_a<": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one."},
"v_a>": {"n": "Handled by mini.ai: also finds the next pair when the cursor isn't inside one."},
"v_i<": {"n": "Handled by mini.ai: <code>i&lt;</code> leaves out inner edge whitespace, <code>i&gt;</code> includes it."},
"v_i>": {"n": "Handled by mini.ai: includes inner edge whitespace (<code>i&lt;</code> leaves it out)."},
"v_aquote": {"n": "Handled by mini.ai: balanced quotes searched over 50 lines; does not include the trailing whitespace."},
"v_iquote": {"n": "Handled by mini.ai: balanced quote pairs, cover-or-next search over 50 lines."},
"v_a'": {"n": "Handled by mini.ai: balanced quotes searched over 50 lines; does not include the trailing whitespace."},
"v_i'": {"n": "Handled by mini.ai: balanced quote pairs, cover-or-next search over 50 lines."},
"v_a`": {"n": "Handled by mini.ai: balanced backticks searched over 50 lines; does not include the trailing whitespace."},
"v_i`": {"n": "Handled by mini.ai: balanced backtick pairs, cover-or-next search over 50 lines."},
"v_at": {"n": "Handled by mini.ai's pattern-based tag textobject; same-name nested tags can mis-match."},
"v_it": {"n": "Handled by mini.ai's pattern-based tag textobject; same-name nested tags can mis-match."},
"v_aB": {"n": "Still Vim's built-in: mini.ai passes letters it doesn't define through."},
"v_iB": {"n": "Still Vim's built-in: mini.ai passes letters it doesn't define through."},
"s": {"n": "Disabled: <code>s</code> is mini.surround's prefix (<code>&lt;Nop&gt;</code>). Use <code>cl</code>."},
"v_s": {"n": "Disabled: <code>s</code> is mini.surround's prefix in Visual mode too. Use <code>c</code>."},
"S": {"n": "Now Leap from window (Normal mode). Use <code>cc</code>."},
"<CR>": {"n": "Now Leap (<code>&lt;Plug&gt;(leap)</code>) in Normal, Visual and Operator-pending mode. Use <code>+</code> or <code>j</code>."},
"g]": {"n": "Now mini.ai's <em>move to right edge of textobject</em>. Use <code>:tselect</code> or <code>g&lt;C-]&gt;</code>."},
"f": {"n": "Now flash.nvim: same line only, highlights matches, <kbd>f</kbd> again = next match."},
"F": {"n": "Now flash.nvim: same line only, highlights matches, <kbd>F</kbd> again = reverse."},
"t": {"n": "Now flash.nvim: same line only, highlights matches, <kbd>t</kbd> again = next match."},
"T": {"n": "Now flash.nvim: same line only, highlights matches, <kbd>T</kbd> again = reverse."},
";": {"n": "Now flash.nvim's repeat (same semantics)."},
",": {"n": "Now flash.nvim's reverse repeat (same semantics)."},
"zz": {"n": "focusline.nvim: puts the line 30% from the top instead of the centre."},
"CTRL-D": {"n": "focusline.nvim: scrolls, then puts the cursor line 30% from the top."},
"CTRL-U": {"n": "focusline.nvim: scrolls, then puts the cursor line 30% from the top."},
"[[": {"n": "Normal mode: Snacks words <em>previous LSP reference</em>; Markdown: previous heading."},
"]]": {"n": "Normal mode: Snacks words <em>next LSP reference</em>; Markdown: next heading."}
},
"notes": [
{"title": "f/t are Flash now", "kind": "change", "lead": "<kbd>f</kbd> <kbd>F</kbd> <kbd>t</kbd> <kbd>T</kbd> <kbd>;</kbd> <kbd>,</kbd> are flash.nvim's char mode, kept to the cursor line (<code>multi_line = false</code>) with no jump labels.", "rows": [["<kbd>f</kbd><kbd>x</kbd>", "Jump to the next <code>x</code>; every <code>x</code> on the line lights up and the rest dims"], ["<kbd>f</kbd> again", "While lit: next <code>x</code> without retyping it. <kbd>F</kbd> goes the other way"], ["<kbd>;</kbd> / <kbd>,</kbd>", "Repeat in the same / opposite direction, any time later"], ["<kbd>3</kbd><kbd>f</kbd><kbd>x</kbd>", "Counts work; no wrap, never leaves the line"], ["<kbd>`</kbd><kbd>`</kbd>", "Each Flash jump sets the <code>'</code> mark, so you can jump back (not <kbd>Ctrl-O</kbd>: same line)"], ["<kbd>Esc</kbd>", "Clears the highlights"]], "note": "After <code>Fx</code>, <kbd>F</kbd> again moves <em>right</em> (flash maps lowercase = next in the motion's direction, uppercase = previous).", "keys": ["f", "F", "t", "T", ";", ","]},
{"title": "Leap on Enter and S", "kind": "change", "lead": "<kbd>Enter</kbd> starts a Leap jump in the current window (Normal, Visual, Operator-pending); <kbd>S</kbd> leaps into another window.", "rows": [["<kbd>Enter</kbd><kbd>a</kbd><kbd>b</kbd>", "Jump to an <code>ab</code> pair; if the closest is unlabeled you're already there, else type its label"], ["<kbd>Enter</kbd><kbd>Enter</kbd>", "Repeat the previous Leap search"], ["<kbd>Enter</kbd><kbd>x</kbd><kbd>Enter</kbd>", "Jump to the closest <code>x</code>"], ["<kbd>Space</kbd> / <kbd>Backspace</kbd>", "Next / previous group of labels"], ["<kbd>x</kbd><kbd>Space</kbd>", "<code>x</code> before whitespace or at the end of a line; <kbd>Space</kbd><kbd>Space</kbd> targets line ends and empty lines"], ["<kbd>d</kbd><kbd>Enter</kbd><kbd>a</kbd><kbd>b</kbd>", "A motion for operators too (inclusive forward)"], ["Lost", "<kbd>Enter</kbd> = next line (use <kbd>+</kbd>/<kbd>j</kbd>); <kbd>S</kbd> = substitute line (use <kbd>cc</kbd>)"]], "note": "Brackets, quotes and whitespace match their whole class: <code>(</code> = <code>([{</code>, <code>'</code> = <code>'\"`</code>. Matching is case-sensitive ('ignorecase' is off). Buffer-local <kbd>Enter</kbd> maps (Snacks picker, explorer) still win over the Leap map.", "keys": ["<CR>", "S"]},
{"title": "Surround on s", "kind": "change", "lead": "mini.surround uses <kbd>s</kbd> as a prefix, so plain <kbd>s</kbd> does nothing in Normal, Visual and Operator-pending mode.", "rows": [["<kbd>sa</kbd>{motion}{char}", "Add: <code>saiw)</code> → <code>(word)</code>, <code>saiw(</code> → <code>( word )</code>"], ["<kbd>sd</kbd>{char}", "Delete: <code>sd\"</code>, <code>sdf</code> (keep args), <code>sdt</code> (keep content)"], ["<kbd>sr</kbd>{old}{new}", "Replace: <code>sr)]</code>, <code>sr'\"</code>, <code>srtt</code>"], ["<kbd>sf</kbd> / <kbd>sF</kbd> / <kbd>sh</kbd>", "Find right part / find left part / highlight"], ["<kbd>n</kbd> / <kbd>l</kbd> suffix", "Next / previous surrounding: <code>sdn)</code>, <code>srl\"'</code>"], ["Ids", "<code>( [ { &lt;</code> padded, <code>) ] } &gt;</code> tight, <code>b</code> brackets, <code>q</code> quotes, <code>t</code> tag, <code>f</code> call, <code>?</code> ask"], ["Lost", "<kbd>s</kbd> → use <kbd>cl</kbd>; Visual <kbd>s</kbd> → use <kbd>c</kbd>"]], "keys": ["s"]},
{"title": "Text objects (mini.ai)", "kind": "change", "lead": "<kbd>a</kbd>/<kbd>i</kbd> are mini.ai: they extend Vim's text objects, search forward when you're not inside one, and pass unknown letters (<code>w W s p B</code>) to Vim.", "rows": [["<kbd>if</kbd> / <kbd>af</kbd>", "Function call: arguments / whole call"], ["<kbd>ia</kbd> / <kbd>aa</kbd>", "Argument / argument plus its comma"], ["<kbd>iq</kbd> / <kbd>ib</kbd>", "Any quotes / any of <code>() [] {}</code>"], ["<kbd>it</kbd> / <kbd>i?</kbd>", "Tag content / custom edges (prompted)"], ["<kbd>ig</kbd>", "Whole buffer (custom, lua/plugins.lua)"], ["<kbd>i_</kbd> <kbd>i,</kbd> <kbd>i*</kbd> …", "Between any punctuation"], ["<kbd>iN(</kbd> / <kbd>il(</kbd>", "Next / previous one, e.g. <code>ciN\"</code> (capital N: <kbd>an</kbd>/<kbd>in</kbd> are Neovim's node selection)"], ["<kbd>g[</kbd> / <kbd>g]</kbd>", "Move to the start / end of <code>a{id}</code>"], ["<kbd>i(</kbd> vs <kbd>i)</kbd>", "Open bracket leaves out the inner edge spaces, close bracket includes them"]], "note": "Search: <code>cover_or_next</code> over 50 lines. <code>a\"</code> no longer grabs trailing whitespace.", "keys": ["a", "i"]},
{"title": "zz and half-page scrolls land at 30%", "kind": "change", "lead": "focusline.nvim re-targets these Normal-mode keys to put the cursor line 30% from the top of the window.", "rows": [["<kbd>zz</kbd>", "Line at 30%, not the centre (use <kbd>z.</kbd> to centre with the cursor at the first non-blank)"], ["<kbd>z,</kbd>", "New: same 30% placement"], ["<kbd>Ctrl-D</kbd> / <kbd>Ctrl-U</kbd>", "Half page down / up, then line at 30%"]], "keys": ["zz", "z,", "<C-D>", "<C-U>"]},
{"title": "Smart pairs", "kind": "change", "lead": "mini.pairs plus lua/smart_pairs.lua: an opener only auto-closes when nothing but whitespace, or a closing bracket, follows the cursor.", "rows": [["<kbd>(</kbd> before text", "Types just <code>(</code>, handy for wrapping existing text"], ["<kbd>'</kbd> after a letter", "Typed alone: <code>don't</code>; <code>\"\"</code> + <kbd>\"</kbd> gives <code>\"\"\"</code>"], ["<kbd>\\</kbd> then opener", "Never pairs after a backslash"], ["<kbd>)</kbd> <kbd>\"</kbd>", "Step over the closer that's already there"], ["<kbd>Backspace</kbd>", "Inside an empty pair deletes both"], ["<kbd>Enter</kbd>", "Between <code>()</code> <code>[]</code> <code>{}</code>: closer on its own line"]], "note": "Disable with <code>vim.g.minipairs_disable = true</code> (or <code>vim.b.</code> per buffer).", "keys": ["(", "[", "{", "\"", "'", "`"]},
{"title": "Markdown code fences", "kind": "tip", "lead": "In Markdown buffers, backticks and tildes build fenced code blocks for you.", "rows": [["<kbd>`</kbd><kbd>`</kbd><kbd>`</kbd> on a blank line", "Opener and closer, cursor after the opener: type the language"], ["more <kbd>`</kbd>", "Lengthens both fences (<code>````</code> to wrap a block that contains <code>```</code>)"], ["<kbd>Backspace</kbd>", "Shrinks both; below 3 the closer disappears"], ["<kbd>~</kbd><kbd>~</kbd><kbd>~</kbd>", "Same with tilde fences"]], "note": "Only opens a pair when the next line is blank, the buffer ends there, or it closes the block you're in.", "keys": ["`", "~"]},
{"title": "an / in select syntax nodes", "kind": "tip", "lead": "Neovim 0.12's incremental selection, free because mini.ai's \"next\" objects live on <kbd>aN</kbd>/<kbd>iN</kbd>.", "rows": [["<kbd>v</kbd> <kbd>an</kbd> <kbd>an</kbd>…", "Grow the selection to the enclosing node each time"], ["<kbd>in</kbd>", "Shrink back to a child node"], ["<kbd>]n</kbd> <kbd>[n</kbd>", "Select the next / previous node"], ["<kbd>]N</kbd> <kbd>[N</kbd>", "Extend over the next / previous sibling"]], "note": "Treesitter where a parser exists, otherwise LSP selection range (<code>:h v_an</code>). <code>lua/plugins.lua:424-429</code>", "keys": ["an", "in"]}
]
}