1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 15:04:36 +03:00

adjust double-click selection class

previously this just used unicode word segmentation rules, but that
is insufficient for most technical users.

Change this to look for sequences that are non-whitespace and not
enclosed by bracket/quote delimiters.  This allows selecting file names
with a double click, which was my main issue.
This commit is contained in:
Wez Furlong 2019-02-24 13:13:35 -08:00
parent dba88d2102
commit 184befae09
2 changed files with 70 additions and 30 deletions

View File

@ -13,7 +13,6 @@ use termwiz::escape::osc::{ITermFileData, ITermProprietary};
use termwiz::escape::{Action, ControlCode, Esc, EscCode, OperatingSystemCommand, CSI};
use termwiz::hyperlink::Rule as HyperlinkRule;
use termwiz::image::{ImageCell, ImageData, TextureCoordinate};
use unicode_segmentation::UnicodeSegmentation;
struct TabStop {
tabs: Vec<bool>,
@ -448,36 +447,43 @@ impl TerminalState {
let y = event.y as ScrollbackOrVisibleRowIndex
- self.viewport_offset as ScrollbackOrVisibleRowIndex;
let idx = self.screen().scrollback_or_visible_row(y);
let line = self.screen().lines[idx].as_str();
let click_range =
self.screen().lines[idx].compute_double_click_range(event.x, |s| {
// TODO: add configuration for this
if s.len() > 1 {
true
} else if s.len() == 1 {
match s.chars().nth(0).unwrap() {
' ' | '\t' | '\n' | '{' | '[' | '}' | ']' | '('
| ')' | '"' | '\'' => false,
_ => true,
}
} else {
false
}
});
self.selection_start = None;
self.selection_range = None;
// TODO: allow user to configure the word boundary rules.
// Also consider making the default work with URLs?
for (x, word) in line.split_word_bound_indices() {
if event.x < x {
break;
}
if event.x <= x + word.len() {
// this is our word
let start = SelectionCoordinate { x, y };
let end = SelectionCoordinate {
x: x + word.len() - 1,
y,
};
self.selection_start = Some(start);
self.selection_range = Some(SelectionRange { start, end });
self.dirty_selection_lines();
let text = self.get_selection_text();
debug!(
"finish 2click selection {:?} '{}'",
self.selection_range, text
);
host.set_clipboard(Some(text))?;
return Ok(());
}
}
host.set_clipboard(None)?;
self.selection_start = Some(SelectionCoordinate {
x: click_range.start,
y,
});
self.selection_range = Some(SelectionRange {
start: SelectionCoordinate {
x: click_range.start,
y,
},
end: SelectionCoordinate {
x: click_range.end,
y,
},
});
self.dirty_selection_lines();
let text = self.get_selection_text();
debug!(
"finish 2click selection {:?} '{}'",
self.selection_range, text
);
host.set_clipboard(Some(text))?;
}
// triple click to select the current line
Some(&LastMouseClick { streak: 3, .. }) => {

View File

@ -180,6 +180,40 @@ impl Line {
s
}
pub fn compute_double_click_range(
&self,
click_col: usize,
is_word: fn(s: &str) -> bool,
) -> Range<usize> {
let mut lower = click_col;
let mut upper = click_col;
// TODO: look back and look ahead for cells that are hidden by
// a preceding multi-wide cell
for (idx, cell) in self
.cells
.iter()
.enumerate()
.skip(click_col.saturating_sub(1))
{
if !is_word(cell.str()) {
break;
}
upper = idx;
}
for (idx, cell) in self.cells.iter().enumerate().rev() {
if idx > click_col {
continue;
}
if !is_word(cell.str()) {
break;
}
lower = idx;
}
lower..upper
}
/// Returns a substring from the line.
pub fn columns_as_str(&self, range: Range<usize>) -> String {
let mut s = String::new();