Add support for double-click bracket-pair selection

This commit is contained in:
Jean Mertz 2019-05-11 18:15:32 +02:00 committed by Christian Duerr
parent ca9724a5ef
commit 1656aff85e
3 changed files with 57 additions and 2 deletions

View File

@ -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

View File

@ -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 })

View File

@ -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<usize>) -> Point<usize>;
/// Find the nearest URL boundary in both directions.
fn url_search(&self, _: Point<usize>) -> Option<Url>;
/// Find the nearest matching bracket.
fn bracket_search(&self, _: Point<usize>) -> Option<Point<usize>>;
}
impl Search for Term {
@ -137,6 +142,49 @@ impl Search for Term {
}
url_parser.url()
}
fn bracket_search(&self, point: Point<usize>) -> Option<Point<usize>> {
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 {