", "m": ["n"], "d": "Replace parentheses with a 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 n (next) and l (last/previous) suffixes work after sd, sr, sf, sF and sh: srn)], sfl\", shnt."},
{"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 [, {, <."},
{"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 ], }, >."},
{"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 q: with the cursor on x in \"a\" x \"b\", sdq strips the quotes around \" x \"."},
{"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 should_pair)."},
{"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 ) ] }. Also blocks pairing before a quote or comma, e.g. typing ( inside an empty \"\"."},
{"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 ` three times: the first pairs to ``, the second steps over, the third turns the line into ``` with a twin ``` 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": "", "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": "", "m": ["i"], "d": "Between (), [] or {}: put the closer on its own line, cursor between", "s": "mini.pairs", "cat": "Pairs", "n": "Quotes are registered with cr = false, so Enter between \"\" 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 char_actions: the lowercase motion key is next, the uppercase one prev. After Fx that means f keeps going left and F goes right. Ends once the highlights go away (cursor moved by something else, Esc, 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": "", "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 (picker.win.input.keys in lua/plugins.lua). Runs flash.jump with pattern ^ restricted to the snacks_picker_list window; picking a label moves the list cursor, it does not confirm."},
{"k": "", "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 (sfnut/SFNLHMUGTZ?); 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": "", "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": "", "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": "", "m": ["n", "x", "o"], "d": "As the first key: repeat the previous Leap search (so re-leaps)", "s": "leap", "cat": "Motion", "ctx": "During a Leap jump", "h": "leap-repeat"},
{"k": "{char}", "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}", "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": "", "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": "", "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 a% in Visual mode, so da% goes through mini.ai's a with % as a separator id. For matchit's group use va%, which stops on the first character of the closing word (e of end)."}
],
"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: modes.char.multi_line = false): 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 f again for the next match. Each jump sets the ' mark, so `` jumps back (Ctrl-O 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 Fx, F moves to the right and f 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 t (next) or T (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 (yf.) 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": "", "d": "Leap: jump anywhere in this window (2 chars, then a label)", "cat": "Motion", "e": 1, "sl": "leap", "force": true, "n": "<Plug>(leap), lua/keymaps.lua. Bidirectional in the current window, closest targets first; inclusive with operators (d<CR>ab). Replaces Vim's Enter = next line (use + or j). Being a global Normal map it also takes over Enter 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": "<Plug>(leap-from-window), Normal mode only: targets every other focusable, non-floating window in the tab and moves you there. Replaces Vim's S (use cc). Visual S 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 cover_or_next within n_lines = 50: the textobject covering the cursor, else the next one (first on the cursor line). Unknown letters fall back to Vim's built-ins (aw, ap, …)."},
{"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 g] (:tselect on the tag under the cursor); use :tselect or g<C-]> 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 s to <Nop> in Normal, Visual and Operator-pending mode. Built-in s = cl; Visual s = c."},
{"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 \\; otherwise types just (. Disable all pairing with vim.g.minipairs_disable or vim.b.minipairs_disable."},
{"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 ) ] }, and not after a letter, digit, backslash or another \"."},
{"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 don't and it's 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": "", "ctx": "markdown buffers", "d": "Markdown backspace: shrink an untouched fence pair, else mini.pairs ", "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": "", "d": "Backspace; inside an empty pair (), [], {}, \"\", '', `` delete both", "cat": "Pairs", "sl": "⌫ pair", "force": true},
{"s": "mini.pairs", "m": "i", "k": "", "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 'commentstring' (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 an/in (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 % with b:match_words: cycles forward through groups like if → else → end."},
{"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 (va%d on an if … end block leaves nd), and a [count] is ignored. In Operator-pending mode a% 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 (focus_target = \"30%\") runs the real zz, then scrolls with Ctrl-E/Ctrl-Y 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 zz 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": "z, is not a Vim command; focusline adds it, so it only does the 30% repositioning."},
{"s": "focusline.nvim", "m": "n", "k": "", "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 <C-D> (it sets 'scroll')."},
{"s": "focusline.nvim", "m": "n", "k": "", "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": "Snacks.words.jump (lua/keymaps.lua) over the LSP document highlights; sets a jumplist entry and opens folds. Replaces Vim's ]] 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 $VIMRUNTIME/ftplugin/markdown.lua; buffer-local, so it beats the global Snacks words ]]."},
{"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 aN/iN 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: b matches any of (), [], {}, and it works from outside the pair (cover-or-next search)."},
"v_ib": {"n": "Handled by mini.ai here: b matches any of (), [], {}, 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: i( leaves out the whitespace just inside the brackets, i) includes it; searches forward if not inside a pair."},
"v_i)": {"n": "Handled by mini.ai: includes the whitespace just inside the brackets (i( 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: i[ leaves out inner edge whitespace, i] includes it."},
"v_i]": {"n": "Handled by mini.ai: includes inner edge whitespace (i[ 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: i{ leaves out inner edge whitespace, i} includes it."},
"v_i}": {"n": "Handled by mini.ai: includes inner edge whitespace (i{ 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: i< leaves out inner edge whitespace, i> includes it."},
"v_i>": {"n": "Handled by mini.ai: includes inner edge whitespace (i< 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: s is mini.surround's prefix (<Nop>). Use cl."},
"v_s": {"n": "Disabled: s is mini.surround's prefix in Visual mode too. Use c."},
"S": {"n": "Now Leap from window (Normal mode). Use cc."},
"": {"n": "Now Leap (<Plug>(leap)) in Normal, Visual and Operator-pending mode. Use + or j."},
"g]": {"n": "Now mini.ai's move to right edge of textobject. Use :tselect or g<C-]>."},
"f": {"n": "Now flash.nvim: same line only, highlights matches, f again = next match."},
"F": {"n": "Now flash.nvim: same line only, highlights matches, F again = reverse."},
"t": {"n": "Now flash.nvim: same line only, highlights matches, t again = next match."},
"T": {"n": "Now flash.nvim: same line only, highlights matches, T 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 previous LSP reference; Markdown: previous heading."},
"]]": {"n": "Normal mode: Snacks words next LSP reference; Markdown: next heading."}
},
"notes": [
{"title": "f/t are Flash now", "kind": "change", "lead": "f F t T ; , are flash.nvim's char mode, kept to the cursor line (multi_line = false) with no jump labels.", "rows": [["fx", "Jump to the next x; every x on the line lights up and the rest dims"], ["f again", "While lit: next x without retyping it. F goes the other way"], ["; / ,", "Repeat in the same / opposite direction, any time later"], ["3fx", "Counts work; no wrap, never leaves the line"], ["``", "Each Flash jump sets the ' mark, so you can jump back (not Ctrl-O: same line)"], ["Esc", "Clears the highlights"]], "note": "After Fx, F again moves right (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": "Enter starts a Leap jump in the current window (Normal, Visual, Operator-pending); S leaps into another window.", "rows": [["Enterab", "Jump to an ab pair; if the closest is unlabeled you're already there, else type its label"], ["EnterEnter", "Repeat the previous Leap search"], ["EnterxEnter", "Jump to the closest x"], ["Space / Backspace", "Next / previous group of labels"], ["xSpace", "x before whitespace or at the end of a line; SpaceSpace targets line ends and empty lines"], ["dEnterab", "A motion for operators too (inclusive forward)"], ["Lost", "Enter = next line (use +/j); S = substitute line (use cc)"]], "note": "Brackets, quotes and whitespace match their whole class: ( = ([{, ' = '\"`. Matching is case-sensitive ('ignorecase' is off). Buffer-local Enter maps (Snacks picker, explorer) still win over the Leap map.", "keys": ["", "S"]},
{"title": "Surround on s", "kind": "change", "lead": "mini.surround uses s as a prefix, so plain s does nothing in Normal, Visual and Operator-pending mode.", "rows": [["sa{motion}{char}", "Add: saiw) → (word), saiw( → ( word )"], ["sd{char}", "Delete: sd\", sdf (keep args), sdt (keep content)"], ["sr{old}{new}", "Replace: sr)], sr'\", srtt"], ["sf / sF / sh", "Find right part / find left part / highlight"], ["n / l suffix", "Next / previous surrounding: sdn), srl\"'"], ["Ids", "( [ { < padded, ) ] } > tight, b brackets, q quotes, t tag, f call, ? ask"], ["Lost", "s → use cl; Visual s → use c"]], "keys": ["s"]},
{"title": "Text objects (mini.ai)", "kind": "change", "lead": "a/i are mini.ai: they extend Vim's text objects, search forward when you're not inside one, and pass unknown letters (w W s p B) to Vim.", "rows": [["if / af", "Function call: arguments / whole call"], ["ia / aa", "Argument / argument plus its comma"], ["iq / ib", "Any quotes / any of () [] {}"], ["it / i?", "Tag content / custom edges (prompted)"], ["ig", "Whole buffer (custom, lua/plugins.lua)"], ["i_ i, i* …", "Between any punctuation"], ["iN( / il(", "Next / previous one, e.g. ciN\" (capital N: an/in are Neovim's node selection)"], ["g[ / g]", "Move to the start / end of a{id}"], ["i( vs i)", "Open bracket leaves out the inner edge spaces, close bracket includes them"]], "note": "Search: cover_or_next over 50 lines. a\" 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": [["zz", "Line at 30%, not the centre (use z. to centre with the cursor at the first non-blank)"], ["z,", "New: same 30% placement"], ["Ctrl-D / Ctrl-U", "Half page down / up, then line at 30%"]], "keys": ["zz", "z,", "", ""]},
{"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": [["( before text", "Types just (, handy for wrapping existing text"], ["' after a letter", "Typed alone: don't; \"\" + \" gives \"\"\""], ["\\ then opener", "Never pairs after a backslash"], [") \"", "Step over the closer that's already there"], ["Backspace", "Inside an empty pair deletes both"], ["Enter", "Between () [] {}: closer on its own line"]], "note": "Disable with vim.g.minipairs_disable = true (or vim.b. per buffer).", "keys": ["(", "[", "{", "\"", "'", "`"]},
{"title": "Markdown code fences", "kind": "tip", "lead": "In Markdown buffers, backticks and tildes build fenced code blocks for you.", "rows": [["``` on a blank line", "Opener and closer, cursor after the opener: type the language"], ["more `", "Lengthens both fences (```` to wrap a block that contains ```)"], ["Backspace", "Shrinks both; below 3 the closer disappears"], ["~~~", "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 aN/iN.", "rows": [["v an an…", "Grow the selection to the enclosing node each time"], ["in", "Shrink back to a child node"], ["]n [n", "Select the next / previous node"], ["]N [N", "Extend over the next / previous sibling"]], "note": "Treesitter where a parser exists, otherwise LSP selection range (:h v_an). lua/plugins.lua:424-429", "keys": ["an", "in"]}
]
}