mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-25 14:05:41 -05:00
Add separate mode for search bindings
This commit is contained in:
parent
116faba7c6
commit
8a7f8c9d3e
6 changed files with 584 additions and 420 deletions
|
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Support for cursor blinking escapes (`CSI ? 12 h`, `CSI ? 12 l` and `CSI Ps SP q`)
|
- Support for cursor blinking escapes (`CSI ? 12 h`, `CSI ? 12 l` and `CSI Ps SP q`)
|
||||||
- IME support on Windows
|
- IME support on Windows
|
||||||
- Urgency support on Windows
|
- Urgency support on Windows
|
||||||
|
- Customizable keybindings for search
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
135
alacritty.yml
135
alacritty.yml
|
@ -611,6 +611,18 @@
|
||||||
# - SearchEnd
|
# - SearchEnd
|
||||||
# End of the match to the right of the vi mode cursor.
|
# End of the match to the right of the vi mode cursor.
|
||||||
#
|
#
|
||||||
|
# - Search mode exclusive actions:
|
||||||
|
# - SearchFocusNext
|
||||||
|
# Move the focus to the next search match.
|
||||||
|
# - SearchFocusPrevious
|
||||||
|
# Move the focus to the previous search match.
|
||||||
|
# - SearchConfirm
|
||||||
|
# - SearchCancel
|
||||||
|
# - SearchClear
|
||||||
|
# Reset the search regex.
|
||||||
|
# - SearchDeleteWord
|
||||||
|
# Delete the last word in the search regex.
|
||||||
|
#
|
||||||
# - macOS exclusive actions:
|
# - macOS exclusive actions:
|
||||||
# - ToggleSimpleFullscreen
|
# - ToggleSimpleFullscreen
|
||||||
# Enter fullscreen without occupying another space.
|
# Enter fullscreen without occupying another space.
|
||||||
|
@ -650,6 +662,7 @@
|
||||||
#
|
#
|
||||||
# - AppCursor
|
# - AppCursor
|
||||||
# - AppKeypad
|
# - AppKeypad
|
||||||
|
# - Search
|
||||||
# - Alt
|
# - Alt
|
||||||
# - Vi
|
# - Vi
|
||||||
#
|
#
|
||||||
|
@ -667,67 +680,75 @@
|
||||||
#- { key: Paste, action: Paste }
|
#- { key: Paste, action: Paste }
|
||||||
#- { key: Copy, action: Copy }
|
#- { key: Copy, action: Copy }
|
||||||
#- { key: L, mods: Control, action: ClearLogNotice }
|
#- { key: L, mods: Control, action: ClearLogNotice }
|
||||||
#- { key: L, mods: Control, mode: ~Vi, chars: "\x0c" }
|
#- { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" }
|
||||||
#- { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp, }
|
#- { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp, }
|
||||||
#- { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown }
|
#- { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown }
|
||||||
#- { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop, }
|
#- { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop, }
|
||||||
#- { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom }
|
#- { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom }
|
||||||
|
|
||||||
# Vi Mode
|
# Vi Mode
|
||||||
#- { key: Space, mods: Shift|Control, mode: Vi, action: ScrollToBottom }
|
#- { key: Space, mods: Shift|Control, mode: Vi|~Search, action: ScrollToBottom }
|
||||||
#- { key: Space, mods: Shift|Control, action: ToggleViMode }
|
#- { key: Space, mods: Shift|Control, mode: ~Search, action: ToggleViMode }
|
||||||
#- { key: Escape, mode: Vi, action: ClearSelection }
|
#- { key: Escape, mode: Vi|~Search, action: ClearSelection }
|
||||||
#- { key: I, mode: Vi, action: ScrollToBottom }
|
#- { key: I, mode: Vi|~Search, action: ScrollToBottom }
|
||||||
#- { key: I, mode: Vi, action: ToggleViMode }
|
#- { key: I, mode: Vi|~Search, action: ToggleViMode }
|
||||||
#- { key: C, mods: Control, mode: Vi, action: ToggleViMode }
|
#- { key: C, mods: Control, mode: Vi|~Search, action: ToggleViMode }
|
||||||
#- { key: Y, mods: Control, mode: Vi, action: ScrollLineUp }
|
#- { key: Y, mods: Control, mode: Vi|~Search, action: ScrollLineUp }
|
||||||
#- { key: E, mods: Control, mode: Vi, action: ScrollLineDown }
|
#- { key: E, mods: Control, mode: Vi|~Search, action: ScrollLineDown }
|
||||||
#- { key: G, mode: Vi, action: ScrollToTop }
|
#- { key: G, mode: Vi|~Search, action: ScrollToTop }
|
||||||
#- { key: G, mods: Shift, mode: Vi, action: ScrollToBottom }
|
#- { key: G, mods: Shift, mode: Vi|~Search, action: ScrollToBottom }
|
||||||
#- { key: B, mods: Control, mode: Vi, action: ScrollPageUp }
|
#- { key: B, mods: Control, mode: Vi|~Search, action: ScrollPageUp }
|
||||||
#- { key: F, mods: Control, mode: Vi, action: ScrollPageDown }
|
#- { key: F, mods: Control, mode: Vi|~Search, action: ScrollPageDown }
|
||||||
#- { key: U, mods: Control, mode: Vi, action: ScrollHalfPageUp }
|
#- { key: U, mods: Control, mode: Vi|~Search, action: ScrollHalfPageUp }
|
||||||
#- { key: D, mods: Control, mode: Vi, action: ScrollHalfPageDown }
|
#- { key: D, mods: Control, mode: Vi|~Search, action: ScrollHalfPageDown }
|
||||||
#- { key: Y, mode: Vi, action: Copy }
|
#- { key: Y, mode: Vi|~Search, action: Copy }
|
||||||
#- { key: Y, mode: Vi, action: ClearSelection }
|
#- { key: Y, mode: Vi|~Search, action: ClearSelection }
|
||||||
#- { key: Copy, mode: Vi, action: ClearSelection }
|
#- { key: Copy, mode: Vi|~Search, action: ClearSelection }
|
||||||
#- { key: V, mode: Vi, action: ToggleNormalSelection }
|
#- { key: V, mode: Vi|~Search, action: ToggleNormalSelection }
|
||||||
#- { key: V, mods: Shift, mode: Vi, action: ToggleLineSelection }
|
#- { key: V, mods: Shift, mode: Vi|~Search, action: ToggleLineSelection }
|
||||||
#- { key: V, mods: Control, mode: Vi, action: ToggleBlockSelection }
|
#- { key: V, mods: Control, mode: Vi|~Search, action: ToggleBlockSelection }
|
||||||
#- { key: V, mods: Alt, mode: Vi, action: ToggleSemanticSelection }
|
#- { key: V, mods: Alt, mode: Vi|~Search, action: ToggleSemanticSelection }
|
||||||
#- { key: Return, mode: Vi, action: Open }
|
#- { key: Return, mode: Vi|~Search, action: Open }
|
||||||
#- { key: K, mode: Vi, action: Up }
|
#- { key: K, mode: Vi|~Search, action: Up }
|
||||||
#- { key: J, mode: Vi, action: Down }
|
#- { key: J, mode: Vi|~Search, action: Down }
|
||||||
#- { key: H, mode: Vi, action: Left }
|
#- { key: H, mode: Vi|~Search, action: Left }
|
||||||
#- { key: L, mode: Vi, action: Right }
|
#- { key: L, mode: Vi|~Search, action: Right }
|
||||||
#- { key: Up, mode: Vi, action: Up }
|
#- { key: Up, mode: Vi|~Search, action: Up }
|
||||||
#- { key: Down, mode: Vi, action: Down }
|
#- { key: Down, mode: Vi|~Search, action: Down }
|
||||||
#- { key: Left, mode: Vi, action: Left }
|
#- { key: Left, mode: Vi|~Search, action: Left }
|
||||||
#- { key: Right, mode: Vi, action: Right }
|
#- { key: Right, mode: Vi|~Search, action: Right }
|
||||||
#- { key: Key0, mode: Vi, action: First }
|
#- { key: Key0, mode: Vi|~Search, action: First }
|
||||||
#- { key: Key4, mods: Shift, mode: Vi, action: Last }
|
#- { key: Key4, mods: Shift, mode: Vi|~Search, action: Last }
|
||||||
#- { key: Key6, mods: Shift, mode: Vi, action: FirstOccupied }
|
#- { key: Key6, mods: Shift, mode: Vi|~Search, action: FirstOccupied }
|
||||||
#- { key: H, mods: Shift, mode: Vi, action: High }
|
#- { key: H, mods: Shift, mode: Vi|~Search, action: High }
|
||||||
#- { key: M, mods: Shift, mode: Vi, action: Middle }
|
#- { key: M, mods: Shift, mode: Vi|~Search, action: Middle }
|
||||||
#- { key: L, mods: Shift, mode: Vi, action: Low }
|
#- { key: L, mods: Shift, mode: Vi|~Search, action: Low }
|
||||||
#- { key: B, mode: Vi, action: SemanticLeft }
|
#- { key: B, mode: Vi|~Search, action: SemanticLeft }
|
||||||
#- { key: W, mode: Vi, action: SemanticRight }
|
#- { key: W, mode: Vi|~Search, action: SemanticRight }
|
||||||
#- { key: E, mode: Vi, action: SemanticRightEnd }
|
#- { key: E, mode: Vi|~Search, action: SemanticRightEnd }
|
||||||
#- { key: B, mods: Shift, mode: Vi, action: WordLeft }
|
#- { key: B, mods: Shift, mode: Vi|~Search, action: WordLeft }
|
||||||
#- { key: W, mods: Shift, mode: Vi, action: WordRight }
|
#- { key: W, mods: Shift, mode: Vi|~Search, action: WordRight }
|
||||||
#- { key: E, mods: Shift, mode: Vi, action: WordRightEnd }
|
#- { key: E, mods: Shift, mode: Vi|~Search, action: WordRightEnd }
|
||||||
#- { key: Key5, mods: Shift, mode: Vi, action: Bracket }
|
#- { key: Key5, mods: Shift, mode: Vi|~Search, action: Bracket }
|
||||||
#- { key: Slash, mode: Vi, action: SearchForward }
|
#- { key: Slash, mode: Vi|~Search, action: SearchForward }
|
||||||
#- { key: Slash, mods: Shift, mode: Vi, action: SearchBackward }
|
#- { key: Slash, mods: Shift, mode: Vi|~Search, action: SearchBackward }
|
||||||
#- { key: N, mode: Vi, action: SearchNext }
|
#- { key: N, mode: Vi|~Search, action: SearchNext }
|
||||||
#- { key: N, mods: Shift, mode: Vi, action: SearchPrevious }
|
#- { key: N, mods: Shift, mode: Vi|~Search, action: SearchPrevious }
|
||||||
|
|
||||||
|
# Search Mode
|
||||||
|
#- { key: Return, mode: Search|Vi, action: SearchConfirm }
|
||||||
|
#- { key: Escape, mode: Search, action: SearchCancel }
|
||||||
|
#- { key: U, mods: Control, mode: Search, action: SearchClear }
|
||||||
|
#- { key: W, mods: Control, mode: Search, action: SearchDeleteWord }
|
||||||
|
#- { key: Return, mode: Search|~Vi, action: SearchFocusNext }
|
||||||
|
#- { key: Return, mods: Shift, mode: Search|~Vi, action: SearchFocusPrevious }
|
||||||
|
|
||||||
# (Windows, Linux, and BSD only)
|
# (Windows, Linux, and BSD only)
|
||||||
#- { key: V, mods: Control|Shift, action: Paste }
|
#- { key: V, mods: Control|Shift, mode: ~Vi, action: Paste }
|
||||||
#- { key: C, mods: Control|Shift, action: Copy }
|
#- { key: C, mods: Control|Shift, action: Copy }
|
||||||
#- { key: F, mods: Control|Shift, action: SearchForward }
|
#- { key: F, mods: Control|Shift, mode: ~Search, action: SearchForward }
|
||||||
#- { key: B, mods: Control|Shift, action: SearchBackward }
|
#- { key: B, mods: Control|Shift, mode: ~Search, action: SearchBackward }
|
||||||
#- { key: C, mods: Control|Shift, mode: Vi, action: ClearSelection }
|
#- { key: C, mods: Control|Shift, mode: Vi|~Search, action: ClearSelection }
|
||||||
#- { key: Insert, mods: Shift, action: PasteSelection }
|
#- { key: Insert, mods: Shift, action: PasteSelection }
|
||||||
#- { key: Key0, mods: Control, action: ResetFontSize }
|
#- { key: Key0, mods: Control, action: ResetFontSize }
|
||||||
#- { key: Equals, mods: Control, action: IncreaseFontSize }
|
#- { key: Equals, mods: Control, action: IncreaseFontSize }
|
||||||
|
@ -740,25 +761,25 @@
|
||||||
#- { key: Return, mods: Alt, action: ToggleFullscreen }
|
#- { key: Return, mods: Alt, action: ToggleFullscreen }
|
||||||
|
|
||||||
# (macOS only)
|
# (macOS only)
|
||||||
#- { key: K, mods: Command, mode: ~Vi, chars: "\x0c" }
|
#- { key: K, mods: Command, mode: ~Vi|~Search, chars: "\x0c" }
|
||||||
|
#- { key: K, mods: Command, mode: ~Vi|~Search, action: ClearHistory }
|
||||||
#- { key: Key0, mods: Command, action: ResetFontSize }
|
#- { key: Key0, mods: Command, action: ResetFontSize }
|
||||||
#- { key: Equals, mods: Command, action: IncreaseFontSize }
|
#- { key: Equals, mods: Command, action: IncreaseFontSize }
|
||||||
#- { key: Plus, mods: Command, action: IncreaseFontSize }
|
#- { key: Plus, mods: Command, action: IncreaseFontSize }
|
||||||
#- { key: NumpadAdd, mods: Command, action: IncreaseFontSize }
|
#- { key: NumpadAdd, mods: Command, action: IncreaseFontSize }
|
||||||
#- { key: Minus, mods: Command, action: DecreaseFontSize }
|
#- { key: Minus, mods: Command, action: DecreaseFontSize }
|
||||||
#- { key: NumpadSubtract, mods: Command, action: DecreaseFontSize }
|
#- { key: NumpadSubtract, mods: Command, action: DecreaseFontSize }
|
||||||
#- { key: K, mods: Command, action: ClearHistory }
|
|
||||||
#- { key: V, mods: Command, action: Paste }
|
#- { key: V, mods: Command, action: Paste }
|
||||||
#- { key: C, mods: Command, action: Copy }
|
#- { key: C, mods: Command, action: Copy }
|
||||||
#- { key: C, mods: Command, mode: Vi, action: ClearSelection }
|
#- { key: C, mods: Command, mode: Vi|~Search, action: ClearSelection }
|
||||||
#- { key: H, mods: Command, action: Hide }
|
#- { key: H, mods: Command, action: Hide }
|
||||||
#- { key: M, mods: Command, action: Minimize }
|
#- { key: M, mods: Command, action: Minimize }
|
||||||
#- { key: Q, mods: Command, action: Quit }
|
#- { key: Q, mods: Command, action: Quit }
|
||||||
#- { key: W, mods: Command, action: Quit }
|
#- { key: W, mods: Command, action: Quit }
|
||||||
#- { key: N, mods: Command, action: SpawnNewInstance }
|
#- { key: N, mods: Command, action: SpawnNewInstance }
|
||||||
#- { key: F, mods: Command|Control, action: ToggleFullscreen }
|
#- { key: F, mods: Command|Control, action: ToggleFullscreen }
|
||||||
#- { key: F, mods: Command, action: SearchForward }
|
#- { key: F, mods: Command, mode: ~Search, action: SearchForward }
|
||||||
#- { key: B, mods: Command, action: SearchBackward }
|
#- { key: B, mods: Command, mode: ~Search, action: SearchBackward }
|
||||||
|
|
||||||
#debug:
|
#debug:
|
||||||
# Display the time it takes to redraw each frame.
|
# Display the time it takes to redraw each frame.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::fmt::{self, Debug, Display};
|
use std::fmt::{self, Debug, Display};
|
||||||
|
|
||||||
|
use bitflags::bitflags;
|
||||||
use glutin::event::VirtualKeyCode::*;
|
use glutin::event::VirtualKeyCode::*;
|
||||||
use glutin::event::{ModifiersState, MouseButton, VirtualKeyCode};
|
use glutin::event::{ModifiersState, MouseButton, VirtualKeyCode};
|
||||||
use serde::de::Error as SerdeError;
|
use serde::de::Error as SerdeError;
|
||||||
|
@ -24,11 +25,11 @@ pub struct Binding<T> {
|
||||||
/// String to send to PTY if mods and mode match.
|
/// String to send to PTY if mods and mode match.
|
||||||
pub action: Action,
|
pub action: Action,
|
||||||
|
|
||||||
/// Terminal mode required to activate binding.
|
/// Binding mode required to activate binding.
|
||||||
pub mode: TermMode,
|
pub mode: BindingMode,
|
||||||
|
|
||||||
/// excluded terminal modes where the binding won't be activated.
|
/// Excluded binding modes where the binding won't be activated.
|
||||||
pub notmode: TermMode,
|
pub notmode: BindingMode,
|
||||||
|
|
||||||
/// This property is used as part of the trigger detection code.
|
/// This property is used as part of the trigger detection code.
|
||||||
///
|
///
|
||||||
|
@ -44,7 +45,7 @@ pub type MouseBinding = Binding<MouseButton>;
|
||||||
|
|
||||||
impl<T: Eq> Binding<T> {
|
impl<T: Eq> Binding<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_triggered_by(&self, mode: TermMode, mods: ModifiersState, input: &T) -> bool {
|
pub fn is_triggered_by(&self, mode: BindingMode, mods: ModifiersState, input: &T) -> bool {
|
||||||
// Check input first since bindings are stored in one big list. This is
|
// Check input first since bindings are stored in one big list. This is
|
||||||
// the most likely item to fail so prioritizing it here allows more
|
// the most likely item to fail so prioritizing it here allows more
|
||||||
// checks to be short circuited.
|
// checks to be short circuited.
|
||||||
|
@ -61,8 +62,8 @@ impl<T: Eq> Binding<T> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selfmode = if self.mode.is_empty() { TermMode::ANY } else { self.mode };
|
let selfmode = if self.mode.is_empty() { BindingMode::all() } else { self.mode };
|
||||||
let bindingmode = if binding.mode.is_empty() { TermMode::ANY } else { binding.mode };
|
let bindingmode = if binding.mode.is_empty() { BindingMode::all() } else { binding.mode };
|
||||||
|
|
||||||
if !selfmode.intersects(bindingmode) {
|
if !selfmode.intersects(bindingmode) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -96,6 +97,10 @@ pub enum Action {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
ViAction(ViAction),
|
ViAction(ViAction),
|
||||||
|
|
||||||
|
/// Perform search mode action.
|
||||||
|
#[serde(skip)]
|
||||||
|
SearchAction(SearchAction),
|
||||||
|
|
||||||
/// Paste contents of system clipboard.
|
/// Paste contents of system clipboard.
|
||||||
Paste,
|
Paste,
|
||||||
|
|
||||||
|
@ -192,6 +197,24 @@ impl From<&'static str> for Action {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ViAction> for Action {
|
||||||
|
fn from(action: ViAction) -> Self {
|
||||||
|
Self::ViAction(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ViMotion> for Action {
|
||||||
|
fn from(motion: ViMotion) -> Self {
|
||||||
|
Self::ViMotion(motion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SearchAction> for Action {
|
||||||
|
fn from(action: SearchAction) -> Self {
|
||||||
|
Self::SearchAction(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Display trait used for error logging.
|
/// Display trait used for error logging.
|
||||||
impl Display for Action {
|
impl Display for Action {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
@ -226,16 +249,21 @@ pub enum ViAction {
|
||||||
Open,
|
Open,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ViAction> for Action {
|
/// Search mode specific actions.
|
||||||
fn from(action: ViAction) -> Self {
|
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
Self::ViAction(action)
|
pub enum SearchAction {
|
||||||
}
|
/// Move the focus to the next search match.
|
||||||
}
|
SearchFocusNext,
|
||||||
|
/// Move the focus to the previous search match.
|
||||||
impl From<ViMotion> for Action {
|
SearchFocusPrevious,
|
||||||
fn from(motion: ViMotion) -> Self {
|
/// Confirm the active search.
|
||||||
Self::ViMotion(motion)
|
SearchConfirm,
|
||||||
}
|
/// Cancel the active search.
|
||||||
|
SearchCancel,
|
||||||
|
/// Reset the search regex.
|
||||||
|
SearchClear,
|
||||||
|
/// Delete the last word in the search regex.
|
||||||
|
SearchDeleteWord,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! bindings {
|
macro_rules! bindings {
|
||||||
|
@ -277,9 +305,9 @@ macro_rules! bindings {
|
||||||
$(
|
$(
|
||||||
let mut _mods = ModifiersState::empty();
|
let mut _mods = ModifiersState::empty();
|
||||||
$(_mods = $mods;)*
|
$(_mods = $mods;)*
|
||||||
let mut _mode = TermMode::empty();
|
let mut _mode = BindingMode::empty();
|
||||||
$(_mode.insert($mode);)*
|
$(_mode.insert($mode);)*
|
||||||
let mut _notmode = TermMode::empty();
|
let mut _notmode = BindingMode::empty();
|
||||||
$(_notmode.insert($notmode);)*
|
$(_notmode.insert($notmode);)*
|
||||||
|
|
||||||
v.push($ty {
|
v.push($ty {
|
||||||
|
@ -298,7 +326,7 @@ macro_rules! bindings {
|
||||||
pub fn default_mouse_bindings() -> Vec<MouseBinding> {
|
pub fn default_mouse_bindings() -> Vec<MouseBinding> {
|
||||||
bindings!(
|
bindings!(
|
||||||
MouseBinding;
|
MouseBinding;
|
||||||
MouseButton::Middle, ~TermMode::VI; Action::PasteSelection;
|
MouseButton::Middle, ~BindingMode::VI; Action::PasteSelection;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,109 +334,179 @@ pub fn default_key_bindings() -> Vec<KeyBinding> {
|
||||||
let mut bindings = bindings!(
|
let mut bindings = bindings!(
|
||||||
KeyBinding;
|
KeyBinding;
|
||||||
Copy; Action::Copy;
|
Copy; Action::Copy;
|
||||||
Copy, +TermMode::VI; Action::ClearSelection;
|
Copy, +BindingMode::VI; Action::ClearSelection;
|
||||||
Paste, ~TermMode::VI; Action::Paste;
|
Paste, ~BindingMode::VI; Action::Paste;
|
||||||
L, ModifiersState::CTRL; Action::ClearLogNotice;
|
L, ModifiersState::CTRL; Action::ClearLogNotice;
|
||||||
L, ModifiersState::CTRL, ~TermMode::VI; Action::Esc("\x0c".into());
|
L, ModifiersState::CTRL, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Tab, ModifiersState::SHIFT, ~TermMode::VI; Action::Esc("\x1b[Z".into());
|
Action::Esc("\x0c".into());
|
||||||
Back, ModifiersState::ALT, ~TermMode::VI; Action::Esc("\x1b\x7f".into());
|
Tab, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Back, ModifiersState::SHIFT, ~TermMode::VI; Action::Esc("\x7f".into());
|
Action::Esc("\x1b[Z".into());
|
||||||
Home, ModifiersState::SHIFT, ~TermMode::ALT_SCREEN; Action::ScrollToTop;
|
Back, ModifiersState::ALT, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
End, ModifiersState::SHIFT, ~TermMode::ALT_SCREEN; Action::ScrollToBottom;
|
Action::Esc("\x1b\x7f".into());
|
||||||
PageUp, ModifiersState::SHIFT, ~TermMode::ALT_SCREEN; Action::ScrollPageUp;
|
Back, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
PageDown, ModifiersState::SHIFT, ~TermMode::ALT_SCREEN; Action::ScrollPageDown;
|
Action::Esc("\x7f".into());
|
||||||
Home, ModifiersState::SHIFT, +TermMode::ALT_SCREEN, ~TermMode::VI;
|
Home, ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollToTop;
|
||||||
Action::Esc("\x1b[1;2H".into());
|
End, ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollToBottom;
|
||||||
End, ModifiersState::SHIFT, +TermMode::ALT_SCREEN, ~TermMode::VI;
|
PageUp, ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollPageUp;
|
||||||
Action::Esc("\x1b[1;2F".into());
|
PageDown, ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollPageDown;
|
||||||
PageUp, ModifiersState::SHIFT, +TermMode::ALT_SCREEN, ~TermMode::VI;
|
Home, ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
|
||||||
Action::Esc("\x1b[5;2~".into());
|
~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[1;2H".into());
|
||||||
PageDown, ModifiersState::SHIFT, +TermMode::ALT_SCREEN, ~TermMode::VI;
|
End, ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
|
||||||
Action::Esc("\x1b[6;2~".into());
|
~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[1;2F".into());
|
||||||
Home, +TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1bOH".into());
|
PageUp, ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
|
||||||
Home, ~TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1b[H".into());
|
~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[5;2~".into());
|
||||||
End, +TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1bOF".into());
|
PageDown, ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
|
||||||
End, ~TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1b[F".into());
|
~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[6;2~".into());
|
||||||
Up, +TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1bOA".into());
|
Home, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Up, ~TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1b[A".into());
|
Action::Esc("\x1bOH".into());
|
||||||
Down, +TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1bOB".into());
|
Home, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Down, ~TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1b[B".into());
|
Action::Esc("\x1b[H".into());
|
||||||
Right, +TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1bOC".into());
|
End, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Right, ~TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1b[C".into());
|
Action::Esc("\x1bOF".into());
|
||||||
Left, +TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1bOD".into());
|
End, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Left, ~TermMode::APP_CURSOR, ~TermMode::VI; Action::Esc("\x1b[D".into());
|
Action::Esc("\x1b[F".into());
|
||||||
Back, ~TermMode::VI; Action::Esc("\x7f".into());
|
Up, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Insert, ~TermMode::VI; Action::Esc("\x1b[2~".into());
|
Action::Esc("\x1bOA".into());
|
||||||
Delete, ~TermMode::VI; Action::Esc("\x1b[3~".into());
|
Up, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
PageUp, ~TermMode::VI; Action::Esc("\x1b[5~".into());
|
Action::Esc("\x1b[A".into());
|
||||||
PageDown, ~TermMode::VI; Action::Esc("\x1b[6~".into());
|
Down, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F1, ~TermMode::VI; Action::Esc("\x1bOP".into());
|
Action::Esc("\x1bOB".into());
|
||||||
F2, ~TermMode::VI; Action::Esc("\x1bOQ".into());
|
Down, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F3, ~TermMode::VI; Action::Esc("\x1bOR".into());
|
Action::Esc("\x1b[B".into());
|
||||||
F4, ~TermMode::VI; Action::Esc("\x1bOS".into());
|
Right, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F5, ~TermMode::VI; Action::Esc("\x1b[15~".into());
|
Action::Esc("\x1bOC".into());
|
||||||
F6, ~TermMode::VI; Action::Esc("\x1b[17~".into());
|
Right, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F7, ~TermMode::VI; Action::Esc("\x1b[18~".into());
|
Action::Esc("\x1b[C".into());
|
||||||
F8, ~TermMode::VI; Action::Esc("\x1b[19~".into());
|
Left, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F9, ~TermMode::VI; Action::Esc("\x1b[20~".into());
|
Action::Esc("\x1bOD".into());
|
||||||
F10, ~TermMode::VI; Action::Esc("\x1b[21~".into());
|
Left, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F11, ~TermMode::VI; Action::Esc("\x1b[23~".into());
|
Action::Esc("\x1b[D".into());
|
||||||
F12, ~TermMode::VI; Action::Esc("\x1b[24~".into());
|
Back, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x7f".into());
|
||||||
F13, ~TermMode::VI; Action::Esc("\x1b[25~".into());
|
Insert, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[2~".into());
|
||||||
F14, ~TermMode::VI; Action::Esc("\x1b[26~".into());
|
Delete, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[3~".into());
|
||||||
F15, ~TermMode::VI; Action::Esc("\x1b[28~".into());
|
PageUp, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[5~".into());
|
||||||
F16, ~TermMode::VI; Action::Esc("\x1b[29~".into());
|
PageDown, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[6~".into());
|
||||||
F17, ~TermMode::VI; Action::Esc("\x1b[31~".into());
|
F1, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOP".into());
|
||||||
F18, ~TermMode::VI; Action::Esc("\x1b[32~".into());
|
F2, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOQ".into());
|
||||||
F19, ~TermMode::VI; Action::Esc("\x1b[33~".into());
|
F3, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOR".into());
|
||||||
F20, ~TermMode::VI; Action::Esc("\x1b[34~".into());
|
F4, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOS".into());
|
||||||
NumpadEnter, ~TermMode::VI; Action::Esc("\n".into());
|
F5, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[15~".into());
|
||||||
Space, ModifiersState::SHIFT | ModifiersState::CTRL, +TermMode::VI; Action::ScrollToBottom;
|
F6, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[17~".into());
|
||||||
Space, ModifiersState::SHIFT | ModifiersState::CTRL; Action::ToggleViMode;
|
F7, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[18~".into());
|
||||||
Escape, +TermMode::VI; Action::ClearSelection;
|
F8, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[19~".into());
|
||||||
I, +TermMode::VI; Action::ScrollToBottom;
|
F9, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[20~".into());
|
||||||
I, +TermMode::VI; Action::ToggleViMode;
|
F10, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[21~".into());
|
||||||
C, ModifiersState::CTRL, +TermMode::VI; Action::ToggleViMode;
|
F11, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[23~".into());
|
||||||
Y, ModifiersState::CTRL, +TermMode::VI; Action::ScrollLineUp;
|
F12, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[24~".into());
|
||||||
E, ModifiersState::CTRL, +TermMode::VI; Action::ScrollLineDown;
|
F13, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[25~".into());
|
||||||
G, +TermMode::VI; Action::ScrollToTop;
|
F14, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[26~".into());
|
||||||
G, ModifiersState::SHIFT, +TermMode::VI; Action::ScrollToBottom;
|
F15, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[28~".into());
|
||||||
B, ModifiersState::CTRL, +TermMode::VI; Action::ScrollPageUp;
|
F16, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[29~".into());
|
||||||
F, ModifiersState::CTRL, +TermMode::VI; Action::ScrollPageDown;
|
F17, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[31~".into());
|
||||||
U, ModifiersState::CTRL, +TermMode::VI; Action::ScrollHalfPageUp;
|
F18, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[32~".into());
|
||||||
D, ModifiersState::CTRL, +TermMode::VI; Action::ScrollHalfPageDown;
|
F19, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[33~".into());
|
||||||
Y, +TermMode::VI; Action::Copy;
|
F20, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[34~".into());
|
||||||
Y, +TermMode::VI; Action::ClearSelection;
|
NumpadEnter, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\n".into());
|
||||||
Slash, +TermMode::VI; Action::SearchForward;
|
Space, ModifiersState::SHIFT | ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Slash, ModifiersState::SHIFT, +TermMode::VI; Action::SearchBackward;
|
Action::ScrollToBottom;
|
||||||
V, +TermMode::VI; ViAction::ToggleNormalSelection;
|
Space, ModifiersState::SHIFT | ModifiersState::CTRL, ~BindingMode::SEARCH;
|
||||||
V, ModifiersState::SHIFT, +TermMode::VI; ViAction::ToggleLineSelection;
|
Action::ToggleViMode;
|
||||||
V, ModifiersState::CTRL, +TermMode::VI; ViAction::ToggleBlockSelection;
|
Escape, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
V, ModifiersState::ALT, +TermMode::VI; ViAction::ToggleSemanticSelection;
|
Action::ClearSelection;
|
||||||
N, +TermMode::VI; ViAction::SearchNext;
|
I, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
N, ModifiersState::SHIFT, +TermMode::VI; ViAction::SearchPrevious;
|
Action::ScrollToBottom;
|
||||||
Return, +TermMode::VI; ViAction::Open;
|
I, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
K, +TermMode::VI; ViMotion::Up;
|
Action::ToggleViMode;
|
||||||
J, +TermMode::VI; ViMotion::Down;
|
C, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
H, +TermMode::VI; ViMotion::Left;
|
Action::ToggleViMode;
|
||||||
L, +TermMode::VI; ViMotion::Right;
|
Y, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Up, +TermMode::VI; ViMotion::Up;
|
Action::ScrollLineUp;
|
||||||
Down, +TermMode::VI; ViMotion::Down;
|
E, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Left, +TermMode::VI; ViMotion::Left;
|
Action::ScrollLineDown;
|
||||||
Right, +TermMode::VI; ViMotion::Right;
|
G, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Key0, +TermMode::VI; ViMotion::First;
|
Action::ScrollToTop;
|
||||||
Key4, ModifiersState::SHIFT, +TermMode::VI; ViMotion::Last;
|
G, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Key6, ModifiersState::SHIFT, +TermMode::VI; ViMotion::FirstOccupied;
|
Action::ScrollToBottom;
|
||||||
H, ModifiersState::SHIFT, +TermMode::VI; ViMotion::High;
|
B, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
M, ModifiersState::SHIFT, +TermMode::VI; ViMotion::Middle;
|
Action::ScrollPageUp;
|
||||||
L, ModifiersState::SHIFT, +TermMode::VI; ViMotion::Low;
|
F, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
B, +TermMode::VI; ViMotion::SemanticLeft;
|
Action::ScrollPageDown;
|
||||||
W, +TermMode::VI; ViMotion::SemanticRight;
|
U, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
E, +TermMode::VI; ViMotion::SemanticRightEnd;
|
Action::ScrollHalfPageUp;
|
||||||
B, ModifiersState::SHIFT, +TermMode::VI; ViMotion::WordLeft;
|
D, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
W, ModifiersState::SHIFT, +TermMode::VI; ViMotion::WordRight;
|
Action::ScrollHalfPageDown;
|
||||||
E, ModifiersState::SHIFT, +TermMode::VI; ViMotion::WordRightEnd;
|
Y, +BindingMode::VI, ~BindingMode::SEARCH; Action::Copy;
|
||||||
Key5, ModifiersState::SHIFT, +TermMode::VI; ViMotion::Bracket;
|
Y, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::ClearSelection;
|
||||||
|
Slash, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::SearchForward;
|
||||||
|
Slash, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::SearchBackward;
|
||||||
|
V, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::ToggleNormalSelection;
|
||||||
|
V, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::ToggleLineSelection;
|
||||||
|
V, ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::ToggleBlockSelection;
|
||||||
|
V, ModifiersState::ALT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::ToggleSemanticSelection;
|
||||||
|
N, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::SearchNext;
|
||||||
|
N, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::SearchPrevious;
|
||||||
|
Return, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViAction::Open;
|
||||||
|
K, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Up;
|
||||||
|
J, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Down;
|
||||||
|
H, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Left;
|
||||||
|
L, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Right;
|
||||||
|
Up, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Up;
|
||||||
|
Down, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Down;
|
||||||
|
Left, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Left;
|
||||||
|
Right, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Right;
|
||||||
|
Key0, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::First;
|
||||||
|
Key4, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Last;
|
||||||
|
Key6, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::FirstOccupied;
|
||||||
|
H, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::High;
|
||||||
|
M, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Middle;
|
||||||
|
L, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Low;
|
||||||
|
B, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::SemanticLeft;
|
||||||
|
W, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::SemanticRight;
|
||||||
|
E, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::SemanticRightEnd;
|
||||||
|
B, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::WordLeft;
|
||||||
|
W, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::WordRight;
|
||||||
|
E, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::WordRightEnd;
|
||||||
|
Key5, ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
ViMotion::Bracket;
|
||||||
|
Return, +BindingMode::SEARCH, +BindingMode::VI;
|
||||||
|
SearchAction::SearchConfirm;
|
||||||
|
Escape, +BindingMode::SEARCH; SearchAction::SearchCancel;
|
||||||
|
U, ModifiersState::CTRL, +BindingMode::SEARCH; SearchAction::SearchClear;
|
||||||
|
W, ModifiersState::CTRL, +BindingMode::SEARCH; SearchAction::SearchDeleteWord;
|
||||||
|
Return, +BindingMode::SEARCH, ~BindingMode::VI;
|
||||||
|
SearchAction::SearchFocusNext;
|
||||||
|
Return, ModifiersState::SHIFT, +BindingMode::SEARCH, ~BindingMode::VI;
|
||||||
|
SearchAction::SearchFocusPrevious;
|
||||||
);
|
);
|
||||||
|
|
||||||
// Code Modifiers
|
// Code Modifiers
|
||||||
|
@ -437,42 +535,72 @@ pub fn default_key_bindings() -> Vec<KeyBinding> {
|
||||||
let modifiers_code = index + 2;
|
let modifiers_code = index + 2;
|
||||||
bindings.extend(bindings!(
|
bindings.extend(bindings!(
|
||||||
KeyBinding;
|
KeyBinding;
|
||||||
Delete, mods, ~TermMode::VI; Action::Esc(format!("\x1b[3;{}~", modifiers_code));
|
Delete, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Up, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}A", modifiers_code));
|
Action::Esc(format!("\x1b[3;{}~", modifiers_code));
|
||||||
Down, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}B", modifiers_code));
|
Up, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
Right, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}C", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}A", modifiers_code));
|
||||||
Left, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}D", modifiers_code));
|
Down, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F1, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}P", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}B", modifiers_code));
|
||||||
F2, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}Q", modifiers_code));
|
Right, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F3, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}R", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}C", modifiers_code));
|
||||||
F4, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}S", modifiers_code));
|
Left, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F5, mods, ~TermMode::VI; Action::Esc(format!("\x1b[15;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}D", modifiers_code));
|
||||||
F6, mods, ~TermMode::VI; Action::Esc(format!("\x1b[17;{}~", modifiers_code));
|
F1, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F7, mods, ~TermMode::VI; Action::Esc(format!("\x1b[18;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}P", modifiers_code));
|
||||||
F8, mods, ~TermMode::VI; Action::Esc(format!("\x1b[19;{}~", modifiers_code));
|
F2, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F9, mods, ~TermMode::VI; Action::Esc(format!("\x1b[20;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}Q", modifiers_code));
|
||||||
F10, mods, ~TermMode::VI; Action::Esc(format!("\x1b[21;{}~", modifiers_code));
|
F3, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F11, mods, ~TermMode::VI; Action::Esc(format!("\x1b[23;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}R", modifiers_code));
|
||||||
F12, mods, ~TermMode::VI; Action::Esc(format!("\x1b[24;{}~", modifiers_code));
|
F4, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F13, mods, ~TermMode::VI; Action::Esc(format!("\x1b[25;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[1;{}S", modifiers_code));
|
||||||
F14, mods, ~TermMode::VI; Action::Esc(format!("\x1b[26;{}~", modifiers_code));
|
F5, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F15, mods, ~TermMode::VI; Action::Esc(format!("\x1b[28;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[15;{}~", modifiers_code));
|
||||||
F16, mods, ~TermMode::VI; Action::Esc(format!("\x1b[29;{}~", modifiers_code));
|
F6, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F17, mods, ~TermMode::VI; Action::Esc(format!("\x1b[31;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[17;{}~", modifiers_code));
|
||||||
F18, mods, ~TermMode::VI; Action::Esc(format!("\x1b[32;{}~", modifiers_code));
|
F7, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
F19, mods, ~TermMode::VI; Action::Esc(format!("\x1b[33;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[18;{}~", modifiers_code));
|
||||||
F20, mods, ~TermMode::VI; Action::Esc(format!("\x1b[34;{}~", modifiers_code));
|
F8, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[19;{}~", modifiers_code));
|
||||||
|
F9, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[20;{}~", modifiers_code));
|
||||||
|
F10, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[21;{}~", modifiers_code));
|
||||||
|
F11, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[23;{}~", modifiers_code));
|
||||||
|
F12, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[24;{}~", modifiers_code));
|
||||||
|
F13, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[25;{}~", modifiers_code));
|
||||||
|
F14, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[26;{}~", modifiers_code));
|
||||||
|
F15, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[28;{}~", modifiers_code));
|
||||||
|
F16, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[29;{}~", modifiers_code));
|
||||||
|
F17, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[31;{}~", modifiers_code));
|
||||||
|
F18, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[32;{}~", modifiers_code));
|
||||||
|
F19, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[33;{}~", modifiers_code));
|
||||||
|
F20, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[34;{}~", modifiers_code));
|
||||||
));
|
));
|
||||||
|
|
||||||
// We're adding the following bindings with `Shift` manually above, so skipping them here.
|
// We're adding the following bindings with `Shift` manually above, so skipping them here.
|
||||||
if modifiers_code != 2 {
|
if modifiers_code != 2 {
|
||||||
bindings.extend(bindings!(
|
bindings.extend(bindings!(
|
||||||
KeyBinding;
|
KeyBinding;
|
||||||
Insert, mods, ~TermMode::VI; Action::Esc(format!("\x1b[2;{}~", modifiers_code));
|
Insert, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
PageUp, mods, ~TermMode::VI; Action::Esc(format!("\x1b[5;{}~", modifiers_code));
|
Action::Esc(format!("\x1b[2;{}~", modifiers_code));
|
||||||
PageDown, mods, ~TermMode::VI; Action::Esc(format!("\x1b[6;{}~", modifiers_code));
|
PageUp, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
End, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}F", modifiers_code));
|
Action::Esc(format!("\x1b[5;{}~", modifiers_code));
|
||||||
Home, mods, ~TermMode::VI; Action::Esc(format!("\x1b[1;{}H", modifiers_code));
|
PageDown, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[6;{}~", modifiers_code));
|
||||||
|
End, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[1;{}F", modifiers_code));
|
||||||
|
Home, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc(format!("\x1b[1;{}H", modifiers_code));
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,12 +614,15 @@ pub fn default_key_bindings() -> Vec<KeyBinding> {
|
||||||
fn common_keybindings() -> Vec<KeyBinding> {
|
fn common_keybindings() -> Vec<KeyBinding> {
|
||||||
bindings!(
|
bindings!(
|
||||||
KeyBinding;
|
KeyBinding;
|
||||||
V, ModifiersState::CTRL | ModifiersState::SHIFT, ~TermMode::VI; Action::Paste;
|
V, ModifiersState::CTRL | ModifiersState::SHIFT, ~BindingMode::VI; Action::Paste;
|
||||||
C, ModifiersState::CTRL | ModifiersState::SHIFT; Action::Copy;
|
C, ModifiersState::CTRL | ModifiersState::SHIFT; Action::Copy;
|
||||||
F, ModifiersState::CTRL | ModifiersState::SHIFT; Action::SearchForward;
|
F, ModifiersState::CTRL | ModifiersState::SHIFT, ~BindingMode::SEARCH;
|
||||||
B, ModifiersState::CTRL | ModifiersState::SHIFT; Action::SearchBackward;
|
Action::SearchForward;
|
||||||
C, ModifiersState::CTRL | ModifiersState::SHIFT, +TermMode::VI; Action::ClearSelection;
|
B, ModifiersState::CTRL | ModifiersState::SHIFT, ~BindingMode::SEARCH;
|
||||||
Insert, ModifiersState::SHIFT, ~TermMode::VI; Action::PasteSelection;
|
Action::SearchBackward;
|
||||||
|
C, ModifiersState::CTRL | ModifiersState::SHIFT,
|
||||||
|
+BindingMode::VI, ~BindingMode::SEARCH; Action::ClearSelection;
|
||||||
|
Insert, ModifiersState::SHIFT, ~BindingMode::VI; Action::PasteSelection;
|
||||||
Key0, ModifiersState::CTRL; Action::ResetFontSize;
|
Key0, ModifiersState::CTRL; Action::ResetFontSize;
|
||||||
Equals, ModifiersState::CTRL; Action::IncreaseFontSize;
|
Equals, ModifiersState::CTRL; Action::IncreaseFontSize;
|
||||||
Plus, ModifiersState::CTRL; Action::IncreaseFontSize;
|
Plus, ModifiersState::CTRL; Action::IncreaseFontSize;
|
||||||
|
@ -526,20 +657,22 @@ pub fn platform_key_bindings() -> Vec<KeyBinding> {
|
||||||
NumpadAdd, ModifiersState::LOGO; Action::IncreaseFontSize;
|
NumpadAdd, ModifiersState::LOGO; Action::IncreaseFontSize;
|
||||||
Minus, ModifiersState::LOGO; Action::DecreaseFontSize;
|
Minus, ModifiersState::LOGO; Action::DecreaseFontSize;
|
||||||
NumpadSubtract, ModifiersState::LOGO; Action::DecreaseFontSize;
|
NumpadSubtract, ModifiersState::LOGO; Action::DecreaseFontSize;
|
||||||
Insert, ModifiersState::SHIFT, ~TermMode::VI; Action::Esc("\x1b[2;2~".into());
|
Insert, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
K, ModifiersState::LOGO, ~TermMode::VI; Action::Esc("\x0c".into());
|
Action::Esc("\x1b[2;2~".into());
|
||||||
V, ModifiersState::LOGO, ~TermMode::VI; Action::Paste;
|
K, ModifiersState::LOGO, ~BindingMode::VI, ~BindingMode::SEARCH;
|
||||||
|
Action::Esc("\x0c".into());
|
||||||
|
K, ModifiersState::LOGO, ~BindingMode::VI, ~BindingMode::SEARCH; Action::ClearHistory;
|
||||||
|
V, ModifiersState::LOGO, ~BindingMode::VI; Action::Paste;
|
||||||
N, ModifiersState::LOGO; Action::SpawnNewInstance;
|
N, ModifiersState::LOGO; Action::SpawnNewInstance;
|
||||||
F, ModifiersState::CTRL | ModifiersState::LOGO; Action::ToggleFullscreen;
|
F, ModifiersState::CTRL | ModifiersState::LOGO; Action::ToggleFullscreen;
|
||||||
K, ModifiersState::LOGO; Action::ClearHistory;
|
|
||||||
C, ModifiersState::LOGO; Action::Copy;
|
C, ModifiersState::LOGO; Action::Copy;
|
||||||
C, ModifiersState::LOGO, +TermMode::VI; Action::ClearSelection;
|
C, ModifiersState::LOGO, +BindingMode::VI, ~BindingMode::SEARCH; Action::ClearSelection;
|
||||||
H, ModifiersState::LOGO; Action::Hide;
|
H, ModifiersState::LOGO; Action::Hide;
|
||||||
M, ModifiersState::LOGO; Action::Minimize;
|
M, ModifiersState::LOGO; Action::Minimize;
|
||||||
Q, ModifiersState::LOGO; Action::Quit;
|
Q, ModifiersState::LOGO; Action::Quit;
|
||||||
W, ModifiersState::LOGO; Action::Quit;
|
W, ModifiersState::LOGO; Action::Quit;
|
||||||
F, ModifiersState::LOGO; Action::SearchForward;
|
F, ModifiersState::LOGO, ~BindingMode::SEARCH; Action::SearchForward;
|
||||||
B, ModifiersState::LOGO; Action::SearchBackward;
|
B, ModifiersState::LOGO, ~BindingMode::SEARCH; Action::SearchBackward;
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,8 +705,31 @@ impl<'a> Deserialize<'a> for Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModeWrapper {
|
struct ModeWrapper {
|
||||||
pub mode: TermMode,
|
pub mode: BindingMode,
|
||||||
pub not_mode: TermMode,
|
pub not_mode: BindingMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Modes available for key bindings.
|
||||||
|
pub struct BindingMode: u8 {
|
||||||
|
const APP_CURSOR = 0b0000_0001;
|
||||||
|
const APP_KEYPAD = 0b0000_0010;
|
||||||
|
const ALT_SCREEN = 0b0000_0100;
|
||||||
|
const VI = 0b0000_1000;
|
||||||
|
const SEARCH = 0b0001_0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BindingMode {
|
||||||
|
pub fn new(mode: &TermMode, search: bool) -> BindingMode {
|
||||||
|
let mut binding_mode = BindingMode::empty();
|
||||||
|
binding_mode.set(BindingMode::APP_CURSOR, mode.contains(TermMode::APP_CURSOR));
|
||||||
|
binding_mode.set(BindingMode::APP_KEYPAD, mode.contains(TermMode::APP_KEYPAD));
|
||||||
|
binding_mode.set(BindingMode::ALT_SCREEN, mode.contains(TermMode::ALT_SCREEN));
|
||||||
|
binding_mode.set(BindingMode::VI, mode.contains(TermMode::VI));
|
||||||
|
binding_mode.set(BindingMode::SEARCH, search);
|
||||||
|
binding_mode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Deserialize<'a> for ModeWrapper {
|
impl<'a> Deserialize<'a> for ModeWrapper {
|
||||||
|
@ -596,18 +752,21 @@ impl<'a> Deserialize<'a> for ModeWrapper {
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
let mut res = ModeWrapper { mode: TermMode::empty(), not_mode: TermMode::empty() };
|
let mut res =
|
||||||
|
ModeWrapper { mode: BindingMode::empty(), not_mode: BindingMode::empty() };
|
||||||
|
|
||||||
for modifier in value.split('|') {
|
for modifier in value.split('|') {
|
||||||
match modifier.trim().to_lowercase().as_str() {
|
match modifier.trim().to_lowercase().as_str() {
|
||||||
"appcursor" => res.mode |= TermMode::APP_CURSOR,
|
"appcursor" => res.mode |= BindingMode::APP_CURSOR,
|
||||||
"~appcursor" => res.not_mode |= TermMode::APP_CURSOR,
|
"~appcursor" => res.not_mode |= BindingMode::APP_CURSOR,
|
||||||
"appkeypad" => res.mode |= TermMode::APP_KEYPAD,
|
"appkeypad" => res.mode |= BindingMode::APP_KEYPAD,
|
||||||
"~appkeypad" => res.not_mode |= TermMode::APP_KEYPAD,
|
"~appkeypad" => res.not_mode |= BindingMode::APP_KEYPAD,
|
||||||
"alt" => res.mode |= TermMode::ALT_SCREEN,
|
"alt" => res.mode |= BindingMode::ALT_SCREEN,
|
||||||
"~alt" => res.not_mode |= TermMode::ALT_SCREEN,
|
"~alt" => res.not_mode |= BindingMode::ALT_SCREEN,
|
||||||
"vi" => res.mode |= TermMode::VI,
|
"vi" => res.mode |= BindingMode::VI,
|
||||||
"~vi" => res.not_mode |= TermMode::VI,
|
"~vi" => res.not_mode |= BindingMode::VI,
|
||||||
|
"search" => res.mode |= BindingMode::SEARCH,
|
||||||
|
"~search" => res.not_mode |= BindingMode::SEARCH,
|
||||||
_ => return Err(E::invalid_value(Unexpected::Str(modifier), &self)),
|
_ => return Err(E::invalid_value(Unexpected::Str(modifier), &self)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,8 +834,8 @@ struct RawBinding {
|
||||||
key: Option<Key>,
|
key: Option<Key>,
|
||||||
mouse: Option<MouseButton>,
|
mouse: Option<MouseButton>,
|
||||||
mods: ModifiersState,
|
mods: ModifiersState,
|
||||||
mode: TermMode,
|
mode: BindingMode,
|
||||||
notmode: TermMode,
|
notmode: BindingMode,
|
||||||
action: Action,
|
action: Action,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,8 +937,8 @@ impl<'a> Deserialize<'a> for RawBinding {
|
||||||
let mut key: Option<Key> = None;
|
let mut key: Option<Key> = None;
|
||||||
let mut chars: Option<String> = None;
|
let mut chars: Option<String> = None;
|
||||||
let mut action: Option<Action> = None;
|
let mut action: Option<Action> = None;
|
||||||
let mut mode: Option<TermMode> = None;
|
let mut mode: Option<BindingMode> = None;
|
||||||
let mut not_mode: Option<TermMode> = None;
|
let mut not_mode: Option<BindingMode> = None;
|
||||||
let mut mouse: Option<MouseButton> = None;
|
let mut mouse: Option<MouseButton> = None;
|
||||||
let mut command: Option<Program> = None;
|
let mut command: Option<Program> = None;
|
||||||
|
|
||||||
|
@ -834,6 +993,10 @@ impl<'a> Deserialize<'a> for RawBinding {
|
||||||
Some(vi_action.into())
|
Some(vi_action.into())
|
||||||
} else if let Ok(vi_motion) = ViMotion::deserialize(value.clone()) {
|
} else if let Ok(vi_motion) = ViMotion::deserialize(value.clone()) {
|
||||||
Some(vi_motion.into())
|
Some(vi_motion.into())
|
||||||
|
} else if let Ok(search_action) =
|
||||||
|
SearchAction::deserialize(value.clone())
|
||||||
|
{
|
||||||
|
Some(search_action.into())
|
||||||
} else {
|
} else {
|
||||||
match Action::deserialize(value.clone()).map_err(V::Error::custom) {
|
match Action::deserialize(value.clone()).map_err(V::Error::custom) {
|
||||||
Ok(action) => Some(action),
|
Ok(action) => Some(action),
|
||||||
|
@ -883,14 +1046,15 @@ impl<'a> Deserialize<'a> for RawBinding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode = mode.unwrap_or_else(TermMode::empty);
|
let mode = mode.unwrap_or_else(BindingMode::empty);
|
||||||
let not_mode = not_mode.unwrap_or_else(TermMode::empty);
|
let not_mode = not_mode.unwrap_or_else(BindingMode::empty);
|
||||||
let mods = mods.unwrap_or_else(ModifiersState::default);
|
let mods = mods.unwrap_or_else(ModifiersState::default);
|
||||||
|
|
||||||
let action = match (action, chars, command) {
|
let action = match (action, chars, command) {
|
||||||
(Some(action @ Action::ViMotion(_)), None, None)
|
(Some(action @ Action::ViMotion(_)), None, None)
|
||||||
| (Some(action @ Action::ViAction(_)), None, None) => {
|
| (Some(action @ Action::ViAction(_)), None, None) => {
|
||||||
if !mode.intersects(TermMode::VI) || not_mode.intersects(TermMode::VI) {
|
if !mode.intersects(BindingMode::VI) || not_mode.intersects(BindingMode::VI)
|
||||||
|
{
|
||||||
return Err(V::Error::custom(format!(
|
return Err(V::Error::custom(format!(
|
||||||
"action `{}` is only available in vi mode, try adding `mode: Vi`",
|
"action `{}` is only available in vi mode, try adding `mode: Vi`",
|
||||||
action,
|
action,
|
||||||
|
@ -898,6 +1062,16 @@ impl<'a> Deserialize<'a> for RawBinding {
|
||||||
}
|
}
|
||||||
action
|
action
|
||||||
},
|
},
|
||||||
|
(Some(action @ Action::SearchAction(_)), None, None) => {
|
||||||
|
if !mode.intersects(BindingMode::SEARCH) {
|
||||||
|
return Err(V::Error::custom(format!(
|
||||||
|
"action `{}` is only available in search mode, try adding `mode: \
|
||||||
|
Search`",
|
||||||
|
action,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
action
|
||||||
|
},
|
||||||
(Some(action), None, None) => action,
|
(Some(action), None, None) => action,
|
||||||
(None, Some(chars), None) => Action::Esc(chars),
|
(None, Some(chars), None) => Action::Esc(chars),
|
||||||
(None, None, Some(cmd)) => Action::Command(cmd),
|
(None, None, Some(cmd)) => Action::Command(cmd),
|
||||||
|
@ -995,12 +1169,10 @@ impl<'a> de::Deserialize<'a> for ModsWrapper {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
use glutin::event::ModifiersState;
|
use glutin::event::ModifiersState;
|
||||||
|
|
||||||
use alacritty_terminal::term::TermMode;
|
|
||||||
|
|
||||||
use crate::config::{Action, Binding};
|
|
||||||
|
|
||||||
type MockBinding = Binding<usize>;
|
type MockBinding = Binding<usize>;
|
||||||
|
|
||||||
impl Default for MockBinding {
|
impl Default for MockBinding {
|
||||||
|
@ -1008,8 +1180,8 @@ mod tests {
|
||||||
Self {
|
Self {
|
||||||
mods: Default::default(),
|
mods: Default::default(),
|
||||||
action: Action::None,
|
action: Action::None,
|
||||||
mode: TermMode::empty(),
|
mode: BindingMode::empty(),
|
||||||
notmode: TermMode::empty(),
|
notmode: BindingMode::empty(),
|
||||||
trigger: Default::default(),
|
trigger: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1048,9 +1220,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_matches_identical_mode() {
|
fn binding_matches_identical_mode() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
b1.mode = TermMode::ALT_SCREEN;
|
b1.mode = BindingMode::ALT_SCREEN;
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b2.mode = TermMode::ALT_SCREEN;
|
b2.mode = BindingMode::ALT_SCREEN;
|
||||||
|
|
||||||
assert!(b1.triggers_match(&b2));
|
assert!(b1.triggers_match(&b2));
|
||||||
assert!(b2.triggers_match(&b1));
|
assert!(b2.triggers_match(&b1));
|
||||||
|
@ -1060,8 +1232,8 @@ mod tests {
|
||||||
fn binding_without_mode_matches_any_mode() {
|
fn binding_without_mode_matches_any_mode() {
|
||||||
let b1 = MockBinding::default();
|
let b1 = MockBinding::default();
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b2.mode = TermMode::APP_KEYPAD;
|
b2.mode = BindingMode::APP_KEYPAD;
|
||||||
b2.notmode = TermMode::ALT_SCREEN;
|
b2.notmode = BindingMode::ALT_SCREEN;
|
||||||
|
|
||||||
assert!(b1.triggers_match(&b2));
|
assert!(b1.triggers_match(&b2));
|
||||||
}
|
}
|
||||||
|
@ -1069,8 +1241,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_with_mode_matches_empty_mode() {
|
fn binding_with_mode_matches_empty_mode() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
b1.mode = TermMode::APP_KEYPAD;
|
b1.mode = BindingMode::APP_KEYPAD;
|
||||||
b1.notmode = TermMode::ALT_SCREEN;
|
b1.notmode = BindingMode::ALT_SCREEN;
|
||||||
let b2 = MockBinding::default();
|
let b2 = MockBinding::default();
|
||||||
|
|
||||||
assert!(b1.triggers_match(&b2));
|
assert!(b1.triggers_match(&b2));
|
||||||
|
@ -1080,9 +1252,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_matches_modes() {
|
fn binding_matches_modes() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
b1.mode = TermMode::ALT_SCREEN | TermMode::APP_KEYPAD;
|
b1.mode = BindingMode::ALT_SCREEN | BindingMode::APP_KEYPAD;
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b2.mode = TermMode::APP_KEYPAD;
|
b2.mode = BindingMode::APP_KEYPAD;
|
||||||
|
|
||||||
assert!(b1.triggers_match(&b2));
|
assert!(b1.triggers_match(&b2));
|
||||||
assert!(b2.triggers_match(&b1));
|
assert!(b2.triggers_match(&b1));
|
||||||
|
@ -1091,9 +1263,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_matches_partial_intersection() {
|
fn binding_matches_partial_intersection() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
b1.mode = TermMode::ALT_SCREEN | TermMode::APP_KEYPAD;
|
b1.mode = BindingMode::ALT_SCREEN | BindingMode::APP_KEYPAD;
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b2.mode = TermMode::APP_KEYPAD | TermMode::APP_CURSOR;
|
b2.mode = BindingMode::APP_KEYPAD | BindingMode::APP_CURSOR;
|
||||||
|
|
||||||
assert!(b1.triggers_match(&b2));
|
assert!(b1.triggers_match(&b2));
|
||||||
assert!(b2.triggers_match(&b1));
|
assert!(b2.triggers_match(&b1));
|
||||||
|
@ -1102,9 +1274,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_mismatches_notmode() {
|
fn binding_mismatches_notmode() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
b1.mode = TermMode::ALT_SCREEN;
|
b1.mode = BindingMode::ALT_SCREEN;
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b2.notmode = TermMode::ALT_SCREEN;
|
b2.notmode = BindingMode::ALT_SCREEN;
|
||||||
|
|
||||||
assert!(!b1.triggers_match(&b2));
|
assert!(!b1.triggers_match(&b2));
|
||||||
assert!(!b2.triggers_match(&b1));
|
assert!(!b2.triggers_match(&b1));
|
||||||
|
@ -1113,9 +1285,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_mismatches_unrelated() {
|
fn binding_mismatches_unrelated() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
b1.mode = TermMode::ALT_SCREEN;
|
b1.mode = BindingMode::ALT_SCREEN;
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b2.mode = TermMode::APP_KEYPAD;
|
b2.mode = BindingMode::APP_KEYPAD;
|
||||||
|
|
||||||
assert!(!b1.triggers_match(&b2));
|
assert!(!b1.triggers_match(&b2));
|
||||||
assert!(!b2.triggers_match(&b1));
|
assert!(!b2.triggers_match(&b1));
|
||||||
|
@ -1125,8 +1297,8 @@ mod tests {
|
||||||
fn binding_matches_notmodes() {
|
fn binding_matches_notmodes() {
|
||||||
let mut subset_notmodes = MockBinding::default();
|
let mut subset_notmodes = MockBinding::default();
|
||||||
let mut superset_notmodes = MockBinding::default();
|
let mut superset_notmodes = MockBinding::default();
|
||||||
subset_notmodes.notmode = TermMode::VI | TermMode::APP_CURSOR;
|
subset_notmodes.notmode = BindingMode::VI | BindingMode::APP_CURSOR;
|
||||||
superset_notmodes.notmode = TermMode::APP_CURSOR;
|
superset_notmodes.notmode = BindingMode::APP_CURSOR;
|
||||||
|
|
||||||
assert!(subset_notmodes.triggers_match(&superset_notmodes));
|
assert!(subset_notmodes.triggers_match(&superset_notmodes));
|
||||||
assert!(superset_notmodes.triggers_match(&subset_notmodes));
|
assert!(superset_notmodes.triggers_match(&subset_notmodes));
|
||||||
|
@ -1136,9 +1308,9 @@ mod tests {
|
||||||
fn binding_matches_mode_notmode() {
|
fn binding_matches_mode_notmode() {
|
||||||
let mut b1 = MockBinding::default();
|
let mut b1 = MockBinding::default();
|
||||||
let mut b2 = MockBinding::default();
|
let mut b2 = MockBinding::default();
|
||||||
b1.mode = TermMode::VI;
|
b1.mode = BindingMode::VI;
|
||||||
b1.notmode = TermMode::APP_CURSOR;
|
b1.notmode = BindingMode::APP_CURSOR;
|
||||||
b2.notmode = TermMode::APP_CURSOR;
|
b2.notmode = BindingMode::APP_CURSOR;
|
||||||
|
|
||||||
assert!(b1.triggers_match(&b2));
|
assert!(b1.triggers_match(&b2));
|
||||||
assert!(b2.triggers_match(&b1));
|
assert!(b2.triggers_match(&b1));
|
||||||
|
@ -1175,26 +1347,26 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_trigger_modes() {
|
fn binding_trigger_modes() {
|
||||||
let mut binding = MockBinding::default();
|
let mut binding = MockBinding::default();
|
||||||
binding.mode = TermMode::ALT_SCREEN;
|
binding.mode = BindingMode::ALT_SCREEN;
|
||||||
|
|
||||||
let t = binding.trigger;
|
let t = binding.trigger;
|
||||||
let mods = binding.mods;
|
let mods = binding.mods;
|
||||||
|
|
||||||
assert!(!binding.is_triggered_by(TermMode::INSERT, mods, &t));
|
assert!(!binding.is_triggered_by(BindingMode::VI, mods, &t));
|
||||||
assert!(binding.is_triggered_by(TermMode::ALT_SCREEN, mods, &t));
|
assert!(binding.is_triggered_by(BindingMode::ALT_SCREEN, mods, &t));
|
||||||
assert!(binding.is_triggered_by(TermMode::ALT_SCREEN | TermMode::INSERT, mods, &t));
|
assert!(binding.is_triggered_by(BindingMode::ALT_SCREEN | BindingMode::VI, mods, &t));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_trigger_notmodes() {
|
fn binding_trigger_notmodes() {
|
||||||
let mut binding = MockBinding::default();
|
let mut binding = MockBinding::default();
|
||||||
binding.notmode = TermMode::ALT_SCREEN;
|
binding.notmode = BindingMode::ALT_SCREEN;
|
||||||
|
|
||||||
let t = binding.trigger;
|
let t = binding.trigger;
|
||||||
let mods = binding.mods;
|
let mods = binding.mods;
|
||||||
|
|
||||||
assert!(binding.is_triggered_by(TermMode::INSERT, mods, &t));
|
assert!(binding.is_triggered_by(BindingMode::VI, mods, &t));
|
||||||
assert!(!binding.is_triggered_by(TermMode::ALT_SCREEN, mods, &t));
|
assert!(!binding.is_triggered_by(BindingMode::ALT_SCREEN, mods, &t));
|
||||||
assert!(!binding.is_triggered_by(TermMode::ALT_SCREEN | TermMode::INSERT, mods, &t));
|
assert!(!binding.is_triggered_by(BindingMode::ALT_SCREEN | BindingMode::VI, mods, &t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ mod bindings;
|
||||||
mod mouse;
|
mod mouse;
|
||||||
|
|
||||||
use crate::cli::Options;
|
use crate::cli::Options;
|
||||||
pub use crate::config::bindings::{Action, Binding, Key, ViAction};
|
pub use crate::config::bindings::{Action, Binding, BindingMode, Key, SearchAction, ViAction};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub use crate::config::mouse::{ClickHandler, Mouse};
|
pub use crate::config::mouse::{ClickHandler, Mouse};
|
||||||
use crate::config::ui_config::UIConfig;
|
use crate::config::ui_config::UIConfig;
|
||||||
|
|
|
@ -418,6 +418,12 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn confirm_search(&mut self) {
|
fn confirm_search(&mut self) {
|
||||||
|
// Just cancel search when not in vi mode.
|
||||||
|
if !self.terminal.mode().contains(TermMode::VI) {
|
||||||
|
self.cancel_search();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Force unlimited search if the previous one was interrupted.
|
// Force unlimited search if the previous one was interrupted.
|
||||||
if self.scheduler.scheduled(TimerId::DelayedSearch) {
|
if self.scheduler.scheduled(TimerId::DelayedSearch) {
|
||||||
self.goto_match(None);
|
self.goto_match(None);
|
||||||
|
@ -445,22 +451,24 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push_search(&mut self, c: char) {
|
fn search_input(&mut self, c: char) {
|
||||||
if let Some(regex) = self.search_state.regex.as_mut() {
|
if let Some(regex) = self.search_state.regex.as_mut() {
|
||||||
|
match c {
|
||||||
|
// Handle backspace/ctrl+h.
|
||||||
|
'\x08' | '\x7f' => {
|
||||||
|
let _ = regex.pop();
|
||||||
|
},
|
||||||
|
// Add ascii and unicode text.
|
||||||
|
' '..='~' | '\u{a0}'..='\u{10ffff}' => regex.push(c),
|
||||||
|
// Ignore non-printable characters.
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
|
||||||
if !self.terminal.mode().contains(TermMode::VI) {
|
if !self.terminal.mode().contains(TermMode::VI) {
|
||||||
// Clear selection so we do not obstruct any matches.
|
// Clear selection so we do not obstruct any matches.
|
||||||
self.terminal.selection = None;
|
self.terminal.selection = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
regex.push(c);
|
|
||||||
self.update_search();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn pop_search(&mut self) {
|
|
||||||
if let Some(regex) = self.search_state.regex.as_mut() {
|
|
||||||
regex.pop();
|
|
||||||
self.update_search();
|
self.update_search();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ use log::trace;
|
||||||
use glutin::dpi::PhysicalPosition;
|
use glutin::dpi::PhysicalPosition;
|
||||||
use glutin::event::{
|
use glutin::event::{
|
||||||
ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase,
|
ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase,
|
||||||
VirtualKeyCode,
|
|
||||||
};
|
};
|
||||||
use glutin::event_loop::EventLoopWindowTarget;
|
use glutin::event_loop::EventLoopWindowTarget;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
@ -32,7 +31,7 @@ use alacritty_terminal::term::{ClipboardType, SizeInfo, Term};
|
||||||
use alacritty_terminal::vi_mode::ViMotion;
|
use alacritty_terminal::vi_mode::ViMotion;
|
||||||
|
|
||||||
use crate::clipboard::Clipboard;
|
use crate::clipboard::Clipboard;
|
||||||
use crate::config::{Action, Binding, Config, Key, ViAction};
|
use crate::config::{Action, Binding, BindingMode, Config, Key, SearchAction, ViAction};
|
||||||
use crate::daemon::start_daemon;
|
use crate::daemon::start_daemon;
|
||||||
use crate::event::{ClickState, Event, Mouse, TYPING_SEARCH_DELAY};
|
use crate::event::{ClickState, Event, Mouse, TYPING_SEARCH_DELAY};
|
||||||
use crate::message_bar::{self, Message};
|
use crate::message_bar::{self, Message};
|
||||||
|
@ -97,8 +96,7 @@ pub trait ActionContext<T: EventListener> {
|
||||||
fn start_search(&mut self, direction: Direction);
|
fn start_search(&mut self, direction: Direction);
|
||||||
fn confirm_search(&mut self);
|
fn confirm_search(&mut self);
|
||||||
fn cancel_search(&mut self);
|
fn cancel_search(&mut self);
|
||||||
fn push_search(&mut self, c: char);
|
fn search_input(&mut self, c: char);
|
||||||
fn pop_search(&mut self);
|
|
||||||
fn pop_word_search(&mut self);
|
fn pop_word_search(&mut self);
|
||||||
fn advance_search_origin(&mut self, direction: Direction);
|
fn advance_search_origin(&mut self, direction: Direction);
|
||||||
fn search_direction(&self) -> Direction;
|
fn search_direction(&self) -> Direction;
|
||||||
|
@ -145,17 +143,6 @@ impl<T: EventListener> Execute<T> for Action {
|
||||||
ctx.scroll(Scroll::Bottom);
|
ctx.scroll(Scroll::Bottom);
|
||||||
ctx.write_to_pty(s.clone().into_bytes())
|
ctx.write_to_pty(s.clone().into_bytes())
|
||||||
},
|
},
|
||||||
Action::Copy => ctx.copy_selection(ClipboardType::Clipboard),
|
|
||||||
#[cfg(not(any(target_os = "macos", windows)))]
|
|
||||||
Action::CopySelection => ctx.copy_selection(ClipboardType::Selection),
|
|
||||||
Action::Paste => {
|
|
||||||
let text = ctx.clipboard_mut().load(ClipboardType::Clipboard);
|
|
||||||
paste(ctx, &text);
|
|
||||||
},
|
|
||||||
Action::PasteSelection => {
|
|
||||||
let text = ctx.clipboard_mut().load(ClipboardType::Selection);
|
|
||||||
paste(ctx, &text);
|
|
||||||
},
|
|
||||||
Action::Command(ref program) => {
|
Action::Command(ref program) => {
|
||||||
let args = program.args();
|
let args = program.args();
|
||||||
let program = program.program();
|
let program = program.program();
|
||||||
|
@ -163,7 +150,6 @@ impl<T: EventListener> Execute<T> for Action {
|
||||||
|
|
||||||
start_daemon(program, args);
|
start_daemon(program, args);
|
||||||
},
|
},
|
||||||
Action::ClearSelection => ctx.clear_selection(),
|
|
||||||
Action::ToggleViMode => ctx.terminal_mut().toggle_vi_mode(),
|
Action::ToggleViMode => ctx.terminal_mut().toggle_vi_mode(),
|
||||||
Action::ViMotion(motion) => {
|
Action::ViMotion(motion) => {
|
||||||
ctx.on_typing_start();
|
ctx.on_typing_start();
|
||||||
|
@ -221,8 +207,35 @@ impl<T: EventListener> Execute<T> for Action {
|
||||||
ctx.terminal_mut().vi_goto_point(*regex_match.end());
|
ctx.terminal_mut().vi_goto_point(*regex_match.end());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Action::SearchAction(SearchAction::SearchFocusNext) => {
|
||||||
|
ctx.advance_search_origin(ctx.search_direction());
|
||||||
|
},
|
||||||
|
Action::SearchAction(SearchAction::SearchFocusPrevious) => {
|
||||||
|
let direction = ctx.search_direction().opposite();
|
||||||
|
ctx.advance_search_origin(direction);
|
||||||
|
},
|
||||||
|
Action::SearchAction(SearchAction::SearchConfirm) => ctx.confirm_search(),
|
||||||
|
Action::SearchAction(SearchAction::SearchCancel) => ctx.cancel_search(),
|
||||||
|
Action::SearchAction(SearchAction::SearchClear) => {
|
||||||
|
let direction = ctx.search_direction();
|
||||||
|
ctx.cancel_search();
|
||||||
|
ctx.start_search(direction);
|
||||||
|
},
|
||||||
|
Action::SearchAction(SearchAction::SearchDeleteWord) => ctx.pop_word_search(),
|
||||||
Action::SearchForward => ctx.start_search(Direction::Right),
|
Action::SearchForward => ctx.start_search(Direction::Right),
|
||||||
Action::SearchBackward => ctx.start_search(Direction::Left),
|
Action::SearchBackward => ctx.start_search(Direction::Left),
|
||||||
|
Action::Copy => ctx.copy_selection(ClipboardType::Clipboard),
|
||||||
|
#[cfg(not(any(target_os = "macos", windows)))]
|
||||||
|
Action::CopySelection => ctx.copy_selection(ClipboardType::Selection),
|
||||||
|
Action::ClearSelection => ctx.clear_selection(),
|
||||||
|
Action::Paste => {
|
||||||
|
let text = ctx.clipboard_mut().load(ClipboardType::Clipboard);
|
||||||
|
paste(ctx, &text);
|
||||||
|
},
|
||||||
|
Action::PasteSelection => {
|
||||||
|
let text = ctx.clipboard_mut().load(ClipboardType::Selection);
|
||||||
|
paste(ctx, &text);
|
||||||
|
},
|
||||||
Action::ToggleFullscreen => ctx.window_mut().toggle_fullscreen(),
|
Action::ToggleFullscreen => ctx.window_mut().toggle_fullscreen(),
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
Action::ToggleSimpleFullscreen => ctx.window_mut().toggle_simple_fullscreen(),
|
Action::ToggleSimpleFullscreen => ctx.window_mut().toggle_simple_fullscreen(),
|
||||||
|
@ -315,7 +328,11 @@ impl<T: EventListener> Execute<T> for Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paste<T: EventListener, A: ActionContext<T>>(ctx: &mut A, contents: &str) {
|
fn paste<T: EventListener, A: ActionContext<T>>(ctx: &mut A, contents: &str) {
|
||||||
if ctx.terminal().mode().contains(TermMode::BRACKETED_PASTE) {
|
if ctx.search_active() {
|
||||||
|
for c in contents.chars() {
|
||||||
|
ctx.search_input(c);
|
||||||
|
}
|
||||||
|
} else if ctx.terminal().mode().contains(TermMode::BRACKETED_PASTE) {
|
||||||
ctx.write_to_pty(&b"\x1b[200~"[..]);
|
ctx.write_to_pty(&b"\x1b[200~"[..]);
|
||||||
ctx.write_to_pty(contents.replace("\x1b", "").into_bytes());
|
ctx.write_to_pty(contents.replace("\x1b", "").into_bytes());
|
||||||
ctx.write_to_pty(&b"\x1b[201~"[..]);
|
ctx.write_to_pty(&b"\x1b[201~"[..]);
|
||||||
|
@ -796,57 +813,14 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
|
||||||
|
|
||||||
/// Process key input.
|
/// Process key input.
|
||||||
pub fn key_input(&mut self, input: KeyboardInput) {
|
pub fn key_input(&mut self, input: KeyboardInput) {
|
||||||
match input.state {
|
|
||||||
ElementState::Pressed if self.ctx.search_active() => {
|
|
||||||
match (input.virtual_keycode, *self.ctx.modifiers()) {
|
|
||||||
(Some(VirtualKeyCode::Back), _) => {
|
|
||||||
self.ctx.pop_search();
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
},
|
|
||||||
(Some(VirtualKeyCode::Return), ModifiersState::SHIFT)
|
|
||||||
if !self.ctx.terminal().mode().contains(TermMode::VI) =>
|
|
||||||
{
|
|
||||||
let direction = self.ctx.search_direction().opposite();
|
|
||||||
self.ctx.advance_search_origin(direction);
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
}
|
|
||||||
(Some(VirtualKeyCode::Return), _)
|
|
||||||
| (Some(VirtualKeyCode::J), ModifiersState::CTRL) => {
|
|
||||||
if self.ctx.terminal().mode().contains(TermMode::VI) {
|
|
||||||
self.ctx.confirm_search();
|
|
||||||
} else {
|
|
||||||
self.ctx.advance_search_origin(self.ctx.search_direction());
|
|
||||||
}
|
|
||||||
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
},
|
|
||||||
(Some(VirtualKeyCode::Escape), _)
|
|
||||||
| (Some(VirtualKeyCode::C), ModifiersState::CTRL) => {
|
|
||||||
self.ctx.cancel_search();
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
},
|
|
||||||
(Some(VirtualKeyCode::U), ModifiersState::CTRL) => {
|
|
||||||
let direction = self.ctx.search_direction();
|
|
||||||
self.ctx.cancel_search();
|
|
||||||
self.ctx.start_search(direction);
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
},
|
|
||||||
(Some(VirtualKeyCode::H), ModifiersState::CTRL) => {
|
|
||||||
self.ctx.pop_search();
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
},
|
|
||||||
(Some(VirtualKeyCode::W), ModifiersState::CTRL) => {
|
|
||||||
self.ctx.pop_word_search();
|
|
||||||
*self.ctx.suppress_chars() = true;
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset search delay when the user is still typing.
|
// Reset search delay when the user is still typing.
|
||||||
|
if self.ctx.search_active() {
|
||||||
if let Some(timer) = self.ctx.scheduler_mut().get_mut(TimerId::DelayedSearch) {
|
if let Some(timer) = self.ctx.scheduler_mut().get_mut(TimerId::DelayedSearch) {
|
||||||
timer.deadline = Instant::now() + TYPING_SEARCH_DELAY;
|
timer.deadline = Instant::now() + TYPING_SEARCH_DELAY;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
|
match input.state {
|
||||||
ElementState::Pressed => {
|
ElementState::Pressed => {
|
||||||
*self.ctx.received_count() = 0;
|
*self.ctx.received_count() = 0;
|
||||||
self.process_key_bindings(input);
|
self.process_key_bindings(input);
|
||||||
|
@ -877,14 +851,8 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
|
||||||
let suppress_chars = *self.ctx.suppress_chars();
|
let suppress_chars = *self.ctx.suppress_chars();
|
||||||
let search_active = self.ctx.search_active();
|
let search_active = self.ctx.search_active();
|
||||||
if suppress_chars || self.ctx.terminal().mode().contains(TermMode::VI) || search_active {
|
if suppress_chars || self.ctx.terminal().mode().contains(TermMode::VI) || search_active {
|
||||||
if search_active {
|
if search_active && !suppress_chars {
|
||||||
// Skip control characters.
|
self.ctx.search_input(c);
|
||||||
let c_decimal = c as isize;
|
|
||||||
let is_printable = (c_decimal >= 0x20 && c_decimal < 0x7f) || c_decimal >= 0xa0;
|
|
||||||
|
|
||||||
if !suppress_chars && is_printable {
|
|
||||||
self.ctx.push_search(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*self.ctx.suppress_chars() = false;
|
*self.ctx.suppress_chars() = false;
|
||||||
|
@ -922,6 +890,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
|
||||||
/// The provided mode, mods, and key must match what is allowed by a binding
|
/// The provided mode, mods, and key must match what is allowed by a binding
|
||||||
/// for its action to be executed.
|
/// for its action to be executed.
|
||||||
fn process_key_bindings(&mut self, input: KeyboardInput) {
|
fn process_key_bindings(&mut self, input: KeyboardInput) {
|
||||||
|
let mode = BindingMode::new(self.ctx.terminal().mode(), self.ctx.search_active());
|
||||||
let mods = *self.ctx.modifiers();
|
let mods = *self.ctx.modifiers();
|
||||||
let mut suppress_chars = None;
|
let mut suppress_chars = None;
|
||||||
|
|
||||||
|
@ -934,7 +903,7 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
if binding.is_triggered_by(*self.ctx.terminal().mode(), mods, &key) {
|
if binding.is_triggered_by(mode, mods, &key) {
|
||||||
// Binding was triggered; run the action.
|
// Binding was triggered; run the action.
|
||||||
let binding = binding.clone();
|
let binding = binding.clone();
|
||||||
binding.execute(&mut self.ctx);
|
binding.execute(&mut self.ctx);
|
||||||
|
@ -953,14 +922,9 @@ impl<'a, T: EventListener, A: ActionContext<T>> Processor<'a, T, A> {
|
||||||
/// The provided mode, mods, and key must match what is allowed by a binding
|
/// The provided mode, mods, and key must match what is allowed by a binding
|
||||||
/// for its action to be executed.
|
/// for its action to be executed.
|
||||||
fn process_mouse_bindings(&mut self, button: MouseButton) {
|
fn process_mouse_bindings(&mut self, button: MouseButton) {
|
||||||
// Ignore bindings while search is active.
|
let mode = BindingMode::new(self.ctx.terminal().mode(), self.ctx.search_active());
|
||||||
if self.ctx.search_active() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mods = *self.ctx.modifiers();
|
|
||||||
let mode = *self.ctx.terminal().mode();
|
|
||||||
let mouse_mode = self.ctx.mouse_mode();
|
let mouse_mode = self.ctx.mouse_mode();
|
||||||
|
let mods = *self.ctx.modifiers();
|
||||||
|
|
||||||
for i in 0..self.ctx.config().ui_config.mouse_bindings.len() {
|
for i in 0..self.ctx.config().ui_config.mouse_bindings.len() {
|
||||||
let mut binding = self.ctx.config().ui_config.mouse_bindings[i].clone();
|
let mut binding = self.ctx.config().ui_config.mouse_bindings[i].clone();
|
||||||
|
@ -1151,9 +1115,7 @@ mod tests {
|
||||||
|
|
||||||
fn cancel_search(&mut self) {}
|
fn cancel_search(&mut self) {}
|
||||||
|
|
||||||
fn push_search(&mut self, _c: char) {}
|
fn search_input(&mut self, _c: char) {}
|
||||||
|
|
||||||
fn pop_search(&mut self) {}
|
|
||||||
|
|
||||||
fn pop_word_search(&mut self) {}
|
fn pop_word_search(&mut self) {}
|
||||||
|
|
||||||
|
@ -1462,65 +1424,65 @@ mod tests {
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_shiftmod_require_shift,
|
name: process_binding_nomode_shiftmod_require_shift,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::SHIFT, action: Action::from("\x1b[1;2D"), mode: TermMode::NONE, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::SHIFT, action: Action::from("\x1b[1;2D"), mode: BindingMode::empty(), notmode: BindingMode::empty() },
|
||||||
triggers: true,
|
triggers: true,
|
||||||
mode: TermMode::NONE,
|
mode: BindingMode::empty(),
|
||||||
mods: ModifiersState::SHIFT,
|
mods: ModifiersState::SHIFT,
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_nomod_require_shift,
|
name: process_binding_nomode_nomod_require_shift,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::SHIFT, action: Action::from("\x1b[1;2D"), mode: TermMode::NONE, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::SHIFT, action: Action::from("\x1b[1;2D"), mode: BindingMode::empty(), notmode: BindingMode::empty() },
|
||||||
triggers: false,
|
triggers: false,
|
||||||
mode: TermMode::NONE,
|
mode: BindingMode::empty(),
|
||||||
mods: ModifiersState::empty(),
|
mods: ModifiersState::empty(),
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_controlmod,
|
name: process_binding_nomode_controlmod,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::CTRL, action: Action::from("\x1b[1;5D"), mode: TermMode::NONE, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::CTRL, action: Action::from("\x1b[1;5D"), mode: BindingMode::empty(), notmode: BindingMode::empty() },
|
||||||
triggers: true,
|
triggers: true,
|
||||||
mode: TermMode::NONE,
|
mode: BindingMode::empty(),
|
||||||
mods: ModifiersState::CTRL,
|
mods: ModifiersState::CTRL,
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_nomod_require_not_appcursor,
|
name: process_binding_nomode_nomod_require_not_appcursor,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1b[D"), mode: TermMode::NONE, notmode: TermMode::APP_CURSOR },
|
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1b[D"), mode: BindingMode::empty(), notmode: BindingMode::APP_CURSOR },
|
||||||
triggers: true,
|
triggers: true,
|
||||||
mode: TermMode::NONE,
|
mode: BindingMode::empty(),
|
||||||
mods: ModifiersState::empty(),
|
mods: ModifiersState::empty(),
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_appcursormode_nomod_require_appcursor,
|
name: process_binding_appcursormode_nomod_require_appcursor,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1bOD"), mode: TermMode::APP_CURSOR, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1bOD"), mode: BindingMode::APP_CURSOR, notmode: BindingMode::empty() },
|
||||||
triggers: true,
|
triggers: true,
|
||||||
mode: TermMode::APP_CURSOR,
|
mode: BindingMode::APP_CURSOR,
|
||||||
mods: ModifiersState::empty(),
|
mods: ModifiersState::empty(),
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_nomode_nomod_require_appcursor,
|
name: process_binding_nomode_nomod_require_appcursor,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1bOD"), mode: TermMode::APP_CURSOR, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1bOD"), mode: BindingMode::APP_CURSOR, notmode: BindingMode::empty() },
|
||||||
triggers: false,
|
triggers: false,
|
||||||
mode: TermMode::NONE,
|
mode: BindingMode::empty(),
|
||||||
mods: ModifiersState::empty(),
|
mods: ModifiersState::empty(),
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_appcursormode_appkeypadmode_nomod_require_appcursor,
|
name: process_binding_appcursormode_appkeypadmode_nomod_require_appcursor,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1bOD"), mode: TermMode::APP_CURSOR, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::empty(), action: Action::from("\x1bOD"), mode: BindingMode::APP_CURSOR, notmode: BindingMode::empty() },
|
||||||
triggers: true,
|
triggers: true,
|
||||||
mode: TermMode::APP_CURSOR | TermMode::APP_KEYPAD,
|
mode: BindingMode::APP_CURSOR | BindingMode::APP_KEYPAD,
|
||||||
mods: ModifiersState::empty(),
|
mods: ModifiersState::empty(),
|
||||||
}
|
}
|
||||||
|
|
||||||
test_process_binding! {
|
test_process_binding! {
|
||||||
name: process_binding_fail_with_extra_mods,
|
name: process_binding_fail_with_extra_mods,
|
||||||
binding: Binding { trigger: KEY, mods: ModifiersState::LOGO, action: Action::from("arst"), mode: TermMode::NONE, notmode: TermMode::NONE },
|
binding: Binding { trigger: KEY, mods: ModifiersState::LOGO, action: Action::from("arst"), mode: BindingMode::empty(), notmode: BindingMode::empty() },
|
||||||
triggers: false,
|
triggers: false,
|
||||||
mode: TermMode::NONE,
|
mode: BindingMode::empty(),
|
||||||
mods: ModifiersState::ALT | ModifiersState::LOGO,
|
mods: ModifiersState::ALT | ModifiersState::LOGO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue