diff options
author | Xiaoyu Yin <yin530@gmail.com> | 2017-01-14 17:53:48 -0800 |
---|---|---|
committer | Joe Wilm <jwilm@users.noreply.github.com> | 2017-02-07 21:04:18 -0800 |
commit | 92e1cec0880313d962d80bf16eca60cebb509eab (patch) | |
tree | 165d470ca13ab89dcf8b399b7491f3766b446ab2 /src/grid.rs | |
parent | 59295e44312b3936132965636e5fac92118e5c27 (diff) | |
download | alacritty-92e1cec0880313d962d80bf16eca60cebb509eab.tar.gz alacritty-92e1cec0880313d962d80bf16eca60cebb509eab.zip |
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/grid.rs')
-rw-r--r-- | src/grid.rs | 114 |
1 files changed, 111 insertions, 3 deletions
diff --git a/src/grid.rs b/src/grid.rs index d913e640..c886807b 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -26,13 +26,18 @@ use std::iter::IntoIterator; use std::ops::{Deref, DerefMut, Range, RangeTo, RangeFrom, RangeFull, Index, IndexMut}; use std::slice::{self, Iter, IterMut}; -use index::{self, Point, IndexRange, RangeInclusive}; +use index::{self, Point, Line, Column, IndexRange, RangeInclusive}; /// Convert a type to a linear index range. pub trait ToRange { fn to_range(&self, columns: index::Column) -> RangeInclusive<index::Linear>; } +/// Bidirection iterator +pub trait BidirectionalIterator: Iterator { + fn prev(&mut self) -> Option<Self::Item>; +} + /// Represents the terminal display contents #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] pub struct Grid<T> { @@ -49,6 +54,11 @@ pub struct Grid<T> { lines: index::Line, } +pub struct GridIterator<'a, T: 'a> { + grid: &'a Grid<T>, + pub cur: Point, +} + impl<T: Clone> Grid<T> { pub fn new(lines: index::Line, cols: index::Column, template: &T) -> Grid<T> { let mut raw = Vec::with_capacity(*lines); @@ -139,6 +149,13 @@ impl<T> Grid<T> { } } + pub fn iter_from(&self, point: Point) -> GridIterator<T> { + GridIterator { + grid: self, + cur: point, + } + } + #[inline] pub fn contains(&self, point: &Point) -> bool { self.lines > point.line && self.cols > point.col @@ -193,6 +210,49 @@ impl<T> Grid<T> { } } +impl<'a, T> Iterator for GridIterator<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<Self::Item> { + let last_line = self.grid.num_lines() - Line(1); + let last_col = self.grid.num_cols() - Column(1); + match self.cur { + Point { line, col } if + (line == last_line) && + (col == last_col) => None, + Point { col, .. } if + (col == last_col) => { + self.cur.line += Line(1); + self.cur.col = Column(0); + Some(&self.grid[self.cur.line][self.cur.col]) + }, + _ => { + self.cur.col += Column(1); + Some(&self.grid[self.cur.line][self.cur.col]) + } + } + } +} + +impl<'a, T> BidirectionalIterator for GridIterator<'a, T> { + fn prev(&mut self) -> Option<Self::Item> { + let num_cols = self.grid.num_cols(); + + match self.cur { + Point { line: Line(0), col: Column(0) } => None, + Point { col: Column(0), .. } => { + self.cur.line -= Line(1); + self.cur.col = num_cols - Column(1); + Some(&self.grid[self.cur.line][self.cur.col]) + }, + _ => { + self.cur.col -= Column(1); + Some(&self.grid[self.cur.line][self.cur.col]) + } + } + } +} + impl<T> Index<index::Line> for Grid<T> { type Output = Row<T>; @@ -464,8 +524,8 @@ clear_region_impl!(RangeFrom<index::Line>); #[cfg(test)] mod tests { - use super::Grid; - use index::{Line, Column}; + use super::{Grid, BidirectionalIterator}; + use index::{Point, Line, Column}; #[test] fn grid_swap_lines_ok() { let mut grid = Grid::new(Line(10), Column(1), &0); @@ -588,4 +648,52 @@ mod tests { assert_eq!(grid[Line(i)][Column(0)], other[Line(i)][Column(0)]); } } + + // Test that GridIterator works + #[test] + fn test_iter() { + info!(""); + + let mut grid = Grid::new(Line(5), Column(5), &0); + for i in 0..5 { + for j in 0..5 { + grid[Line(i)][Column(j)] = i*5 + j; + } + } + + info!("grid: {:?}", grid); + + let mut iter = grid.iter_from(Point { + line: Line(0), + col: Column(0), + }); + + assert_eq!(None, iter.prev()); + assert_eq!(Some(&1), iter.next()); + assert_eq!(Column(1), iter.cur.col); + assert_eq!(Line(0), iter.cur.line); + + assert_eq!(Some(&2), iter.next()); + assert_eq!(Some(&3), iter.next()); + assert_eq!(Some(&4), iter.next()); + + // test linewrapping + assert_eq!(Some(&5), iter.next()); + assert_eq!(Column(0), iter.cur.col); + assert_eq!(Line(1), iter.cur.line); + + assert_eq!(Some(&4), iter.prev()); + assert_eq!(Column(4), iter.cur.col); + assert_eq!(Line(0), iter.cur.line); + + + // test that iter ends at end of grid + let mut final_iter = grid.iter_from(Point { + line: Line(4), + col: Column(4), + }); + assert_eq!(None, final_iter.next()); + assert_eq!(Some(&23), final_iter.prev()); + } + } |