summaryrefslogtreecommitdiffstats
path: root/src/term/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/term/mod.rs')
-rw-r--r--src/term/mod.rs145
1 files changed, 140 insertions, 5 deletions
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 0dc5532c..b0ca2a59 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -20,8 +20,8 @@ use std::cmp::min;
use std::io;
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset};
-use grid::{Grid, ClearRegion, ToRange};
-use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive};
+use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange};
+use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side};
use selection::{Span, Selection};
use config::{Config};
@@ -352,6 +352,8 @@ pub struct Term {
/// Saved cursor from alt grid
cursor_save_alt: Cursor,
+
+ semantic_escape_chars: String,
}
/// Terminal size info
@@ -436,11 +438,13 @@ impl Term {
size_info: size,
empty_cell: template,
custom_cursor_colors: config.custom_cursor_colors(),
+ semantic_escape_chars: config.selection().semantic_escape_chars.clone(),
}
}
pub fn update_config(&mut self, config: &Config) {
- self.custom_cursor_colors = config.custom_cursor_colors()
+ self.custom_cursor_colors = config.custom_cursor_colors();
+ self.semantic_escape_chars = config.selection().semantic_escape_chars.clone();
}
#[inline]
@@ -448,6 +452,64 @@ impl Term {
self.dirty
}
+ pub fn line_selection(&self, selection: &mut Selection, point: Point) {
+ selection.clear();
+ selection.update(Point {
+ line: point.line,
+ col: Column(0),
+ }, Side::Left);
+ selection.update(Point {
+ line: point.line,
+ col: self.grid.num_cols() - Column(1),
+ }, Side::Right);
+ }
+
+ pub fn semantic_selection(&self, selection: &mut Selection, point: Point) {
+ let mut side_left = Point {
+ line: point.line,
+ col: point.col
+ };
+ let mut side_right = Point {
+ line: point.line,
+ col: point.col
+ };
+
+ let mut left_iter = self.grid.iter_from(point);
+ let mut right_iter = self.grid.iter_from(point);
+
+ let last_col = self.grid.num_cols() - Column(1);
+
+ while let Some(cell) = left_iter.prev() {
+ if self.semantic_escape_chars.contains(cell.c) {
+ break;
+ }
+
+ if left_iter.cur.col == last_col && !cell.flags.contains(cell::WRAPLINE) {
+ break; // cut off if on new line or hit escape char
+ }
+
+ side_left.col = left_iter.cur.col;
+ side_left.line = left_iter.cur.line;
+ }
+
+ while let Some(cell) = right_iter.next() {
+ if self.semantic_escape_chars.contains(cell.c) {
+ break;
+ }
+
+ side_right.col = right_iter.cur.col;
+ side_right.line = right_iter.cur.line;
+
+ if right_iter.cur.col == last_col && !cell.flags.contains(cell::WRAPLINE) {
+ break; // cut off if on new line or hit escape char
+ }
+ }
+
+ selection.clear();
+ selection.update(side_left, Side::Left);
+ selection.update(side_right, Side::Right);
+ }
+
pub fn string_from_selection(&self, span: &Span) -> String {
/// Need a generic push() for the Append trait
trait PushChar {
@@ -1283,12 +1345,85 @@ impl ansi::Handler for Term {
mod tests {
extern crate serde_json;
- use super::{Term, limit, SizeInfo};
+ use super::{Cell, Term, limit, SizeInfo};
+ use term::cell;
use grid::Grid;
use index::{Point, Line, Column};
- use term::{Cell};
use ansi::{Handler, CharsetIndex, StandardCharset};
+ use selection::Selection;
+ use std::mem;
+
+ #[test]
+ fn semantic_selection_works() {
+ let size = SizeInfo {
+ width: 21.0,
+ height: 51.0,
+ cell_width: 3.0,
+ cell_height: 3.0,
+ };
+ let mut term = Term::new(&Default::default(), size);
+ let mut grid: Grid<Cell> = Grid::new(Line(3), Column(5), &Cell::default());
+ for i in 0..5 {
+ for j in 0..2 {
+ grid[Line(j)][Column(i)].c = 'a';
+ }
+ }
+ grid[Line(0)][Column(0)].c = '"';
+ grid[Line(0)][Column(3)].c = '"';
+ grid[Line(1)][Column(2)].c = '"';
+ grid[Line(0)][Column(4)].flags.insert(cell::WRAPLINE);
+
+ let mut escape_chars = String::from("\"");
+
+ mem::swap(&mut term.grid, &mut grid);
+ mem::swap(&mut term.semantic_escape_chars, &mut escape_chars);
+
+ {
+ let mut selection = Selection::new();
+ term.semantic_selection(&mut selection, Point { line: Line(0), col: Column(1) });
+ assert_eq!(term.string_from_selection(&selection.span().unwrap()), "aa");
+ }
+
+ {
+ let mut selection = Selection::new();
+ term.semantic_selection(&mut selection, Point { line: Line(0), col: Column(4) });
+ assert_eq!(term.string_from_selection(&selection.span().unwrap()), "aaa");
+ }
+
+ {
+ let mut selection = Selection::new();
+ term.semantic_selection(&mut selection, Point { line: Line(1), col: Column(1) });
+ assert_eq!(term.string_from_selection(&selection.span().unwrap()), "aaa");
+ }
+ }
+
+ #[test]
+ fn line_selection_works() {
+ let size = SizeInfo {
+ width: 21.0,
+ height: 51.0,
+ cell_width: 3.0,
+ cell_height: 3.0,
+ };
+ let mut term = Term::new(&Default::default(), size);
+ let mut grid: Grid<Cell> = Grid::new(Line(1), Column(5), &Cell::default());
+ for i in 0..5 {
+ grid[Line(0)][Column(i)].c = 'a';
+ }
+ grid[Line(0)][Column(0)].c = '"';
+ grid[Line(0)][Column(3)].c = '"';
+
+
+ mem::swap(&mut term.grid, &mut grid);
+
+ let mut selection = Selection::new();
+ term.line_selection(&mut selection, Point { line: Line(0), col: Column(3) });
+ match selection.span() {
+ Some(span) => assert_eq!(term.string_from_selection(&span), "\"aa\"a"),
+ _ => ()
+ }
+ }
/// Check that the grid can be serialized back and forth losslessly
///