feat: add Visual selection and clipboard editing
This commit is contained in:
+90
@@ -242,6 +242,31 @@ fn draw(frame: &mut Frame, editor: &Editor, top: &mut usize, left: &mut usize) {
|
||||
buffer[(area.x + (column - *left) as u16, y)].set_style(style);
|
||||
}
|
||||
}
|
||||
if let Some(selection) = editor.selection() {
|
||||
let first = selection.start.row.max(*top);
|
||||
let last = selection.end.row.min(top.saturating_add(height - 1));
|
||||
let style = Style::default().fg(Color::White).bg(Color::Blue);
|
||||
for row in first..=last {
|
||||
let line = &editor.lines()[row];
|
||||
let start = if row == selection.start.row {
|
||||
display_column(line, selection.start.column)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let end = if row == selection.end.row {
|
||||
display_column(line, selection.end.column)
|
||||
} else {
|
||||
display_column(line, usize::MAX) + 1
|
||||
};
|
||||
let start = start.max(*left);
|
||||
let end = end.min(left.saturating_add(width));
|
||||
let y = area.y + (row - *top) as u16;
|
||||
let buffer = frame.buffer_mut();
|
||||
for column in start..end {
|
||||
buffer[(area.x + (column - *left) as u16, y)].set_style(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
let path = editor
|
||||
.path()
|
||||
.map(|p| p.to_string_lossy().into_owned())
|
||||
@@ -301,6 +326,71 @@ mod tests {
|
||||
assert_eq!(visible_line(text, 5, 2), " e\u{301}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn visual_selection_highlights_graphemes_newlines_and_clipped_ranges_over_search() {
|
||||
let mut editor = Editor::open(None, vec![]).unwrap();
|
||||
editor
|
||||
.apply(vec![crate::editor::Effect::Replace(
|
||||
"a\t界e\u{301}z\n\nxy".into(),
|
||||
)])
|
||||
.unwrap();
|
||||
editor.handle(Input::Char('/'));
|
||||
for ch in "界e\u{301}".chars() {
|
||||
editor.handle(Input::Char(ch));
|
||||
}
|
||||
editor.handle(Input::Enter);
|
||||
editor.handle(Input::Char('v'));
|
||||
editor.handle(Input::Left);
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(10, 6)).unwrap();
|
||||
let (mut top, mut left) = (0, 0);
|
||||
terminal
|
||||
.draw(|frame| draw(frame, &editor, &mut top, &mut left))
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
for x in [1, 2, 3, 4] {
|
||||
assert_eq!(buffer[(x, 0)].bg, Color::Blue);
|
||||
}
|
||||
assert_eq!(buffer[(4, 0)].symbol(), "界");
|
||||
assert_eq!(buffer[(6, 0)].bg, Color::Yellow);
|
||||
editor.handle(Input::Down);
|
||||
editor.handle(Input::Down);
|
||||
terminal
|
||||
.draw(|frame| draw(frame, &editor, &mut top, &mut left))
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
assert_eq!(buffer[(8, 0)].symbol(), " ");
|
||||
assert_eq!(buffer[(8, 0)].bg, Color::Blue);
|
||||
assert_eq!(buffer[(0, 1)].bg, Color::Blue);
|
||||
assert_eq!(buffer[(0, 2)].bg, Color::Blue);
|
||||
assert_ne!(buffer[(1, 2)].bg, Color::Blue);
|
||||
|
||||
editor.handle(Input::Up);
|
||||
editor.handle(Input::Up);
|
||||
editor.handle(Input::End);
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(5, 6)).unwrap();
|
||||
terminal
|
||||
.draw(|frame| draw(frame, &editor, &mut top, &mut left))
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
assert_eq!(left, 4);
|
||||
assert_eq!(buffer[(0, 0)].symbol(), "界");
|
||||
assert_eq!(buffer[(2, 0)].symbol(), "e\u{301}");
|
||||
assert_eq!(buffer[(4, 0)].symbol(), " ");
|
||||
for x in [0, 2, 3, 4] {
|
||||
assert_eq!(buffer[(x, 0)].bg, Color::Blue);
|
||||
}
|
||||
assert_ne!(buffer[(0, 1)].bg, Color::Blue);
|
||||
editor.handle(Input::Escape);
|
||||
terminal
|
||||
.draw(|frame| draw(frame, &editor, &mut top, &mut left))
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
assert_eq!(buffer[(0, 0)].bg, Color::Yellow);
|
||||
assert_eq!(buffer[(2, 0)].bg, Color::Yellow);
|
||||
assert_ne!(buffer[(3, 0)].bg, Color::Blue);
|
||||
assert_ne!(buffer[(4, 0)].bg, Color::Blue);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn active_search_highlight_uses_display_cells_and_clips_with_horizontal_scroll() {
|
||||
let mut editor = Editor::open(None, vec![]).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user