Skip to main content

lattice_listing/
install.rs

1//! LM.3: boot-wiring for the listing crate — its modes and the oil chord
2//! command declarations.
3//!
4//! Mirrors `lattice_diff::install` / `lattice_multibuffer::install`: the
5//! host calls one `install(boot)` and the crate registers its own modes
6//! (keymaps + `action_handlers`, picked up by the K.2.4 +
7//! `register_mode_action_handlers` walks) and its `action:*` command
8//! declarations. The chord *bodies* live in `OilMode::action_handlers()`;
9//! these declarations exist so the keymap `cmd:` names resolve to a
10//! `CommandId` and the handlers bind.
11
12use std::sync::Arc;
13
14use lattice_grammar::{ActionSpec, CommandRegistry, Effect};
15use lattice_mode::SubsystemBoot;
16
17/// Register the listing crate's modes + the oil chord commands at boot.
18pub fn install(boot: &mut impl SubsystemBoot) {
19    crate::oil::register_oil_modes(boot.modes_mut());
20    crate::file_tree::register_file_tree_modes(boot.modes_mut());
21    crate::listing_mode::register_listing_modes(boot.modes_mut());
22    register_oil_commands(boot.commands_mut());
23    register_file_tree_commands(boot.commands_mut());
24}
25
26/// The `action:oil-*` command names the oil-mode chords resolve to. All are
27/// mode-owned: the real bodies are `OilMode::action_handlers()`, consulted
28/// before this `apply` fallback (which is `Effect::None` — a bare chord in a
29/// harness with no handler registered does nothing rather than erroring).
30fn register_oil_commands(registry: &mut CommandRegistry) {
31    for (name, doc) in [
32        (
33            "action:oil-follow",
34            "oil `<CR>`: open the entry under the cursor — descend into a directory, or open a file in the current pane.",
35        ),
36        (
37            "action:oil-navigate-up",
38            "oil `-`: re-list the parent directory, landing on the directory stepped out of.",
39        ),
40        (
41            "action:oil-follow-split",
42            "oil `<C-s>`: open the entry under the cursor in a horizontal split.",
43        ),
44        (
45            "action:oil-follow-vsplit",
46            "oil `<C-v>`: open the entry under the cursor in a vertical split.",
47        ),
48        (
49            "action:oil-follow-tab",
50            "oil `<C-t>`: open the entry under the cursor in a new tab.",
51        ),
52    ] {
53        registry.register_action(
54            name,
55            doc,
56            ActionSpec {
57                apply: Arc::new(|_| Ok(Effect::None)),
58                args_schema: vec![],
59            },
60        );
61    }
62}
63
64/// The `action:file-tree-*` command names the file-tree-mode chords resolve
65/// to. Mode-owned like the oil ones: bodies are
66/// `FileTreeMode::action_handlers()`; the `apply` fallback is `Effect::None`.
67fn register_file_tree_commands(registry: &mut CommandRegistry) {
68    for (name, doc) in [
69        (
70            "action:file-tree-follow",
71            "file-tree `<CR>`: toggle a directory row's expansion, or open a file in the current pane.",
72        ),
73        (
74            "action:file-tree-navigate-up",
75            "file-tree `-`: open an oil browser at the row's directory.",
76        ),
77        (
78            "action:file-tree-follow-split",
79            "file-tree `<C-s>`: open the row under the cursor in a horizontal split.",
80        ),
81        (
82            "action:file-tree-follow-vsplit",
83            "file-tree `<C-v>`: open the row under the cursor in a vertical split.",
84        ),
85        (
86            "action:file-tree-follow-tab",
87            "file-tree `<C-t>`: open the row under the cursor in a new tab.",
88        ),
89    ] {
90        registry.register_action(
91            name,
92            doc,
93            ActionSpec {
94                apply: Arc::new(|_| Ok(Effect::None)),
95                args_schema: vec![],
96            },
97        );
98    }
99}