#[derive(Clone, Copy)]
pub enum Handler {
Leaf(fn(&mut crate::editor::Editor, char)),
Alias(&'static str),
Motion,
Operator,
ObjectPrefix,
Prefix,
TextLine,
AbsorbChar(AbsorbKind),
AbsorbRegister,
Contextual,
Soon,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AbsorbKind {
Replace,
MarkSet,
MarkJump,
Find,
MacroRecord,
MacroPlay,
}
pub struct Binding {
pub keys: &'static str,
pub desc: &'static str,
pub sections: &'static [&'static str],
pub live: bool,
pub id: &'static str,
pub handler: Handler,
}
pub const SECTIONS: &[&str] = &["normal", "visual", "insert", "leader", "git", "ex+panes"];
pub const BINDINGS: &[Binding] = &[
Binding {
keys: "h j k l",
desc: "move (never off the line)",
sections: &["normal"],
live: true,
id: "move",
handler: Handler::Motion,
},
Binding {
keys: "w b e W B E",
desc: "word / WORD motions",
sections: &["normal"],
live: true,
id: "word-motions",
handler: Handler::Motion,
},
Binding {
keys: "zz zt zb",
desc: "center/top/bottom the cursor line",
sections: &["normal"],
live: true,
id: "view-place",
handler: Handler::Leaf(|e, k| e.view_place(k)),
},
Binding {
keys: "H M L",
desc: "top/middle/bottom visible line",
sections: &["normal"],
live: true,
id: "visible-jumps",
handler: Handler::Leaf(|e, k| e.jump_visible(k, 1)),
},
Binding {
keys: "ZZ",
desc: "write + close window",
sections: &["normal"],
live: true,
id: "write-quit",
handler: Handler::Leaf(|e, _| e.write_quit()),
},
Binding {
keys: "gv",
desc: "reselect last visual",
sections: &["normal"],
live: true,
id: "reselect-visual",
handler: Handler::Leaf(|e, _| e.reselect_visual()),
},
Binding {
keys: "gi",
desc: "insert at last insert",
sections: &["normal"],
live: true,
id: "insert-at-last",
handler: Handler::Leaf(|e, _| e.insert_at_last()),
},
Binding {
keys: "g;",
desc: "older change (changelist)",
sections: &["normal"],
live: true,
id: "change-back",
handler: Handler::Leaf(|e, _| e.change_jump(true)),
},
Binding {
keys: "g,",
desc: "newer change (changelist)",
sections: &["normal"],
live: true,
id: "change-forward",
handler: Handler::Leaf(|e, _| e.change_jump(false)),
},
Binding {
keys: "ge gE { }",
desc: "word-end back / paragraph motions",
sections: &["normal"],
live: true,
id: "paragraph-motions",
handler: Handler::Motion,
},
Binding {
keys: "0 $ G %",
desc: "line/file/pair jumps",
sections: &["normal"],
live: true,
id: "line-jumps",
handler: Handler::Motion,
},
Binding {
keys: "g<space>",
desc: "collection: open full source at caret",
sections: &["normal"],
live: true,
id: "collection-source",
handler: Handler::Leaf(|e, _| e.collection_open_source_pub()),
},
Binding {
keys: "gb",
desc: "select next occurrence of word/selection",
sections: &["normal", "visual"],
live: true,
id: "occurrence-next",
handler: Handler::Leaf(|e, _| e.occurrence_next_pub()),
},
Binding {
keys: "gB",
desc: "select all occurrences in buffer",
sections: &["normal", "visual"],
live: true,
id: "occurrence-all",
handler: Handler::Leaf(|e, _| e.occurrence_all_pub()),
},
Binding {
keys: "gg",
desc: "top of file",
sections: &["normal"],
live: true,
id: "top",
handler: Handler::Motion,
},
Binding {
keys: "enter",
desc: "line down, first non-blank (blame gutter: dive)",
sections: &["normal"],
live: true,
id: "enter",
handler: Handler::Leaf(|e, _| e.enter_pub()),
},
Binding {
keys: "tab",
desc: "jump list forward (ctrl-i)",
sections: &["normal"],
live: true,
id: "jump-forward",
handler: Handler::Leaf(|e, _| e.jump_forward()),
},
Binding {
keys: "ctrl-r",
desc: "redo",
sections: &["normal"],
live: true,
id: "redo",
handler: Handler::Leaf(|e, _| e.redo()),
},
Binding {
keys: "ctrl-d ctrl-u ctrl-f ctrl-b",
desc: "half/full page scroll (count = lines)",
sections: &["normal"],
live: true,
id: "scroll-pages",
handler: Handler::Leaf(|_, _| {}), },
Binding {
keys: "ctrl-^",
desc: "alternate buffer",
sections: &["normal"],
live: true,
id: "alternate-buffer",
handler: Handler::Leaf(|e, _| e.alternate_buffer()),
},
Binding {
keys: "q<a>",
desc: "record macro into register",
sections: &["normal"],
live: true,
id: "macro-record",
handler: Handler::AbsorbChar(AbsorbKind::MacroRecord),
},
Binding {
keys: "@<a>",
desc: "play macro (count repeats)",
sections: &["normal"],
live: true,
id: "macro-play",
handler: Handler::AbsorbChar(AbsorbKind::MacroPlay),
},
Binding {
keys: "gr",
desc: "references (LSP)",
sections: &["normal"],
live: true,
id: "references",
handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::References)),
},
Binding {
keys: "gI",
desc: "implementation (LSP)",
sections: &["normal"],
live: true,
id: "implementation",
handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::Implementation)),
},
Binding {
keys: "gy",
desc: "type definition (LSP)",
sections: &["normal"],
live: true,
id: "type-definition",
handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::TypeDefinition)),
},
Binding {
keys: "gD",
desc: "declaration (LSP)",
sections: &["normal"],
live: true,
id: "declaration",
handler: Handler::Leaf(|e, _| e.lsp_locations_pub(strop_lsp::LocKind::Declaration)),
},
Binding {
keys: "]d [d",
desc: "next/prev diagnostic",
sections: &["normal"],
live: true,
id: "diagnostic-jumps",
handler: Handler::Leaf(|e, k| e.jump_diagnostic_pub(k != '[')),
},
Binding {
keys: "gd",
desc: "goto definition (LSP)",
sections: &["normal"],
live: true,
id: "goto-definition",
handler: Handler::Leaf(|e, _| crate::editor::Editor::lsp_goto_definition_pub(e)),
},
Binding {
keys: "gs",
desc: "switch source/header (clangd)",
sections: &["normal"],
live: true,
id: "switch-source-header",
handler: Handler::Leaf(|e, _| crate::editor::Editor::lsp_switch_source_header_pub(e)),
},
Binding {
keys: "f<c> F<c> t<c> T<c>",
desc: "find/till char (candidates light up)",
sections: &["normal"],
live: true,
id: "find-char",
handler: Handler::AbsorbChar(AbsorbKind::Find),
},
Binding {
keys: ":",
desc: "ex command line",
sections: &["normal"],
live: true,
id: "ex-line",
handler: Handler::TextLine,
},
Binding {
keys: "/ ?",
desc: "literal search forward / backward (live as you type or delete)",
sections: &["normal"],
live: true,
id: "search",
handler: Handler::TextLine,
},
Binding {
keys: "n",
desc: "next match",
sections: &["normal"],
live: true,
id: "search-next",
handler: Handler::Leaf(|e, _| e.repeat_search_pub(false)),
},
Binding {
keys: "N",
desc: "previous match",
sections: &["normal"],
live: true,
id: "search-prev",
handler: Handler::Leaf(|e, _| e.repeat_search_pub(true)),
},
Binding {
keys: "]f [f",
desc: "next / prev file card (collections)",
sections: &["normal"],
live: true,
id: "collection-file-nav",
handler: Handler::Leaf(|e, k| e.collection_file_step_pub(k != '[')),
},
Binding {
keys: "]e [e",
desc: "next / prev excerpt (collections; +/- context)",
sections: &["normal"],
live: true,
id: "collection-excerpt-nav",
handler: Handler::Leaf(|e, k| e.collection_excerpt_step(k != '[')),
},
Binding {
keys: "]c [c",
desc: "next / prev git hunk",
sections: &["normal"],
live: true,
id: "hunk-nav",
handler: Handler::Leaf(|e, k| e.jump_hunk_pub(k != '[')),
},
Binding {
keys: "m<a>",
desc: "set mark at cursor",
sections: &["normal"],
live: true,
id: "mark-set",
handler: Handler::AbsorbChar(AbsorbKind::MarkSet),
},
Binding {
keys: "'<a> `<a>",
desc: "jump to mark",
sections: &["normal"],
live: true,
id: "mark-jump",
handler: Handler::AbsorbChar(AbsorbKind::MarkJump),
},
Binding {
keys: "* #",
desc: "word under cursor, forward / backward",
sections: &["normal"],
live: true,
id: "word-search",
handler: Handler::Leaf(|e, k| e.search_word_under_cursor_pub(k == '#')),
},
Binding {
keys: "; ,",
desc: "repeat find, same / reversed",
sections: &["normal"],
live: true,
id: "find-repeat",
handler: Handler::Leaf(|e, k| e.repeat_find_pub(k == ',')),
},
Binding {
keys: "|",
desc: "column motion (vim); pipe moved to space |",
sections: &["normal"],
live: true,
id: "column-motion",
handler: Handler::Motion,
},
Binding {
keys: "space |",
desc: "pipe line/selection through shell (:! runs)",
sections: &["leader"],
live: true,
id: "pipe-shell",
handler: Handler::TextLine,
},
Binding {
keys: "Q",
desc: "toggle cursor at point (multicursor)",
sections: &["normal"],
live: true,
id: "cursor-toggle",
handler: Handler::Leaf(|e, _| crate::editor::Editor::toggle_cursor(e)),
},
Binding {
keys: "d y c > <",
desc: "operators + motion/object (live preview)",
sections: &["normal"],
live: true,
id: "operators",
handler: Handler::Operator,
},
Binding {
keys: "dd yy cc",
desc: "line delete/yank/change",
sections: &["normal"],
live: true,
id: "line-ops",
handler: Handler::Operator,
},
Binding {
keys: "D",
desc: "delete to line end",
sections: &["normal"],
live: true,
id: "op-alias-d",
handler: Handler::Alias("d$"),
},
Binding {
keys: "C",
desc: "change to line end",
sections: &["normal"],
live: true,
id: "op-alias-c",
handler: Handler::Alias("c$"),
},
Binding {
keys: "Y",
desc: "yank line",
sections: &["normal"],
live: true,
id: "op-alias-y",
handler: Handler::Alias("yy"),
},
Binding {
keys: "s",
desc: "substitute char",
sections: &["normal"],
live: true,
id: "op-alias-s",
handler: Handler::Alias("cl"),
},
Binding {
keys: "x X",
desc: "delete char / char back",
sections: &["normal"],
live: true,
id: "char-delete",
handler: Handler::Leaf(|e, _| crate::editor::Editor::delete_char(e)),
},
Binding {
keys: "iw i\" i' i( i[ i{",
desc: "inner objects (quotes scan the line)",
sections: &["normal"],
live: true,
id: "objects",
handler: Handler::ObjectPrefix,
},
Binding {
keys: "ds\" cs\"' ysiw\"",
desc: "surround: delete / change / add",
sections: &["normal"],
live: true,
id: "surround",
handler: Handler::ObjectPrefix,
},
Binding {
keys: "i a A o O I",
desc: "insert (auto-indent)",
sections: &["normal"],
live: true,
id: "insert-entries",
handler: Handler::Leaf(crate::editor::Editor::insert_entry_pub),
},
Binding {
keys: "p P",
desc: "paste after / before",
sections: &["normal"],
live: true,
id: "paste",
handler: Handler::Leaf(|e, k| e.paste_named_pub(None, 1, k == 'P')),
},
Binding {
keys: "r<c>",
desc: "replace char",
sections: &["normal"],
live: true,
id: "replace-char",
handler: Handler::AbsorbChar(AbsorbKind::Replace),
},
Binding {
keys: "J .",
desc: "join lines · repeat change",
sections: &["normal"],
live: true,
id: "join-repeat",
handler: Handler::Leaf(crate::editor::Editor::join_or_repeat),
},
Binding {
keys: "^",
desc: "first non-blank",
sections: &["normal"],
live: true,
id: "first-non-blank",
handler: Handler::Motion,
},
Binding {
keys: "~",
desc: "toggle case",
sections: &["normal"],
live: true,
id: "toggle-case",
handler: Handler::Leaf(|e, _| crate::editor::Editor::toggle_case_pub(e)),
},
Binding {
keys: "S",
desc: "change line",
sections: &["normal"],
live: true,
id: "subst-line",
handler: Handler::Alias("cc"),
},
Binding {
keys: "u ctrl-r",
desc: "undo / redo (one unit per command)",
sections: &["normal"],
live: true,
id: "undo-redo",
handler: Handler::Leaf(|e, _| crate::editor::Editor::undo(e)),
},
Binding {
keys: "\"+y \"+p \"+P",
desc: "system clipboard: yank / paste after / before",
sections: &["normal"],
live: true,
id: "reg-clipboard",
handler: Handler::AbsorbRegister,
},
Binding {
keys: "\"xy \"xp",
desc: "named register: yank / paste",
sections: &["normal"],
live: true,
id: "reg-named",
handler: Handler::AbsorbRegister,
},
Binding {
keys: "ctrl-v",
desc: "visual block",
sections: &["normal"],
live: true,
id: "visual-block",
handler: Handler::Leaf(|e, _| e.enter_block_pub()),
},
Binding {
keys: "v V",
desc: "visual / visual-line",
sections: &["normal"],
live: true,
id: "visual-enter",
handler: Handler::Leaf(|e, k| e.enter_visual_pub(k)),
},
Binding {
keys: "d y c x > <",
desc: "operate on selection",
sections: &["visual"],
live: true,
id: "visual-ops",
handler: Handler::Operator,
},
Binding {
keys: "S<c>",
desc: "wrap selection in pair",
sections: &["visual"],
live: true,
id: "visual-surround",
handler: Handler::AbsorbChar(AbsorbKind::Replace),
},
Binding {
keys: "i<a> a<a>",
desc: "objects select (vi[ works)",
sections: &["visual"],
live: true,
id: "visual-objects",
handler: Handler::ObjectPrefix,
},
Binding {
keys: "space y",
desc: "yank selection → clipboard",
sections: &["visual"],
live: true,
id: "clip-yank",
handler: Handler::Leaf(|e, _| e.clipboard_yank_pub()),
},
Binding {
keys: "esc",
desc: "normal mode (session = one undo unit)",
sections: &["insert"],
live: true,
id: "insert-esc",
handler: Handler::Prefix,
},
Binding {
keys: "backspace",
desc: "delete back",
sections: &["insert"],
live: true,
id: "insert-bs",
handler: Handler::Prefix,
},
Binding {
keys: "enter",
desc: "new line (auto-indent)",
sections: &["insert"],
live: true,
id: "insert-enter",
handler: Handler::Prefix,
},
Binding {
keys: "} ] )",
desc: "closer on indent-only line dedents",
sections: &["insert"],
live: true,
id: "insert-closers",
handler: Handler::Prefix,
},
Binding {
keys: "space e",
desc: "reveal source in its Directory buffer",
sections: &["leader"],
live: true,
id: "directory-reveal",
handler: Handler::Leaf(|e, _| e.reveal_source()),
},
Binding {
keys: "space f",
desc: "file finder",
sections: &["leader"],
live: true,
id: "files",
handler: Handler::Leaf(|e, _| e.open_picker(strop_picker::Kind::Files)),
},
Binding {
keys: "space o",
desc: "open remote destination",
sections: &["leader"],
live: true,
id: "remote-open",
handler: Handler::Leaf(|e, _| e.open_remote_picker()),
},
Binding {
keys: "space b",
desc: "buffers (MRU)",
sections: &["leader"],
live: true,
id: "buffers",
handler: Handler::Leaf(|e, _| e.open_picker(strop_picker::Kind::Buffers)),
},
Binding {
keys: "space /",
desc: "Search workspace (resume investigation)",
sections: &["leader"],
live: true,
id: "search",
handler: Handler::Leaf(|e, _| e.open_search(false)),
},
Binding {
keys: "space R",
desc: "Search with replacement",
sections: &["leader"],
live: true,
id: "replace-global",
handler: Handler::Leaf(|e, _| e.open_search(true)),
},
Binding {
keys: "space ?",
desc: "help buffer",
sections: &["leader"],
live: true,
id: "help",
handler: Handler::Leaf(|e, _| crate::editor::Editor::open_help(e)),
},
Binding {
keys: "space y",
desc: "yank motion → system clipboard",
sections: &["leader"],
live: true,
id: "clip-yank",
handler: Handler::Leaf(|e, _| e.clipboard_yank_pub()),
},
Binding {
keys: "space p",
desc: "paste clipboard after",
sections: &["leader"],
live: true,
id: "clip-paste",
handler: Handler::Leaf(|e, k| e.clipboard_paste_pub(k == 'P')),
},
Binding {
keys: "space P",
desc: "paste clipboard before",
sections: &["leader"],
live: true,
id: "clip-paste-before",
handler: Handler::Leaf(|e, k| e.clipboard_paste_pub(k == 'P')),
},
Binding {
keys: "space d",
desc: "diagnostics picker",
sections: &["leader"],
live: true,
id: "diagnostics",
handler: Handler::Leaf(|e, _| e.open_diagnostics_picker()),
},
Binding {
keys: "space k",
desc: "hover docs",
sections: &["leader"],
live: true,
id: "hover",
handler: Handler::Leaf(|e, _| e.lsp_hover_pub()),
},
Binding {
keys: "space a",
desc: "context actions (code / filesystem)",
sections: &["leader"],
live: true,
id: "code-actions",
handler: Handler::Leaf(|e, _| e.context_actions()),
},
Binding {
keys: "space s",
desc: "document symbols picker",
sections: &["leader"],
live: true,
id: "document-symbols",
handler: Handler::Leaf(|e, _| e.lsp_document_symbols_pub()),
},
Binding {
keys: "space S",
desc: "workspace symbols picker",
sections: &["leader"],
live: false,
id: "workspace-symbols",
handler: Handler::Soon,
},
Binding {
keys: "space j",
desc: "jumplist picker",
sections: &["leader"],
live: true,
id: "jumplist-picker",
handler: Handler::Leaf(|e, _| e.open_picker(strop_picker::Kind::Jumps)),
},
Binding {
keys: "space u",
desc: "undo-tree browser",
sections: &["leader"],
live: true,
id: "undo-tree",
handler: Handler::Leaf(|e, _| crate::editor::Editor::open_undo_tree(e)),
},
Binding {
keys: "space c",
desc: "cursor on next line too (multicursor)",
sections: &["leader"],
live: true,
id: "cursor-stack",
handler: Handler::Leaf(|e, _| crate::editor::Editor::add_cursor_next_line(e)),
},
Binding {
keys: "space g",
desc: "git…",
sections: &["git"],
live: true,
id: "git-prefix",
handler: Handler::Prefix,
},
Binding {
keys: "space g l",
desc: "commit browser",
sections: &["git"],
live: true,
id: "git-log",
handler: Handler::Leaf(|e, _| e.open_log_pub(false)),
},
Binding {
keys: "space g h",
desc: "file history (visual: selected lines)",
sections: &["git"],
live: true,
id: "git-file-history",
handler: Handler::Leaf(|e, _| e.open_log_pub(true)),
},
Binding {
keys: "space g b",
desc: "toggle blame gutter / card",
sections: &["git"],
live: true,
id: "git-blame",
handler: Handler::Leaf(|e, _| e.toggle_blame_gutter()),
},
Binding {
keys: "space g y",
desc: "permalink: copy",
sections: &["git"],
live: true,
id: "git-permalink-yank",
handler: Handler::Leaf(|e, _| e.yank_permalink()),
},
Binding {
keys: "space g o",
desc: "permalink: open",
sections: &["git"],
live: true,
id: "git-permalink-open",
handler: Handler::Leaf(|e, _| e.open_permalink()),
},
Binding {
keys: "space g u",
desc: "hunk: undo unstaged (restore from index)",
sections: &["git"],
live: true,
id: "git-hunk-undo",
handler: Handler::Leaf(|e, _| e.undo_hunk()),
},
Binding {
keys: "space g s",
desc: "hunk: stage (live→index)",
sections: &["git"],
live: true,
id: "git-hunk-stage",
handler: Handler::Leaf(|e, _| e.stage_hunk()),
},
Binding {
keys: "space g S",
desc: "hunk: unstage (index→HEAD)",
sections: &["git"],
live: true,
id: "git-hunk-unstage",
handler: Handler::Leaf(|e, _| e.unstage_hunk()),
},
Binding {
keys: "space g p",
desc: "hunk: preview",
sections: &["git"],
live: true,
id: "git-hunk-preview",
handler: Handler::Leaf(|e, _| e.preview_hunk()),
},
Binding {
keys: "]f [f",
desc: "next / prev file in commit diff",
sections: &["git"],
live: true,
id: "commit-file-nav",
handler: Handler::Soon,
},
Binding {
keys: "enter",
desc: "dive into the line's commit (blame gutter)",
sections: &["git"],
live: true,
id: "surface-dive",
handler: Handler::Prefix,
},
Binding {
keys: "q",
desc: "close surface (readonly buffers)",
sections: &["git"],
live: true,
id: "surface-close",
handler: Handler::Prefix,
},
Binding {
keys: ":w :q :q! :wq :w {file} :trust",
desc: "write / quit (force) / write-quit / write-as",
sections: &["ex+panes"],
live: true,
id: "ex-write-quit",
handler: Handler::TextLine,
},
Binding {
keys: ":[range]s/a/b/[g] :N :% :N,Md :N,My",
desc: "substitute (literal) / goto line / ranged delete+yank",
sections: &["ex+panes"],
live: true,
id: "ex-ranges",
handler: Handler::TextLine,
},
Binding {
keys: "ctrl-d ctrl-u ctrl-f ctrl-b",
desc: "half/full page scroll (count = lines)",
sections: &["ex+panes"],
live: true,
id: "scroll-pages",
handler: Handler::TextLine,
},
Binding {
keys: ":e",
desc: "edit file",
sections: &["ex+panes"],
live: true,
id: "ex-edit",
handler: Handler::TextLine,
},
Binding {
keys: ":help",
desc: "help buffer (this text — / searches it)",
sections: &["ex+panes"],
live: true,
id: "ex-help",
handler: Handler::TextLine,
},
Binding {
keys: ":vs :sp",
desc: "split vertical / horizontal",
sections: &["ex+panes"],
live: true,
id: "ex-split",
handler: Handler::TextLine,
},
Binding {
keys: "ctrl-w h / l / j / k / w",
desc: "pane move / cycle",
sections: &["ex+panes"],
live: true,
id: "pane-nav",
handler: Handler::Leaf(crate::editor::Editor::pane_move_pub),
},
Binding {
keys: "ctrl-o / ctrl-i (tab)",
desc: "jump back / forward (jumplist)",
sections: &["ex+panes"],
live: true,
id: "jumplist",
handler: Handler::Leaf(|e, _| crate::editor::Editor::jump_back(e)),
},
Binding {
keys: "ctrl-w v / s",
desc: "pane split (vs / sp)",
sections: &["ex+panes"],
live: true,
id: "pane-split",
handler: Handler::Leaf(crate::editor::Editor::split_pub),
},
Binding {
keys: ":view :set",
desc: "readonly browsing (:set ro/noro; CLI: -R)",
sections: &["ex+panes"],
live: true,
id: "readonly",
handler: Handler::TextLine,
},
Binding {
keys: "ctrl-w q",
desc: "close pane (last → buffer)",
sections: &["ex+panes"],
live: true,
id: "pane-close",
handler: Handler::Leaf(|e, _| crate::editor::Editor::pane_close_pub(e)),
},
Binding {
keys: "up down left right tab s-tab",
desc: "picker navigation / arrows = hjkl everywhere",
sections: &["ex+panes"],
live: true,
id: "picker-nav",
handler: Handler::Prefix,
},
Binding {
keys: "ctrl-x",
desc: "Search: exclude/include match",
sections: &["ex+panes"],
live: true,
id: "search-exclude",
handler: Handler::Contextual,
},
Binding {
keys: "ctrl-space",
desc: "query field: qualifier, language and value suggestions",
sections: &["ex+panes"],
live: true,
id: "query-suggestions",
handler: Handler::Contextual,
},
Binding {
keys: "ctrl-d",
desc: "Search: exclude/include file",
sections: &["ex+panes"],
live: true,
id: "search-file-exclude",
handler: Handler::Contextual,
},
Binding {
keys: "ctrl-r",
desc: "Search: toggle replacement; document: redo",
sections: &["ex+panes"],
live: true,
id: "search-replacement",
handler: Handler::Contextual,
},
Binding {
keys: "enter",
desc: "Search Find: open source; With: prepare review",
sections: &["ex+panes"],
live: true,
id: "search-accept",
handler: Handler::Contextual,
},
Binding {
keys: "ctrl-o",
desc: "Search: collect included matches",
sections: &["ex+panes"],
live: true,
id: "search-collect",
handler: Handler::Contextual,
},
Binding {
keys: ":tab-size :indent-style :search-options",
desc: "source indentation and search visibility controls",
sections: &["ex+panes"],
live: true,
id: "source-and-search-settings",
handler: Handler::Contextual,
},
Binding {
keys: ":fs :browse :filter",
desc: "filesystem actions, namespace-aware browsing and folder filtering",
sections: &["ex+panes"],
live: true,
id: "filesystem",
handler: Handler::Contextual,
},
Binding {
keys: ":apply-change :cancel-change :save-change",
desc: "review: apply text or filesystem changes, cancel, or save changed text",
sections: &["ex+panes"],
live: true,
id: "change-review-actions",
handler: Handler::Contextual,
},
Binding {
keys: "ctrl-l",
desc: "redraw: full repaint when the terminal desyncs",
sections: &["ex+panes"],
live: true,
id: "redraw",
handler: Handler::Leaf(|e, _| e.needs_repaint = true),
},
];
pub(crate) mod lookup;
pub use lookup::{any_child, children_of, compat_report, find_row, Hint};
#[cfg(test)]
mod tests;