From ae470bf68bf27921109890da3d90a5b61fa6a7aa Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Mon, 26 Dec 2016 22:52:37 -0500 Subject: Implement copying selection for macOS Still need automatic loading into selection copy buffer for linux. --- src/term/mod.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'src/term/mod.rs') diff --git a/src/term/mod.rs b/src/term/mod.rs index b25e8382..28e73b19 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -21,10 +21,11 @@ use std::io; use ansi::{self, Color, NamedColor, Attr, Handler}; use grid::{Grid, ClearRegion, ToRange}; use index::{self, Cursor, Column, Line, Linear}; -use selection::Selection; +use selection::{Span, Selection}; pub mod cell; pub use self::cell::Cell; +use self::cell::LineLength; /// Iterator that yields cells needing render /// @@ -309,6 +310,85 @@ impl Term { } } + pub fn string_from_selection(&self, span: &Span) -> String { + trait Append { + fn append(&mut self, grid: &Grid, line: Line, cols: T); + } + + use std::ops::{Range, RangeTo, RangeFrom, RangeFull}; + + impl Append> for String { + fn append(&mut self, grid: &Grid, line: Line, cols: Range) { + let line = &grid[line]; + let line_length = line.line_length(); + let line_end = cmp::min(line_length, cols.end + 1); + for cell in &line[cols.start..line_end] { + self.push(cell.c); + } + } + } + + impl Append> for String { + #[inline] + fn append(&mut self, grid: &Grid, line: Line, cols: RangeTo) { + self.append(grid, line, Column(0)..cols.end); + } + } + + impl Append> for String { + #[inline] + fn append(&mut self, grid: &Grid, line: Line, cols: RangeFrom) { + self.append(grid, line, cols.start..Column(usize::max_value() - 1)); + self.push('\n'); + } + } + + impl Append for String { + #[inline] + fn append(&mut self, grid: &Grid, line: Line, _: RangeFull) { + self.append(grid, line, Column(0)..Column(usize::max_value() - 1)); + self.push('\n'); + } + } + + let mut res = String::new(); + + let (start, end) = span.to_locations(self.grid.num_cols()); + let line_count = end.line - start.line; + + match line_count { + // Selection within single line + Line(0) => { + res.append(&self.grid, start.line, start.col..end.col); + }, + + // Selection ends on line following start + Line(1) => { + // Starting line + res.append(&self.grid, start.line, start.col..); + + // Ending line + res.append(&self.grid, end.line, ..end.col); + }, + + // Multi line selection + _ => { + // Starting line + res.append(&self.grid, start.line, start.col..); + + let middle_range = (start.line + 1)..(end.line); + for line in middle_range { + res.append(&self.grid, line, ..); + } + + // Ending line + res.append(&self.grid, end.line, ..end.col); + } + } + + res + } + /// Convert the given pixel values to a grid coordinate /// /// The mouse coordinates are expected to be relative to the top left. The -- cgit