Part of the Vim-compatibility chain (issue 2 of 9). Chained after the oracle-harness issue.
Decision this implements
EditorMode { Vim, Vscode } already exists (src/core/settings.rs:20), and editor_mode already defaults to EditorMode::Vim (settings.rs:761).
But editor_mode is referenced zero times in src/core/engine/keys.rs. The contested defaults are unconditional constants:
| Setting |
Current default |
settings.rs |
ctrl_f_action |
"find" — opens find/replace, even in Normal mode |
:335 |
auto_pairs |
true — typing ( in insert yields () |
:355 |
completion_keys.accept |
"Tab" — the popup eats <Tab> |
:658 |
So "Vim mode" is already the shipped default and already does not mean Vim. A user pressing <C-f> to page down gets a find dialog.
Agreed design: mode-derived defaults. Each default_*() becomes a function of EditorMode. Vim mode yields strict Vim values; Vscode mode yields today's IDE values. Every setting stays independently overridable, so :set mode=vim followed by :set auto_pairs=true is a valid, supported combination.
Agreed ship default: EditorMode::Vim — unchanged from today, but now honest.
fn default_ctrl_f_action(mode: EditorMode) -> String {
match mode {
EditorMode::Vim => "page".to_string(), // <C-f> pages down
EditorMode::Vscode => "find".to_string(), // opens find/replace
}
}
What to do
- Introduce a mode-aware defaults layer in
src/core/settings.rs. Serde's #[serde(default = "...")] cannot see sibling fields, so resolve in two steps: deserialize contested fields as Option<T>, then fill None from the mode in a post-deserialize pass (Settings::apply_mode_defaults(&mut self)), called after load and whenever editor_mode changes at runtime.
- An explicit user setting must always win over the mode default, including when the mode is changed later. Distinguish "unset, inherit from mode" from "explicitly set to the value that happens to equal a mode default" — otherwise
:set mode=vscode silently discards a user's explicit auto_pairs=false.
- Convert these three to mode-derived:
ctrl_f_action, auto_pairs, completion_keys.accept. Later issues in this chain will add more; this issue establishes the mechanism and is deliberately small.
:set mode=vim / :set mode=vscode must re-resolve unset fields live, without a restart.
- Document the mechanism and the full contested-defaults table in
docs/PATTERNS.md (it already covers "adding new settings").
Migration
This changes behaviour on upgrade for existing users on the default config: <C-f> stops opening find, ( stops auto-pairing, <Tab> stops accepting the completion popup. Call it out in the release notes with the one-line escape hatch (:set mode=vscode).
Acceptance
Part of the Vim-compatibility chain (issue 2 of 9). Chained after the oracle-harness issue.
Decision this implements
EditorMode { Vim, Vscode }already exists (src/core/settings.rs:20), andeditor_modealready defaults toEditorMode::Vim(settings.rs:761).But
editor_modeis referenced zero times insrc/core/engine/keys.rs. The contested defaults are unconditional constants:settings.rsctrl_f_action"find"— opens find/replace, even in Normal mode:335auto_pairstrue— typing(in insert yields():355completion_keys.accept"Tab"— the popup eats<Tab>:658So "Vim mode" is already the shipped default and already does not mean Vim. A user pressing
<C-f>to page down gets a find dialog.Agreed design: mode-derived defaults. Each
default_*()becomes a function ofEditorMode. Vim mode yields strict Vim values; Vscode mode yields today's IDE values. Every setting stays independently overridable, so:set mode=vimfollowed by:set auto_pairs=trueis a valid, supported combination.Agreed ship default:
EditorMode::Vim— unchanged from today, but now honest.What to do
src/core/settings.rs. Serde's#[serde(default = "...")]cannot see sibling fields, so resolve in two steps: deserialize contested fields asOption<T>, then fillNonefrom the mode in a post-deserialize pass (Settings::apply_mode_defaults(&mut self)), called after load and whenevereditor_modechanges at runtime.:set mode=vscodesilently discards a user's explicitauto_pairs=false.ctrl_f_action,auto_pairs,completion_keys.accept. Later issues in this chain will add more; this issue establishes the mechanism and is deliberately small.:set mode=vim/:set mode=vscodemust re-resolve unset fields live, without a restart.docs/PATTERNS.md(it already covers "adding new settings").Migration
This changes behaviour on upgrade for existing users on the default config:
<C-f>stops opening find,(stops auto-pairing,<Tab>stops accepting the completion popup. Call it out in the release notes with the one-line escape hatch (:set mode=vscode).Acceptance
mode=vim,ctrl_f_action=page,auto_pairs=false,completion_keys.acceptdoes not capture<Tab>.mode=vscodeand nothing else set: all three revert to today's IDE values.:set mode=vim+:set auto_pairs=truekeeps autopairs on and everything else strict; a later:set mode=vscodedoes not clobber that explicittrue.settings.rsfor each of the three fields × two modes × (unset, explicitly set).TuiDriverblack-box test insrc/tui_main/shell_app.rs: in default (Vim) mode,<C-f>scrolls the rendered viewport rather than opening the find overlay. Assert on rendered output, not on a state field.docs/PATTERNS.mdupdated.