1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-26 06:42:12 +03:00

add some tests for a double-width selection bug

This commit is contained in:
Wez Furlong 2018-02-11 17:40:14 -08:00
parent adc11f303a
commit d0de936f62
5 changed files with 143 additions and 7 deletions

View File

@ -166,6 +166,10 @@ impl Cell {
} }
} }
pub fn str(&self) -> &str {
str::from_utf8(self.bytes()).unwrap_or("?")
}
pub fn width(&self) -> usize { pub fn width(&self) -> usize {
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
str::from_utf8(self.bytes()).unwrap_or("").width() str::from_utf8(self.bytes()).unwrap_or("").width()

View File

@ -1,3 +1,4 @@
use std::ops::Range;
use std::str; use std::str;
use super::*; use super::*;
@ -63,7 +64,20 @@ impl Line {
pub fn as_str(&self) -> String { pub fn as_str(&self) -> String {
let mut s = String::new(); let mut s = String::new();
for c in self.cells.iter() { 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 s
} }
@ -74,7 +88,7 @@ impl Line {
let mut clusters = Vec::new(); let mut clusters = Vec::new();
for (cell_idx, c) in self.cells.iter().enumerate() { 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() { last_cluster = match last_cluster.take() {
None => { None => {

View File

@ -129,15 +129,11 @@ impl TerminalState {
let screen = self.screen(); let screen = self.screen();
for y in sel.rows() { for y in sel.rows() {
let idx = screen.scrollback_or_visible_row(y); let idx = screen.scrollback_or_visible_row(y);
let line = screen.lines[idx].as_str();
let cols = sel.cols_for_row(y); 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 { if s.len() > 0 {
s.push('\n'); s.push('\n');
} }
s.push_str(selected); s.push_str(&screen.lines[idx].columns_as_str(cols).trim_right());
} }
} }

View File

@ -2,6 +2,7 @@
//! processing routines. //! processing routines.
use super::*; use super::*;
mod selection;
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct TestHost { struct TestHost {
@ -111,6 +112,69 @@ impl TestTerm {
self.print(CSI); self.print(CSI);
self.print("!p"); 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 { impl Deref for TestTerm {

View 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");
}