summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Heard <jasonh@pandell.com>2021-07-29 09:40:51 -0600
committerGitHub <noreply@github.com>2021-07-29 15:40:51 +0000
commit3c309a0953566fe6f726b84eb117fd9cfa42df3d (patch)
treed6f4c6200bc4f9a6abb192adeee5bb15b4603815
parent96a098c358870e8be41921f19ed72810651106ae (diff)
downloadalacritty-3c309a0953566fe6f726b84eb117fd9cfa42df3d.tar.gz
alacritty-3c309a0953566fe6f726b84eb117fd9cfa42df3d.zip
Add ExpandSelection mouse binding action
Fixes #4132.
-rw-r--r--CHANGELOG.md4
-rw-r--r--alacritty.yml10
-rw-r--r--alacritty/src/config/bindings.rs31
-rw-r--r--alacritty/src/config/mod.rs4
-rw-r--r--alacritty/src/event.rs36
-rw-r--r--alacritty/src/input.rs53
6 files changed, 91 insertions, 47 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 796d1c3c..9e2ec6b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 0.10.0-dev
+### Changed
+
+- `ExpandSelection` is now a configurable mouse binding action
+
## 0.9.0
### Packaging
diff --git a/alacritty.yml b/alacritty.yml
index a7628203..e93f3f74 100644
--- a/alacritty.yml
+++ b/alacritty.yml
@@ -507,13 +507,19 @@
# - Right
# - Numeric identifier such as `5`
#
-# - `action` (see key bindings)
+# - `action` (see key bindings for actions not exclusive to mouse mode)
+#
+# - Mouse exclusive actions:
+#
+# - ExpandSelection
+# Expand the selection to the current mouse cursor location.
#
# And optionally:
#
# - `mods` (see key bindings)
#mouse_bindings:
-# - { mouse: Middle, action: PasteSelection }
+# - { mouse: Right, action: ExpandSelection }
+# - { mouse: Middle, mode: ~Vi, action: PasteSelection }
# Key bindings
#
diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs
index 57237ad3..a4271430 100644
--- a/alacritty/src/config/bindings.rs
+++ b/alacritty/src/config/bindings.rs
@@ -109,6 +109,10 @@ pub enum Action {
#[config(skip)]
Search(SearchAction),
+ /// Perform mouse binding exclusive action.
+ #[config(skip)]
+ Mouse(MouseAction),
+
/// Paste contents of system clipboard.
Paste,
@@ -227,12 +231,19 @@ impl From<SearchAction> for Action {
}
}
+impl From<MouseAction> for Action {
+ fn from(action: MouseAction) -> Self {
+ Self::Mouse(action)
+ }
+}
+
/// Display trait used for error logging.
impl Display for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Action::ViMotion(motion) => motion.fmt(f),
Action::Vi(action) => action.fmt(f),
+ Action::Mouse(action) => action.fmt(f),
_ => write!(f, "{:?}", self),
}
}
@@ -283,6 +294,13 @@ pub enum SearchAction {
SearchHistoryNext,
}
+/// Mouse binding specific actions.
+#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
+pub enum MouseAction {
+ /// Expand the selection to the current mouse cursor position.
+ ExpandSelection,
+}
+
macro_rules! bindings {
(
KeyBinding;
@@ -343,6 +361,7 @@ macro_rules! bindings {
pub fn default_mouse_bindings() -> Vec<MouseBinding> {
bindings!(
MouseBinding;
+ MouseButton::Right; MouseAction::ExpandSelection;
MouseButton::Middle, ~BindingMode::VI; Action::PasteSelection;
)
}
@@ -1027,6 +1046,9 @@ impl<'a> Deserialize<'a> for RawBinding {
SearchAction::deserialize(value.clone())
{
Some(search_action.into())
+ } else if let Ok(mouse_action) = MouseAction::deserialize(value.clone())
+ {
+ Some(mouse_action.into())
} else {
match Action::deserialize(value.clone()).map_err(V::Error::custom) {
Ok(action) => Some(action),
@@ -1102,6 +1124,15 @@ impl<'a> Deserialize<'a> for RawBinding {
}
action
},
+ (Some(action @ Action::Mouse(_)), None, None) => {
+ if mouse.is_none() {
+ return Err(V::Error::custom(format!(
+ "action `{}` is only available for mouse bindings",
+ action,
+ )));
+ }
+ action
+ },
(Some(action), None, None) => action,
(None, Some(chars), None) => Action::Esc(chars),
(None, None, Some(cmd)) => Action::Command(cmd),
diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs
index 840a4b68..43cade6d 100644
--- a/alacritty/src/config/mod.rs
+++ b/alacritty/src/config/mod.rs
@@ -22,7 +22,9 @@ mod bindings;
mod mouse;
use crate::cli::Options;
-pub use crate::config::bindings::{Action, Binding, BindingMode, Key, SearchAction, ViAction};
+pub use crate::config::bindings::{
+ Action, Binding, BindingMode, Key, MouseAction, SearchAction, ViAction,
+};
#[cfg(test)]
pub use crate::config::mouse::{ClickHandler, Mouse};
use crate::config::ui_config::UiConfig;
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index 37d28bb9..bc9c305a 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -671,6 +671,42 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
}
}
+ /// Expand the selection to the current mouse cursor position.
+ #[inline]
+ fn expand_selection(&mut self) {
+ let selection_type = match self.mouse().click_state {
+ ClickState::Click => {
+ if self.modifiers().ctrl() {
+ SelectionType::Block
+ } else {
+ SelectionType::Simple
+ }
+ },
+ ClickState::DoubleClick => SelectionType::Semantic,
+ ClickState::TripleClick => SelectionType::Lines,
+ ClickState::None => return,
+ };
+
+ // Load mouse point, treating message bar and padding as the closest cell.
+ let display_offset = self.terminal().grid().display_offset();
+ let point = self.mouse().point(&self.size_info(), display_offset);
+
+ let cell_side = self.mouse().cell_side;
+
+ let selection = match &mut self.terminal_mut().selection {
+ Some(selection) => selection,
+ None => return,
+ };
+
+ selection.ty = selection_type;
+ self.update_selection(point, cell_side);
+
+ // Move vi mode cursor to mouse click position.
+ if self.terminal().mode().contains(TermMode::VI) && !self.search_active() {
+ self.terminal_mut().vi_mode_cursor.point = point;
+ }
+ }
+
/// Paste a text into the terminal.
fn paste(&mut self, text: &str) {
if self.search_active() {
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs
index 3258137c..98a1b723 100644
--- a/alacritty/src/input.rs
+++ b/alacritty/src/input.rs
@@ -29,7 +29,7 @@ use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode};
use alacritty_terminal::vi_mode::ViMotion;
use crate::clipboard::Clipboard;
-use crate::config::{Action, BindingMode, Config, Key, SearchAction, ViAction};
+use crate::config::{Action, BindingMode, Config, Key, MouseAction, SearchAction, ViAction};
use crate::daemon::start_daemon;
use crate::display::hint::HintMatch;
use crate::display::window::Window;
@@ -104,6 +104,7 @@ pub trait ActionContext<T: EventListener> {
fn toggle_vi_mode(&mut self) {}
fn hint_input(&mut self, _character: char) {}
fn trigger_hint(&mut self, _hint: &HintMatch) {}
+ fn expand_selection(&mut self) {}
fn paste(&mut self, _text: &str) {}
}
@@ -231,6 +232,7 @@ impl<T: EventListener> Execute<T> for Action {
Action::Search(SearchAction::SearchDeleteWord) => ctx.search_pop_word(),
Action::Search(SearchAction::SearchHistoryPrevious) => ctx.search_history_previous(),
Action::Search(SearchAction::SearchHistoryNext) => ctx.search_history_next(),
+ Action::Mouse(MouseAction::ExpandSelection) => ctx.expand_selection(),
Action::SearchForward => ctx.start_search(Direction::Right),
Action::SearchBackward => ctx.start_search(Direction::Left),
Action::Copy => ctx.copy_selection(ClipboardType::Clipboard),
@@ -531,51 +533,12 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
let display_offset = self.ctx.terminal().grid().display_offset();
let point = self.ctx.mouse().point(&self.ctx.size_info(), display_offset);
- match button {
- MouseButton::Left => self.on_left_click(point),
- MouseButton::Right => self.on_right_click(point),
- // Do nothing when using buttons other than LMB.
- _ => self.ctx.mouse_mut().click_state = ClickState::None,
+ if let MouseButton::Left = button {
+ self.on_left_click(point)
}
}
}
- /// Handle selection expansion on right click.
- fn on_right_click(&mut self, point: Point) {
- match self.ctx.mouse().click_state {
- ClickState::Click => {
- let selection_type = if self.ctx.modifiers().ctrl() {
- SelectionType::Block
- } else {
- SelectionType::Simple
- };
-
- self.expand_selection(point, selection_type);
- },
- ClickState::DoubleClick => self.expand_selection(point, SelectionType::Semantic),
- ClickState::TripleClick => self.expand_selection(point, SelectionType::Lines),
- ClickState::None => (),
- }
- }
-
- /// Expand existing selection.
- fn expand_selection(&mut self, point: Point, selection_type: SelectionType) {
- let cell_side = self.ctx.mouse().cell_side;
-
- let selection = match &mut self.ctx.terminal_mut().selection {
- Some(selection) => selection,
- None => return,
- };
-
- selection.ty = selection_type;
- self.ctx.update_selection(point, cell_side);
-
- // Move vi mode cursor to mouse click position.
- if self.ctx.terminal().mode().contains(TermMode::VI) && !self.ctx.search_active() {
- self.ctx.terminal_mut().vi_mode_cursor.point = point;
- }
- }
-
/// Handle left click selection and vi mode cursor movement.
fn on_left_click(&mut self, point: Point) {
let side = self.ctx.mouse().cell_side;
@@ -749,8 +712,9 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
} else {
match state {
ElementState::Pressed => {
- self.process_mouse_bindings(button);
+ // Process mouse press before bindings to update the `click_state`.
self.on_mouse_press(button);
+ self.process_mouse_bindings(button);
},
ElementState::Released => self.on_mouse_release(button),
}
@@ -1138,6 +1102,7 @@ mod tests {
let mut mouse = Mouse {
click_state: $initial_state,
+ last_click_button: $initial_button,
..Mouse::default()
};
@@ -1239,7 +1204,7 @@ mod tests {
},
window_id: unsafe { std::mem::transmute_copy(&0) },
},
- end_state: ClickState::None,
+ end_state: ClickState::Click,
}
test_clickstate! {