diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c5fe1..3ed21a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Config option `working_directory` - Config group `debug` with the options `debug.log_level`, `debug.print_events` and `debug.ref_test` +- Select until next matching bracket when double-clicking a bracket ### Changed diff --git a/alacritty_terminal/src/selection.rs b/alacritty_terminal/src/selection.rs index 6aaedf2..ad2f2ba 100644 --- a/alacritty_terminal/src/selection.rs +++ b/alacritty_terminal/src/selection.rs @@ -188,14 +188,20 @@ impl Selection { Selection::alt_screen_clamp(&mut start, &mut end, lines, cols)?; } - let (mut start, mut end) = if start < end && start.line == end.line { + let (mut start, mut end) = if start == end { + if let Some(end) = grid.bracket_search(start.into()) { + (start.into(), end) + } else { + (grid.semantic_search_right(start.into()), grid.semantic_search_left(end.into())) + } + } else if start < end && start.line == end.line { (grid.semantic_search_left(start.into()), grid.semantic_search_right(end.into())) } else { (grid.semantic_search_right(start.into()), grid.semantic_search_left(end.into())) }; if start > end { - ::std::mem::swap(&mut start, &mut end); + std::mem::swap(&mut start, &mut end); } Some(Span { start, end }) diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index de4d132..c01c159 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -46,6 +46,9 @@ use crate::tty; pub mod cell; pub mod color; +/// Used to match equal brackets, when performing a bracket-pair selection. +const BRACKET_PAIRS: [(char, char); 4] = [('(', ')'), ('[', ']'), ('{', '}'), ('<', '>')]; + /// A type that can expand a given point to a region /// /// Usually this is implemented for some 2-D array type since @@ -57,6 +60,8 @@ pub trait Search { fn semantic_search_right(&self, _: Point) -> Point; /// Find the nearest URL boundary in both directions. fn url_search(&self, _: Point) -> Option; + /// Find the nearest matching bracket. + fn bracket_search(&self, _: Point) -> Option>; } impl Search for Term { @@ -137,6 +142,49 @@ impl Search for Term { } url_parser.url() } + + fn bracket_search(&self, point: Point) -> Option> { + let start_char = self.grid[point.line][point.col].c; + + // Find the matching bracket we're looking for + let (forwards, end_char) = BRACKET_PAIRS.iter().find_map(|(open, close)| { + if open == &start_char { + Some((true, *close)) + } else if close == &start_char { + Some((false, *open)) + } else { + None + } + })?; + + let mut iter = self.grid.iter_from(point); + + // For every character match that equals the starting bracket, we + // ignore one bracket of the opposite type. + let mut skip_pairs = 0; + + loop { + // Check the next cell + let cell = if forwards { iter.next() } else { iter.prev() }; + + // Break if there are no more cells + let c = match cell { + Some(cell) => cell.c, + None => break, + }; + + // Check if the bracket matches + if c == end_char && skip_pairs == 0 { + return Some(iter.cur); + } else if c == start_char { + skip_pairs += 1; + } else if c == end_char { + skip_pairs -= 1; + } + } + + None + } } impl selection::Dimensions for Term {