summaryrefslogtreecommitdiffstats
path: root/src/term/mod.rs
diff options
context:
space:
mode:
authorXiaoyu Yin <yin530@gmail.com>2017-01-14 17:53:48 -0800
committerJoe Wilm <jwilm@users.noreply.github.com>2017-02-07 21:04:18 -0800
commit92e1cec0880313d962d80bf16eca60cebb509eab (patch)
tree165d470ca13ab89dcf8b399b7491f3766b446ab2 /src/term/mod.rs
parent59295e44312b3936132965636e5fac92118e5c27 (diff)
Semantic Selection
Fix tests and add line select Refactor BidirectionalIter to remove if blocks Allow for cells tagged with WRAPLINE to continue expanding the selection Reorganize config into structs Add test coverage that callbacks are called Cleanup mouse config - Uses Duration type for ClickHandler::threshold - Removes `action` property from ClickHandler--this can be added in a backwards compatible way later on - Renames ClickState::DblClick to DoubleClick fixup! Cleanup mouse config
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
///