mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-11-06 00:15:06 +00:00
fix(keymap): let the code editor's line commands beat the app's chords
The editor binds toggle comment, move/copy/delete line, insert line, select line and go-to-bracket on its CodeEditor key context. A context-free app binding ranks as deep as the focused context and wins the tie by being added later, so ⌘/ (shortcut sheet), ⌘↵ (fullscreen), ⌘⇧↵ (maximize) and, off macOS, ⌥↑/⌥↓ (pane focus) took those keys inside the editor. Re-add them in fixed_bindings on CodeEditor, which only a multi-line code editor declares, so plain text fields and the terminal keep the app's keys.
This commit is contained in:
@@ -2100,17 +2100,20 @@ impl Tty7App {
|
||||
)
|
||||
.menu(t(L10nKey::AppMenuSelectAll), Box::new(edit::SelectAll))
|
||||
.separator()
|
||||
// The line commands act on the caret's line or every line the
|
||||
// selection touches; the chords come from gpui-component's
|
||||
// `CodeEditor` key context, which sits deeper than any of the
|
||||
// app's own bindings and so wins while the editor has focus.
|
||||
// The line commands act on every line a cursor or selection
|
||||
// touches. Their chords live on gpui-component's `CodeEditor` key
|
||||
// context and are re-added in `keymap::fixed_bindings`, so they
|
||||
// beat the app's own keys while the editor has focus.
|
||||
.menu(
|
||||
t(L10nKey::EditorToggleComment),
|
||||
Box::new(edit::ToggleLineComment),
|
||||
)
|
||||
.menu(t(L10nKey::EditorMoveLineUp), Box::new(edit::MoveLineUp))
|
||||
.menu(t(L10nKey::EditorMoveLineDown), Box::new(edit::MoveLineDown))
|
||||
.menu(t(L10nKey::EditorDuplicateLine), Box::new(edit::CopyLineDown))
|
||||
.menu(
|
||||
t(L10nKey::EditorDuplicateLine),
|
||||
Box::new(edit::CopyLineDown),
|
||||
)
|
||||
.menu(t(L10nKey::EditorDeleteLine), Box::new(edit::DeleteLine))
|
||||
.separator()
|
||||
.menu(t(L10nKey::AppMenuFind), Box::new(edit::Search))
|
||||
|
||||
@@ -92,6 +92,32 @@ fn fixed_bindings() -> Vec<KeyBinding> {
|
||||
bindings.push(KeyBinding::new("secondary-alt-up", AddCursorAbove, input));
|
||||
bindings.push(KeyBinding::new("secondary-alt-down", AddCursorBelow, input));
|
||||
}
|
||||
// The code editor's line commands, for the same tie: ⌘/ is the shortcut
|
||||
// sheet, ⌘↵ fullscreen, ⌘⇧↵ maximize and ⌥↑/⌥↓ pane focus off macOS, all
|
||||
// context-free. Bound on `CodeEditor`, which only a multi-line code
|
||||
// editor declares, so every other text field and the terminal keep the
|
||||
// app's keys.
|
||||
{
|
||||
use gpui_component::input::{
|
||||
CODE_EDITOR_CONTEXT, CopyLineDown, CopyLineUp, DeleteLine, InsertLineAbove,
|
||||
InsertLineBelow, MoveLineDown, MoveLineUp, MoveToMatchingBracket, SelectLine,
|
||||
ToggleBlockComment, ToggleLineComment,
|
||||
};
|
||||
let editor = Some(CODE_EDITOR_CONTEXT);
|
||||
bindings.extend([
|
||||
KeyBinding::new("secondary-/", ToggleLineComment, editor),
|
||||
KeyBinding::new("alt-shift-a", ToggleBlockComment, editor),
|
||||
KeyBinding::new("alt-up", MoveLineUp, editor),
|
||||
KeyBinding::new("alt-down", MoveLineDown, editor),
|
||||
KeyBinding::new("alt-shift-up", CopyLineUp, editor),
|
||||
KeyBinding::new("alt-shift-down", CopyLineDown, editor),
|
||||
KeyBinding::new("secondary-shift-k", DeleteLine, editor),
|
||||
KeyBinding::new("secondary-enter", InsertLineBelow, editor),
|
||||
KeyBinding::new("secondary-shift-enter", InsertLineAbove, editor),
|
||||
KeyBinding::new("secondary-l", SelectLine, editor),
|
||||
KeyBinding::new("secondary-shift-\\", MoveToMatchingBracket, editor),
|
||||
]);
|
||||
}
|
||||
bindings
|
||||
}
|
||||
|
||||
@@ -2617,6 +2643,59 @@ mod gpui_tests {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// The code editor's line commands sit on chords the app also spends —
|
||||
/// ⌘/ is the shortcut sheet, ⌘↵ fullscreen, ⌘⇧↵ maximize, ⌥↑/⌥↓ pane
|
||||
/// focus off macOS. `fixed_bindings` re-adds them on the `CodeEditor`
|
||||
/// context the editor declares beside `Input`, after the app's table, so
|
||||
/// inside the editor they win and everywhere else nothing changes.
|
||||
#[gpui::test]
|
||||
fn the_code_editor_chords_win_inside_the_editor(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
running_on_json(cx, "{}");
|
||||
let first = |keys: &str, stack: &[&str]| {
|
||||
let input: Vec<Keystroke> = keys
|
||||
.split(' ')
|
||||
.map(|k| Keystroke::parse(k).expect("the typed keystroke parses"))
|
||||
.collect();
|
||||
let stack: Vec<gpui::KeyContext> = stack
|
||||
.iter()
|
||||
.map(|c| gpui::KeyContext::parse(c).expect("the context parses"))
|
||||
.collect();
|
||||
cx.key_bindings()
|
||||
.borrow()
|
||||
.bindings_for_input(&input, &stack)
|
||||
.0
|
||||
.first()
|
||||
.map(|b| b.action().name())
|
||||
};
|
||||
let editor = ["Workspace", "Input CodeEditor"];
|
||||
for (keys, action) in [
|
||||
("secondary-/", "input::ToggleLineComment"),
|
||||
("alt-up", "input::MoveLineUp"),
|
||||
("alt-down", "input::MoveLineDown"),
|
||||
("alt-shift-up", "input::CopyLineUp"),
|
||||
("alt-shift-down", "input::CopyLineDown"),
|
||||
("secondary-shift-k", "input::DeleteLine"),
|
||||
("secondary-enter", "input::InsertLineBelow"),
|
||||
("secondary-shift-enter", "input::InsertLineAbove"),
|
||||
("secondary-l", "input::SelectLine"),
|
||||
("secondary-shift-\\", "input::MoveToMatchingBracket"),
|
||||
] {
|
||||
assert_eq!(first(keys, &editor), Some(action), "{keys} in the editor");
|
||||
assert_ne!(
|
||||
first(keys, &["Workspace", "Input"]),
|
||||
Some(action),
|
||||
"{keys} in a plain text field"
|
||||
);
|
||||
assert_ne!(
|
||||
first(keys, &["Workspace", "Terminal"]),
|
||||
Some(action),
|
||||
"{keys} in a terminal"
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_chord_added_in_config_keeps_the_default_one(cx: &mut TestAppContext) {
|
||||
use gpui::Action as _;
|
||||
|
||||
Reference in New Issue
Block a user