Skip to content

Commit

Permalink
Add duplicate bindings for terminals that support enhanced keys
Browse files Browse the repository at this point in the history
  • Loading branch information
ulyssa committed Apr 24, 2024
1 parent 2445dab commit b093c20
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 100 deletions.
16 changes: 15 additions & 1 deletion crates/modalkit-ratatui/examples/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ use std::time::Duration;

use modalkit::crossterm::{
self,
event::{poll, read, Event},
event::{
poll,
read,
Event,
KeyboardEnhancementFlags,
PushKeyboardEnhancementFlags,
},
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen},
};
Expand Down Expand Up @@ -518,6 +524,14 @@ impl Editor {

crossterm::execute!(stdout, EnterAlternateScreen)?;

if crossterm::terminal::supports_keyboard_enhancement()? {
// Enable the Kitty keyboard enhancement protocol for improved keypresses.
crossterm::execute!(
stdout,
PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES)
)?;
}

let backend = CrosstermBackend::new(stdout);
let terminal = Terminal::new(backend)?;

Expand Down
1 change: 1 addition & 0 deletions crates/modalkit/src/env/emacs/keybindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt

// Command mode keybindings.
( CMAP, "<C-G>", prompt!(PromptAction::Abort(false), EmacsMode::Insert) ),
( CMAP, "<C-I>", editor!(EditorAction::Complete(CompletionType::Auto, CompletionSelection::Single, CompletionDisplay::Bar)) ),
( CMAP, "<Up>", prompt!(PromptAction::Recall(MoveDir1D::Previous, Count::Contextual, false)) ),
( CMAP, "<Down>", prompt!(PromptAction::Recall(MoveDir1D::Next, Count::Contextual, false)) ),
( CMAP, "<Space>", editor!(EditorAction::Complete(CompletionType::Auto, CompletionSelection::Prefix, CompletionDisplay::Bar)) ),
Expand Down
22 changes: 14 additions & 8 deletions crates/modalkit/src/env/keyparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,19 @@ mod tests {
}

#[test]
fn test_ctl_rename() {
assert_eq!(parse("<C-?>"), res![evkey!(KeyCode::Backspace)]);
assert_eq!(parse("<C-I>"), res![evkey!(KeyCode::Tab)]);
assert_eq!(parse("<C-J>"), res![evkey!('\n')]);
assert_eq!(parse("<C-M>"), res![evkey!(KeyCode::Enter)]);
assert_eq!(parse("<C-@>"), res![evctl!(' ')]);
assert_eq!(parse("<C-[>"), res![evkey!(KeyCode::Esc)]);
fn test_ctl_no_collision() {
// These characters are sometimes be the same keypresses, but we should
// allow them to be mapped separately for environments that support it.
assert_eq!(parse("<C-?>"), res![evctl!('?')]);
assert_eq!(parse("<BS>"), res![evkey!(KeyCode::Backspace)]);
assert_eq!(parse("<C-I>"), res![evctl!('i')]);
assert_eq!(parse("<Tab>"), res![evkey!(KeyCode::Tab)]);
assert_eq!(parse("<C-M>"), res![evctl!('m')]);
assert_eq!(parse("<Enter>"), res![evkey!(KeyCode::Enter)]);
assert_eq!(parse("<C-@>"), res![evctl!('@')]);
assert_eq!(parse("<C-Space>"), res![evctl!(' ')]);
assert_eq!(parse("<C-[>"), res![evctl!('[')]);
assert_eq!(parse("<Esc>"), res![evkey!(KeyCode::Esc)]);
}

#[test]
Expand Down Expand Up @@ -273,7 +279,7 @@ mod tests {
assert_eq!(parse("<Delete>"), res![evkey!(KeyCode::Delete)]);
assert_eq!(parse("<Undo>"), res![evkey!(KeyCode::F(14))]);
assert_eq!(parse("<Help>"), res![evkey!(KeyCode::F(15))]);
assert_eq!(parse("<S-Tab>"), res![evkey!(KeyCode::BackTab)]);
assert_eq!(parse("<S-Tab>"), res![evkey!(KeyCode::BackTab, KeyModifiers::SHIFT)]);
}

#[test]
Expand Down
14 changes: 13 additions & 1 deletion crates/modalkit/src/env/vim/keybindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
[
// Normal, Visual, Select, Insert mode keys
( NVIMAP, "<C-\\><C-N>", normal!() ),
( NVIMAP, "<C-4><C-N>", normal!() ),
( NVIMAP, "<C-End>", edit_target_end!(EditTarget::Boundary(RangeType::Buffer, true, MoveTerminus::End, Count::Contextual)) ),
( NVIMAP, "<C-PageDown>", tab_focus!(FocusChange::Direction1D(MoveDir1D::Next, Count::Exact(1), true), FocusChange::Offset(Count::Contextual, false)) ),
( NVIMAP, "<C-PageUp>", tab_focus!(FocusChange::Direction1D(MoveDir1D::Previous, Count::Contextual, true)) ),
Expand All @@ -1292,6 +1293,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( MAP, "<C-J>", edit_end!(MoveType::Line(MoveDir1D::Next)) ),
( MAP, "<C-N>", edit_end!(MoveType::Line(MoveDir1D::Next)) ),
( MAP, "<C-P>", edit_end!(MoveType::Line(MoveDir1D::Previous)) ),
( MAP, "<C-?>", edit_end!(MoveType::Column(MoveDir1D::Previous, true)) ),
( MAP, "<Up>", edit_end!(MoveType::Line(MoveDir1D::Previous)) ),
( MAP, "<Down>", edit_end!(MoveType::Line(MoveDir1D::Next)) ),
( MAP, "<Left>", edit_end!(MoveType::Column(MoveDir1D::Previous, false)) ),
Expand Down Expand Up @@ -1607,10 +1609,13 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( NMAP, "<C-T>", unmapped!() ),
( NMAP, "<C-X>", edit_target!(EditAction::ChangeNumber(NumberChange::Decrease(Count::Contextual), false), EditTarget::Motion(MoveType::LinePos(MovePosition::End), 0.into())) ),
( NMAP, "<C-Z>", act!(Action::Suspend) ),
( NMAP, "<C-[>", normal!() ),
( NMAP, "<C-^>", window_switch!(OpenTarget::Alternate, OpenTarget::List(Count::Contextual)) ),
( NMAP, "<C-6>", window_switch!(OpenTarget::Alternate, OpenTarget::List(Count::Contextual)) ),
( NMAP, "<Del>", edit_nocount!(EditAction::Delete, MoveType::Column(MoveDir1D::Next, false)) ),
( NMAP, "<Esc>", normal!() ),
( NMAP, "<Insert>", insert!(InsertStyle::Insert) ),
( NMAP, "<Tab>", jump!(PositionList::JumpList, MoveDir1D::Next) ),

// Visual, Select mode keys
( VMAP, "<C-A>", edit_selection!(EditAction::ChangeNumber(NumberChange::Increase(Count::Contextual), false)) ),
Expand All @@ -1620,6 +1625,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( VMAP, "<C-X>", edit_selection!(EditAction::ChangeNumber(NumberChange::Decrease(Count::Contextual), false)) ),
( VMAP, "<C-Z>", act!(Action::Suspend) ),
( VMAP, "<Del>", edit_selection_nocount!(EditAction::Delete) ),
( VMAP, "<C-[>", normal!() ),
( VMAP, "<Esc>", normal!() ),

// Visual mode keys
Expand Down Expand Up @@ -1717,6 +1723,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( IMAP, "<C-X><C-E>", scroll2d!(MoveDir2D::Down, ScrollSize::Cell) ),
( IMAP, "<C-X><C-Y>", scroll2d!(MoveDir2D::Up, ScrollSize::Cell) ),
( IMAP, "<C-Y>", chartype!(Char::CopyLine(MoveDir1D::Previous)) ),
( IMAP, "<C-[>", normal!() ),
( IMAP, "<Home>", edit!(EditAction::Motion, MoveType::LinePos(MovePosition::Beginning), 0) ),
( IMAP, "<End>", edit!(EditAction::Motion, MoveType::LinePos(MovePosition::End), 0) ),
( IMAP, "<Up>", edit!(EditAction::Motion, MoveType::Line(MoveDir1D::Previous)) ),
Expand All @@ -1729,6 +1736,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( IMAP, "<S-Right>", edit!(EditAction::Motion, MoveType::WordBegin(WordStyle::Little, MoveDir1D::Next)) ),
( IMAP, "<C-Left>", edit_end!(MoveType::WordBegin(WordStyle::Little, MoveDir1D::Previous)) ),
( IMAP, "<C-Right>", edit_end!(MoveType::WordBegin(WordStyle::Little, MoveDir1D::Next)) ),
( IMAP, "<C-Space>", paste_register!(MoveDir1D::Previous, Register::LastInserted, VimMode::Normal) ),
( IMAP, "<Esc>", normal!() ),
( IMAP, "<Tab>", chartype!(Char::Single('\t')) ),
( IMAP, "<C-Home>", edit!(EditAction::Motion, MoveType::BufferPos(MovePosition::Beginning)) ),
Expand All @@ -1747,6 +1755,8 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( CMAP, "<C-N>", unmapped!() ),
( CMAP, "<C-P>", unmapped!() ),
( CMAP, "<C-\\><C-N>", command_unfocus!() ),
( CMAP, "<C-4><C-N>", command_unfocus!() ),
( CMAP, "<C-[>", command_unfocus!() ),
( CMAP, "<Home>", edit_buffer!(EditAction::Motion, MoveTerminus::Beginning, VimMode::Command) ),
( CMAP, "<End>", edit_buffer!(EditAction::Motion, MoveTerminus::End, VimMode::Command) ),
( CMAP, "<Esc>", command_unfocus!() ),
Expand Down Expand Up @@ -1784,6 +1794,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( SUFFIX_CHARSRCH, "<C-V>{dec<=3}", charsearch_suffix!() ),
( SUFFIX_CHARSRCH, "<C-V>{any}", charsearch_suffix!() ),
( SUFFIX_CHARSRCH, "{any}", charsearch_suffix!() ),
( SUFFIX_CHARSRCH, "<C-[>", act!(Action::NoOp) ),
( SUFFIX_CHARSRCH, "<Esc>", act!(Action::NoOp) ),

// Internal mode to simplify keypresses allowed after r/gr.
Expand All @@ -1797,6 +1808,7 @@ fn default_keys<I: ApplicationInfo>() -> Vec<(MappedModes, &'static str, InputSt
( SUFFIX_CHARREPL, "<C-V>{dec<=3}", charreplace_suffix!() ),
( SUFFIX_CHARREPL, "{any}", charreplace_suffix!() ),
( SUFFIX_CHARREPL, "<C-C>", normal!() ),
( SUFFIX_CHARREPL, "<C-[>", act!(Action::NoOp) ),
( SUFFIX_CHARREPL, "<Esc>", act!(Action::NoOp) ),
( SUFFIX_CHARREPL, "<C-E>", charreplace_suffix!(Char::CopyLine(MoveDir1D::Previous)) ),
( SUFFIX_CHARREPL, "<C-Y>", charreplace_suffix!(Char::CopyLine(MoveDir1D::Next)) ),
Expand Down Expand Up @@ -3304,7 +3316,7 @@ mod tests {

// <C-J> (newline)
let mov = mv!(MoveType::Line(MoveDir1D::Next));
vm.input_key(key!('\n'));
vm.input_key(ctl!('j'));
assert_pop1!(vm, mov, ctx);
assert_normal!(vm, ctx);

Expand Down
Loading

0 comments on commit b093c20

Please sign in to comment.