Assure that newlines are in selections (#777)

When a selection was made, the last line of the selection did not
include a new line character when the line ending was selected. This
would occur if only one line was selected; if multiple lines were
selected, only the final line did not include a newline.

This commit updates the `string_from_selection` function to attempt to
append a newline character in all places where they are suitable.
Because of the simplification of newline insertion, several trait
implementations were removed.
This commit is contained in:
Dustin 2017-12-23 00:17:04 -05:00 committed by Joe Wilm
parent 7f7ec0682c
commit ea8cf10b2f
1 changed files with 23 additions and 52 deletions

View File

@ -866,78 +866,49 @@ impl Term {
self.push(c);
}
}
trait Append<T> : PushChar {
fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: T) -> Option<Range<Column>>;
use std::ops::Range;
trait Append : PushChar {
fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: Range<Column>) -> Option<Range<Column>>;
}
use std::ops::{Range, RangeTo, RangeFrom, RangeFull};
impl Append<Range<Column>> for String {
impl Append for String {
fn append(
&mut self,
grid: &Grid<Cell>,
line: Line,
cols: Range<Column>
) -> Option<Range<Column>> {
let line = &grid[line];
let line_length = line.line_length();
let grid_line = &grid[line];
let line_length = grid_line.line_length();
let line_end = min(line_length, cols.end + 1);
if cols.start >= line_end {
None
} else {
for cell in &line[cols.start..line_end] {
for cell in &grid_line[cols.start..line_end] {
if !cell.flags.contains(cell::WIDE_CHAR_SPACER) {
self.push(cell.c);
}
}
Some(cols.start..line_end)
let range = Some(cols.start..line_end);
if cols.end >= grid.num_cols() - 1 {
range.as_ref()
.map(|range| self.maybe_newline(grid, line, range.end));
}
range
}
}
}
impl Append<RangeTo<Column>> for String {
#[inline]
fn append(&mut self, grid: &Grid<Cell>, line: Line, cols: RangeTo<Column>) -> Option<Range<Column>> {
self.append(grid, line, Column(0)..cols.end)
}
}
impl Append<RangeFrom<Column>> for String {
#[inline]
fn append(
&mut self,
grid: &Grid<Cell>,
line: Line,
cols: RangeFrom<Column>
) -> Option<Range<Column>> {
let range = self.append(grid, line, cols.start..Column(usize::max_value() - 1));
range.as_ref()
.map(|range| self.maybe_newline(grid, line, range.end));
range
}
}
impl Append<RangeFull> for String {
#[inline]
fn append(
&mut self,
grid: &Grid<Cell>,
line: Line,
_: RangeFull
) -> Option<Range<Column>> {
let range = self.append(grid, line, Column(0)..Column(usize::max_value() - 1));
range.as_ref()
.map(|range| self.maybe_newline(grid, line, range.end));
range
}
}
let mut res = String::new();
let (start, end) = span.to_locations();
let line_count = end.line - start.line;
let max_col = Column(usize::max_value() - 1);
match line_count {
// Selection within single line
@ -948,24 +919,24 @@ impl Term {
// Selection ends on line following start
Line(1) => {
// Starting line
res.append(&self.grid, start.line, start.col..);
res.append(&self.grid, start.line, start.col..max_col);
// Ending line
res.append(&self.grid, end.line, ..end.col);
res.append(&self.grid, end.line, Column(0)..end.col);
},
// Multi line selection
_ => {
// Starting line
res.append(&self.grid, start.line, start.col..);
res.append(&self.grid, start.line, start.col..max_col);
let middle_range = IndexRange::from((start.line + 1)..(end.line));
for line in middle_range {
res.append(&self.grid, line, ..);
res.append(&self.grid, line, Column(0)..max_col);
}
// Ending line
res.append(&self.grid, end.line, ..end.col);
res.append(&self.grid, end.line, Column(0)..end.col);
}
}
@ -1963,7 +1934,7 @@ mod tests {
let selection = Selection::lines(Point { line: Line(0), col: Column(3) });
match selection.to_span(&term) {
Some(span) => assert_eq!(term.string_from_selection(&span), "\"aa\"a"),
Some(span) => assert_eq!(term.string_from_selection(&span), "\"aa\"a\n"),
_ => ()
}
}