mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 22:01:47 +03:00
add some tests for a double-width selection bug
This commit is contained in:
parent
adc11f303a
commit
d0de936f62
@ -166,6 +166,10 @@ impl Cell {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn str(&self) -> &str {
|
||||
str::from_utf8(self.bytes()).unwrap_or("?")
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
str::from_utf8(self.bytes()).unwrap_or("").width()
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::ops::Range;
|
||||
use std::str;
|
||||
|
||||
use super::*;
|
||||
@ -63,7 +64,20 @@ impl Line {
|
||||
pub fn as_str(&self) -> String {
|
||||
let mut s = String::new();
|
||||
for c in self.cells.iter() {
|
||||
s.push_str(str::from_utf8(c.bytes()).unwrap_or("?"));
|
||||
s.push_str(c.str());
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// Returns a substring from the line.
|
||||
pub fn columns_as_str(&self, range: Range<usize>) -> String {
|
||||
let mut s = String::new();
|
||||
let limit = range.end - range.start;
|
||||
for (n, c) in self.cells.iter().skip(range.start).enumerate() {
|
||||
if n >= limit {
|
||||
break;
|
||||
}
|
||||
s.push_str(c.str());
|
||||
}
|
||||
s
|
||||
}
|
||||
@ -74,7 +88,7 @@ impl Line {
|
||||
let mut clusters = Vec::new();
|
||||
|
||||
for (cell_idx, c) in self.cells.iter().enumerate() {
|
||||
let cell_str = str::from_utf8(c.bytes()).unwrap_or("?");
|
||||
let cell_str = c.str();
|
||||
|
||||
last_cluster = match last_cluster.take() {
|
||||
None => {
|
||||
|
@ -129,15 +129,11 @@ impl TerminalState {
|
||||
let screen = self.screen();
|
||||
for y in sel.rows() {
|
||||
let idx = screen.scrollback_or_visible_row(y);
|
||||
let line = screen.lines[idx].as_str();
|
||||
let cols = sel.cols_for_row(y);
|
||||
let end = cols.end.min(line.len());
|
||||
let col_range = cols.start..end;
|
||||
let selected = &line[col_range].trim_right();
|
||||
if s.len() > 0 {
|
||||
s.push('\n');
|
||||
}
|
||||
s.push_str(selected);
|
||||
s.push_str(&screen.lines[idx].columns_as_str(cols).trim_right());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
//! processing routines.
|
||||
|
||||
use super::*;
|
||||
mod selection;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct TestHost {
|
||||
@ -111,6 +112,69 @@ impl TestTerm {
|
||||
self.print(CSI);
|
||||
self.print("!p");
|
||||
}
|
||||
|
||||
fn mouse(&mut self, event: MouseEvent) -> Result<(), Error> {
|
||||
self.term.mouse_event(event, &mut self.host)
|
||||
}
|
||||
|
||||
fn get_clipboard(&self) -> Option<&String> {
|
||||
self.host.clip.as_ref()
|
||||
}
|
||||
|
||||
/// Inject n_times clicks of the button at the specified coordinates
|
||||
fn click_n(&mut self, x: usize, y: i64, button: MouseButton, n_times: usize) {
|
||||
for _ in 0..n_times {
|
||||
self.mouse(MouseEvent {
|
||||
kind: MouseEventKind::Press,
|
||||
x,
|
||||
y,
|
||||
button,
|
||||
modifiers: KeyModifiers::default(),
|
||||
}).unwrap();
|
||||
self.mouse(MouseEvent {
|
||||
kind: MouseEventKind::Release,
|
||||
x,
|
||||
y,
|
||||
button,
|
||||
modifiers: KeyModifiers::default(),
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Left mouse button drag from the start to the end coordinates
|
||||
fn drag_select(&mut self, start_x: usize, start_y: i64, end_x: usize, end_y: i64) {
|
||||
// Break any outstanding click streak that might falsely trigger due to
|
||||
// this unit test happening much faster than the CLICK_INTERVAL allows.
|
||||
self.click_n(0, 0, MouseButton::Right, 1);
|
||||
|
||||
// Now inject the appropriate left click events
|
||||
|
||||
self.mouse(MouseEvent {
|
||||
kind: MouseEventKind::Press,
|
||||
x: start_x,
|
||||
y: start_y,
|
||||
button: MouseButton::Left,
|
||||
modifiers: KeyModifiers::default(),
|
||||
}).unwrap();
|
||||
assert!(self.host.clip.is_none());
|
||||
|
||||
self.mouse(MouseEvent {
|
||||
kind: MouseEventKind::Move,
|
||||
x: end_x,
|
||||
y: end_y,
|
||||
button: MouseButton::None,
|
||||
modifiers: KeyModifiers::default(),
|
||||
}).unwrap();
|
||||
assert!(self.host.clip.is_none());
|
||||
|
||||
self.mouse(MouseEvent {
|
||||
kind: MouseEventKind::Release,
|
||||
x: end_x,
|
||||
y: end_y,
|
||||
button: MouseButton::Left,
|
||||
modifiers: KeyModifiers::default(),
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for TestTerm {
|
||||
|
58
term/src/test/selection.rs
Normal file
58
term/src/test/selection.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use super::*;
|
||||
|
||||
/// Test basic dragging to select some text
|
||||
#[test]
|
||||
fn drag_selection() {
|
||||
let mut term = TestTerm::new(3, 12, 0);
|
||||
term.print("hello world\n");
|
||||
assert_visible_contents(&term, &["hello world ", " ", " "]);
|
||||
|
||||
term.drag_select(1, 0, 4, 0);
|
||||
assert_eq!(term.get_clipboard().unwrap(), "ello");
|
||||
|
||||
// Now check that we respect double-width boundaries reasonably sanely;
|
||||
// here we're dragging from the middle of the skull emoji
|
||||
term.print("\u{1F480}skull\n");
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
&["hello world ", "\u{1F480}skull ", " "],
|
||||
);
|
||||
term.drag_select(1, 1, 5, 1);
|
||||
assert_eq!(term.get_clipboard().unwrap(), "skul");
|
||||
|
||||
// Let's include the start of it this time
|
||||
term.drag_select(0, 1, 5, 1);
|
||||
assert_eq!(term.get_clipboard().unwrap(), "\u{1F480}skul");
|
||||
|
||||
// Multi-line selection
|
||||
term.drag_select(1, 0, 6, 1);
|
||||
assert_eq!(term.get_clipboard().unwrap(), "ello world\n\u{1F480}skull");
|
||||
|
||||
term.drag_select(0, 0, 0, 2);
|
||||
assert_eq!(
|
||||
term.get_clipboard().unwrap(),
|
||||
"hello world\n\u{1F480}skull\n"
|
||||
);
|
||||
}
|
||||
|
||||
/// Test double click to select a word
|
||||
#[test]
|
||||
fn double_click_selection() {
|
||||
let mut term = TestTerm::new(3, 10, 0);
|
||||
term.print("hello world");
|
||||
|
||||
term.click_n(1, 0, MouseButton::Left, 2);
|
||||
|
||||
assert_eq!(term.get_clipboard().unwrap(), "hello");
|
||||
}
|
||||
|
||||
/// Test triple click to select a line
|
||||
#[test]
|
||||
fn triple_click_selection() {
|
||||
let mut term = TestTerm::new(3, 10, 0);
|
||||
term.print("hello world");
|
||||
assert_visible_contents(&term, &["hello worl", "d ", " "]);
|
||||
term.click_n(1, 0, MouseButton::Left, 3);
|
||||
|
||||
assert_eq!(term.get_clipboard().unwrap(), "hello worl");
|
||||
}
|
Loading…
Reference in New Issue
Block a user