Trim \n from hints/semantic-/simple selection

Before this patch a hint regex ending in the last column would append a
newline, despite this newline being "invisible" to the user. To match
the expected behavior, newlines are trimmed from regex hint matches.

To ensure consistency the simple and semantic selection also do not
include a newline at the end of the copied text anymore.

Fixes #5697.
This commit is contained in:
a5ob7r 2022-01-05 06:46:20 +09:00 committed by GitHub
parent 437f42f8d3
commit 2057ac243a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 16 deletions

View File

@ -36,6 +36,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Strip trailing whitespaces when yanking from a block selection
- Display area keeps history position when viewport is cleared
- Commands spawn from the current directory of the foreground shell in Unix-like systems
- Remove trailing newline from strings taken from hints or simple/semantic selections
### Fixed

View File

@ -17,7 +17,7 @@ use crate::config::Config;
use crate::event::{Event, EventListener};
use crate::grid::{Dimensions, Grid, GridIterator, Scroll};
use crate::index::{self, Boundary, Column, Direction, Line, Point, Side};
use crate::selection::{Selection, SelectionRange};
use crate::selection::{Selection, SelectionRange, SelectionType};
use crate::term::cell::{Cell, Flags, LineLength};
use crate::term::color::{Colors, Rgb};
use crate::vi_mode::{ViModeCursor, ViMotion};
@ -348,24 +348,30 @@ impl<T> Term<T> {
/// Convert the active selection to a String.
pub fn selection_to_string(&self) -> Option<String> {
let selection_range = self.selection.as_ref().and_then(|s| s.to_range(self))?;
let SelectionRange { start, end, is_block } = selection_range;
let SelectionRange { start, end, .. } = selection_range;
let mut res = String::new();
if is_block {
for line in (start.line.0..end.line.0).map(Line::from) {
res += self
.line_to_string(line, start.column..end.column, start.column.0 != 0)
.trim_end();
match self.selection.as_ref() {
Some(Selection { ty: SelectionType::Block, .. }) => {
for line in (start.line.0..end.line.0).map(Line::from) {
res += self
.line_to_string(line, start.column..end.column, start.column.0 != 0)
.trim_end();
// If the last column is included, newline is appended automatically.
if end.column != self.columns() - 1 {
res += "\n";
// If the last column is included, newline is appended automatically.
if end.column != self.columns() - 1 {
res += "\n";
}
}
}
res += self.line_to_string(end.line, start.column..end.column, true).trim_end();
} else {
res = self.bounds_to_string(start, end);
res += self.line_to_string(end.line, start.column..end.column, true).trim_end();
},
Some(Selection { ty: SelectionType::Lines, .. }) => {
res = self.bounds_to_string(start, end) + "\n";
},
_ => {
res = self.bounds_to_string(start, end);
},
}
Some(res)
@ -382,7 +388,7 @@ impl<T> Term<T> {
res += &self.line_to_string(line, start_col..end_col, line == end.line);
}
res
res.strip_suffix('\n').map(str::to_owned).unwrap_or(res)
}
/// Convert a single line in the grid to a String.
@ -2103,7 +2109,7 @@ mod tests {
);
selection.update(Point { line: Line(2), column: Column(2) }, Side::Right);
term.selection = Some(selection);
assert_eq!(term.selection_to_string(), Some("aaa\n\naaa\n".into()));
assert_eq!(term.selection_to_string(), Some("aaa\n\naaa".into()));
}
/// Check that the grid can be serialized back and forth losslessly.