mirror of
https://github.com/alacritty/alacritty.git
synced 2025-04-14 17:53:03 -04:00
Clear selection on clear line/screen escapes
Selection is now cleared if clear line or clear screen escape sequences are clearing content behind it.
This commit is contained in:
parent
6c8966f426
commit
8a39346b75
4 changed files with 78 additions and 6 deletions
|
@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Set IUTF8 termios flag for improved UTF8 input support
|
||||
- Dragging files into terminal now adds a space after each path
|
||||
- Default binding replacement conditions
|
||||
- Adjusted selection clearing granularity to more accurately match content
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -187,6 +187,11 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
|
|||
Point { line: self.lines.0 + self.display_offset - point.line.0 - 1, col: point.col }
|
||||
}
|
||||
|
||||
/// Return the cursor position in buffer coordinates.
|
||||
pub fn cursor_buffer_point(&self) -> Point<usize> {
|
||||
Point { line: self.lines.0 - self.cursor.point.line.0 - 1, col: self.cursor.point.col }
|
||||
}
|
||||
|
||||
/// Update the size of the scrollback history.
|
||||
pub fn update_history(&mut self, history_size: usize) {
|
||||
let current_history_size = self.history_size();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::Range;
|
||||
use std::ops::{Bound, Range, RangeBounds};
|
||||
|
||||
use crate::index::{Column, Line, Point, Side};
|
||||
use crate::term::{Search, Term};
|
||||
|
@ -193,6 +193,30 @@ impl Selection {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check whether selection contains any point in a given range.
|
||||
pub fn intersects_range<R: RangeBounds<usize>>(&self, range: R) -> bool {
|
||||
let mut start = self.region.start.point.line;
|
||||
let mut end = self.region.end.point.line;
|
||||
|
||||
if Self::points_need_swap(self.region.start.point, self.region.end.point) {
|
||||
mem::swap(&mut start, &mut end);
|
||||
}
|
||||
|
||||
let range_start = match range.start_bound() {
|
||||
Bound::Included(&range_start) => range_start,
|
||||
Bound::Excluded(&range_start) => range_start.saturating_add(1),
|
||||
Bound::Unbounded => 0,
|
||||
};
|
||||
|
||||
let range_end = match range.end_bound() {
|
||||
Bound::Included(&range_end) => range_end,
|
||||
Bound::Excluded(&range_end) => range_end.saturating_sub(1),
|
||||
Bound::Unbounded => usize::max_value(),
|
||||
};
|
||||
|
||||
range_start <= start && range_end >= end
|
||||
}
|
||||
|
||||
/// Expand selection sides to include all cells.
|
||||
pub fn include_all(&mut self) {
|
||||
let (start, end) = (self.region.start.point, self.region.end.point);
|
||||
|
@ -217,7 +241,9 @@ impl Selection {
|
|||
let num_cols = grid.num_cols();
|
||||
|
||||
// Order start above the end.
|
||||
let (mut start, mut end) = (self.region.start, self.region.end);
|
||||
let mut start = self.region.start;
|
||||
let mut end = self.region.end;
|
||||
|
||||
if Self::points_need_swap(start.point, end.point) {
|
||||
mem::swap(&mut start, &mut end);
|
||||
}
|
||||
|
@ -643,4 +669,21 @@ mod tests {
|
|||
is_block: true,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range_intersection() {
|
||||
let mut selection =
|
||||
Selection::new(SelectionType::Lines, Point::new(6, Column(1)), Side::Left);
|
||||
selection.update(Point::new(3, Column(1)), Side::Right);
|
||||
|
||||
assert!(selection.intersects_range(..));
|
||||
assert!(selection.intersects_range(2..));
|
||||
assert!(selection.intersects_range(2..=4));
|
||||
assert!(selection.intersects_range(2..=7));
|
||||
assert!(selection.intersects_range(4..=5));
|
||||
assert!(selection.intersects_range(5..8));
|
||||
|
||||
assert!(!selection.intersects_range(..=2));
|
||||
assert!(!selection.intersects_range(7..=8));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1763,6 +1763,12 @@ impl<T: EventListener> Handler for Term<T> {
|
|||
}
|
||||
},
|
||||
}
|
||||
|
||||
let cursor_buffer_line = self.grid.cursor_buffer_point().line;
|
||||
self.selection = self
|
||||
.selection
|
||||
.take()
|
||||
.filter(|s| !s.intersects_range(cursor_buffer_line..=cursor_buffer_line));
|
||||
}
|
||||
|
||||
/// Set the indexed color value.
|
||||
|
@ -1840,8 +1846,8 @@ impl<T: EventListener> Handler for Term<T> {
|
|||
trace!("Clearing screen: {:?}", mode);
|
||||
let template = self.grid.cursor.template;
|
||||
|
||||
// Remove active selections.
|
||||
self.selection = None;
|
||||
let num_lines = self.grid.num_lines().0;
|
||||
let cursor_buffer_line = self.grid.cursor_buffer_point().line;
|
||||
|
||||
match mode {
|
||||
ansi::ClearMode::Above => {
|
||||
|
@ -1858,15 +1864,24 @@ impl<T: EventListener> Handler for Term<T> {
|
|||
for cell in &mut self.grid[cursor.line][..end] {
|
||||
cell.reset(&template);
|
||||
}
|
||||
|
||||
self.selection = self
|
||||
.selection
|
||||
.take()
|
||||
.filter(|s| !s.intersects_range(cursor_buffer_line..num_lines));
|
||||
},
|
||||
ansi::ClearMode::Below => {
|
||||
let cursor = self.grid.cursor.point;
|
||||
for cell in &mut self.grid[cursor.line][cursor.col..] {
|
||||
cell.reset(&template);
|
||||
}
|
||||
if cursor.line < self.grid.num_lines() - 1 {
|
||||
|
||||
if cursor.line.0 < num_lines - 1 {
|
||||
self.grid.region_mut((cursor.line + 1)..).each(|cell| cell.reset(&template));
|
||||
}
|
||||
|
||||
self.selection =
|
||||
self.selection.take().filter(|s| !s.intersects_range(..=cursor_buffer_line));
|
||||
},
|
||||
ansi::ClearMode::All => {
|
||||
if self.mode.contains(TermMode::ALT_SCREEN) {
|
||||
|
@ -1875,8 +1890,16 @@ impl<T: EventListener> Handler for Term<T> {
|
|||
let template = Cell { bg: template.bg, ..Cell::default() };
|
||||
self.grid.clear_viewport(template);
|
||||
}
|
||||
|
||||
self.selection = self.selection.take().filter(|s| !s.intersects_range(..num_lines));
|
||||
},
|
||||
ansi::ClearMode::Saved => self.grid.clear_history(),
|
||||
ansi::ClearMode::Saved if self.grid.history_size() > 0 => {
|
||||
self.grid.clear_history();
|
||||
|
||||
self.selection = self.selection.take().filter(|s| !s.intersects_range(num_lines..));
|
||||
},
|
||||
// We have no history to clear.
|
||||
ansi::ClearMode::Saved => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue