From 277425956f361677deb1de92b25aeca9cbcd1cd1 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Thu, 12 Oct 2017 20:01:28 -0700 Subject: Move grid Row and tests into submodules This is part of some cleanup for the grid module as a whole. --- src/grid/row.rs | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/grid/row.rs (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs new file mode 100644 index 00000000..8711d04f --- /dev/null +++ b/src/grid/row.rs @@ -0,0 +1,186 @@ +// Copyright 2016 Joe Wilm, The Alacritty Project Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Defines the Row type which makes up lines in the grid + +use std::ops::{Deref, DerefMut, Index, IndexMut}; +use std::ops::{Range, RangeTo, RangeFrom, RangeFull}; +use std::slice; + +use index::Column; + +/// A row in the grid +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct Row(Vec); + +impl Row { + pub fn new(columns: Column, template: &T) -> Row { + Row(vec![template.to_owned(); *columns]) + } + + pub fn grow(&mut self, cols: Column, template: &T) { + while self.len() != *cols { + self.push(template.to_owned()); + } + } +} + +impl Row { + pub fn shrink(&mut self, cols: Column) { + while self.len() != *cols { + self.pop(); + } + } + + #[inline] + pub fn cells(&self) -> slice::Iter { + self.0.iter() + } + + #[inline] + pub fn cells_mut(&mut self) -> slice::IterMut { + self.0.iter_mut() + } +} + + +impl<'a, T> IntoIterator for &'a Row { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + #[inline] + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +impl<'a, T> IntoIterator for &'a mut Row { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + + #[inline] + fn into_iter(self) -> slice::IterMut<'a, T> { + self.iter_mut() + } +} + +impl Deref for Row { + type Target = Vec; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + + +impl DerefMut for Row { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Index for Row { + type Output = T; + + #[inline] + fn index(&self, index: Column) -> &T { + &self.0[index.0] + } +} + +impl IndexMut for Row { + #[inline] + fn index_mut(&mut self, index: Column) -> &mut T { + &mut self.0[index.0] + } +} + +macro_rules! row_index_range { + ($range:ty) => { + impl Index<$range> for Row { + type Output = [T]; + + #[inline] + fn index(&self, index: $range) -> &[T] { + &self.0[index] + } + } + + impl IndexMut<$range> for Row { + #[inline] + fn index_mut(&mut self, index: $range) -> &mut [T] { + &mut self.0[index] + } + } + } +} + +row_index_range!(Range); +row_index_range!(RangeTo); +row_index_range!(RangeFrom); +row_index_range!(RangeFull); + +// ----------------------------------------------------------------------------- +// Column ranges for Row +// ----------------------------------------------------------------------------- + +impl Index> for Row { + type Output = [T]; + + #[inline] + fn index(&self, index: Range) -> &[T] { + &self.0[(index.start.0)..(index.end.0)] + } +} + +impl IndexMut> for Row { + #[inline] + fn index_mut(&mut self, index: Range) -> &mut [T] { + &mut self.0[(index.start.0)..(index.end.0)] + } +} + +impl Index> for Row { + type Output = [T]; + + #[inline] + fn index(&self, index: RangeTo) -> &[T] { + &self.0[..(index.end.0)] + } +} + +impl IndexMut> for Row { + #[inline] + fn index_mut(&mut self, index: RangeTo) -> &mut [T] { + &mut self.0[..(index.end.0)] + } +} + +impl Index> for Row { + type Output = [T]; + + #[inline] + fn index(&self, index: RangeFrom) -> &[T] { + &self.0[(index.start.0)..] + } +} + +impl IndexMut> for Row { + #[inline] + fn index_mut(&mut self, index: RangeFrom) -> &mut [T] { + &mut self.0[(index.start.0)..] + } +} -- cgit From 4ed25009c49b5963d91f4e3c7ead0f4a5b678980 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Thu, 12 Oct 2017 20:29:35 -0700 Subject: Remove some unused methods and impls --- src/grid/row.rs | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index 8711d04f..4b355a56 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -108,33 +108,8 @@ impl IndexMut for Row { } } -macro_rules! row_index_range { - ($range:ty) => { - impl Index<$range> for Row { - type Output = [T]; - - #[inline] - fn index(&self, index: $range) -> &[T] { - &self.0[index] - } - } - - impl IndexMut<$range> for Row { - #[inline] - fn index_mut(&mut self, index: $range) -> &mut [T] { - &mut self.0[index] - } - } - } -} - -row_index_range!(Range); -row_index_range!(RangeTo); -row_index_range!(RangeFrom); -row_index_range!(RangeFull); - // ----------------------------------------------------------------------------- -// Column ranges for Row +// Index ranges of columns // ----------------------------------------------------------------------------- impl Index> for Row { @@ -184,3 +159,19 @@ impl IndexMut> for Row { &mut self.0[(index.start.0)..] } } + +impl Index for Row { + type Output = [T]; + + #[inline] + fn index(&self, _: RangeFull) -> &[T] { + &self.0[..] + } +} + +impl IndexMut for Row { + #[inline] + fn index_mut(&mut self, _: RangeFull) -> &mut [T] { + &mut self.0[..] + } +} -- cgit From 350bb8c800232ce0b27512420e99645ec8b95ef1 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Sun, 14 Jan 2018 10:17:08 -0800 Subject: Use memcpy for resetting row contents In addition to a marginal performance improvement, this simplifies some logic in the Term implementation since now the Grid fully handles row recycling. --- src/grid/row.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index 4b355a56..e9cf8dc9 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -24,16 +24,22 @@ use index::Column; #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Row(Vec); -impl Row { +impl Row { pub fn new(columns: Column, template: &T) -> Row { - Row(vec![template.to_owned(); *columns]) + Row(vec![*template; *columns]) } pub fn grow(&mut self, cols: Column, template: &T) { while self.len() != *cols { - self.push(template.to_owned()); + self.push(*template); } } + + /// Resets contents to the contents of `other` + #[inline] + pub fn reset(&mut self, other: &Row) { + self.copy_from_slice(&**other); + } } impl Row { -- cgit From 94796a70fcbc11df2dc642057fef242466822067 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Sun, 11 Feb 2018 21:25:33 -0800 Subject: wip scrollback --- src/grid/row.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index e9cf8dc9..1c83d45d 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -22,7 +22,10 @@ use index::Column; /// A row in the grid #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] -pub struct Row(Vec); +pub struct Row { + data: Vec, + id: u64 +} impl Row { pub fn new(columns: Column, template: &T) -> Row { @@ -37,8 +40,9 @@ impl Row { /// Resets contents to the contents of `other` #[inline] - pub fn reset(&mut self, other: &Row) { + pub fn reset(&mut self, other: &Row, id: u64) { self.copy_from_slice(&**other); + self.id = id; } } -- cgit From 45c2b3fbf72fa6dfd36bee590e64314c6da7c6c2 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Thu, 15 Feb 2018 18:35:49 -0800 Subject: checkpoint: very basic scrolling works Things that do not work - Limiting how far back in the buffer it's possible to scroll - Selections (need to transform to buffer offsets) --- src/grid/row.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index 1c83d45d..6b6af7c8 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -22,10 +22,7 @@ use index::Column; /// A row in the grid #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] -pub struct Row { - data: Vec, - id: u64 -} +pub struct Row(Vec); impl Row { pub fn new(columns: Column, template: &T) -> Row { @@ -40,9 +37,8 @@ impl Row { /// Resets contents to the contents of `other` #[inline] - pub fn reset(&mut self, other: &Row, id: u64) { + pub fn reset(&mut self, other: &Row) { self.copy_from_slice(&**other); - self.id = id; } } @@ -52,16 +48,6 @@ impl Row { self.pop(); } } - - #[inline] - pub fn cells(&self) -> slice::Iter { - self.0.iter() - } - - #[inline] - pub fn cells_mut(&mut self) -> slice::IterMut { - self.0.iter_mut() - } } -- cgit From 8ef062efd94975885776e61b6df936088b018da0 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Mon, 5 Mar 2018 09:57:34 -0800 Subject: Move selection into Grid Supporting selections with scrollback has two major components: 1. Grid needs access to Selection so that it may update the scroll position as the terminal text changes. 2. Selection needs to be implemented in terms of buffer offsets -- NOT lines -- and be updated when Storage is rotated. This commit implements the first part. --- src/grid/row.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index 6b6af7c8..f6b2a20e 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -21,7 +21,7 @@ use std::slice; use index::Column; /// A row in the grid -#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Row(Vec); impl Row { -- cgit From b19045da66899999856c6b2cc6707b60c607660a Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Mon, 2 Apr 2018 08:44:54 -0700 Subject: Fix BCE ref tests BCE was broken in attempt to optimize row clearing. The fix is to revert to passing in the current cursor state when clearing. --- src/grid/row.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index f6b2a20e..f7e4a98a 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -37,8 +37,10 @@ impl Row { /// Resets contents to the contents of `other` #[inline] - pub fn reset(&mut self, other: &Row) { - self.copy_from_slice(&**other); + pub fn reset(&mut self, other: &T) { + for item in &mut self.0 { + *item = *other; + } } } -- cgit From c3b7b98d6b19bbebf0b5a29689feb9b7162c9864 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 29 May 2018 11:13:49 -0700 Subject: Add assert to Row::grow This enforces the invariant that Row::Grow is only called when the row actually needs to be grown. --- src/grid/row.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index f7e4a98a..e907b61d 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -30,8 +30,10 @@ impl Row { } pub fn grow(&mut self, cols: Column, template: &T) { + assert!(self.len() < * cols); + while self.len() != *cols { - self.push(*template); + self.inner.push(*template); } } -- cgit From c01ce1e6ff3d36d0ec55707421e9f31fe000559f Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 29 May 2018 16:33:00 -0700 Subject: fixup! Add assert to Row::grow Resolves #1337 --- src/grid/row.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index e907b61d..55c82a0d 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -33,7 +33,7 @@ impl Row { assert!(self.len() < * cols); while self.len() != *cols { - self.inner.push(*template); + self.0.push(*template); } } -- cgit From c61a912f6221a320ec4787cd883527b0e7f26a8e Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Sat, 19 May 2018 11:18:37 -0700 Subject: Optimize Row::reset Now, only cells that have been used are cleared. This is achieved by using a "occupied" memo on the Row itself. The value, `occ`, is updated wherever the Row is accessed mutably, and it's cleared to zero in Row::reset. The tests for grid scroll_up and scroll_down were updated to include a test on the value `occ` and slightly refactored, but are otherwise equivalent to the previous implementation of those tests. Because of the change to the `Row` struct, the ref tests were updated so Deserialization keeps working as expected. --- src/grid/row.rs | 96 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 36 deletions(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index 55c82a0d..ea8804a7 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -14,43 +14,78 @@ //! Defines the Row type which makes up lines in the grid -use std::ops::{Deref, DerefMut, Index, IndexMut}; +use std::ops::{Index, IndexMut}; use std::ops::{Range, RangeTo, RangeFrom, RangeFull}; +use std::cmp::{max, min}; use std::slice; use index::Column; /// A row in the grid -#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] -pub struct Row(Vec); +#[derive(Default, Clone, Debug, Serialize, Deserialize)] +pub struct Row { + inner: Vec, + + /// occupied entries + /// + /// Semantically, this value can be understood as the **end** of an + /// Exclusive Range. Thus, + /// + /// - Zero means there are no occupied entries + /// - 1 means there is a value at index zero, but nowhere else + /// - `occ == inner.len` means every value is occupied + pub(crate) occ: usize, +} + +impl PartialEq for Row { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } +} impl Row { pub fn new(columns: Column, template: &T) -> Row { - Row(vec![*template; *columns]) + Row { + inner: vec![*template; *columns], + occ: 0, + } } pub fn grow(&mut self, cols: Column, template: &T) { assert!(self.len() < * cols); while self.len() != *cols { - self.0.push(*template); + self.inner.push(*template); } } /// Resets contents to the contents of `other` - #[inline] + #[inline(never)] pub fn reset(&mut self, other: &T) { - for item in &mut self.0 { + let occ = self.occ; + for item in &mut self.inner[..occ] { *item = *other; } + + self.occ = 0; } } impl Row { pub fn shrink(&mut self, cols: Column) { while self.len() != *cols { - self.pop(); + self.inner.pop(); } + + self.occ = min(self.occ, *cols); + } + + pub fn len(&self) -> usize { + self.inner.len() + } + + pub fn iter<'a>(&'a self) -> slice::Iter<'a, T> { + self.inner.iter() } } @@ -71,24 +106,8 @@ impl<'a, T> IntoIterator for &'a mut Row { #[inline] fn into_iter(self) -> slice::IterMut<'a, T> { - self.iter_mut() - } -} - -impl Deref for Row { - type Target = Vec; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.0 - } -} - - -impl DerefMut for Row { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 + self.occ = self.len(); + self.inner.iter_mut() } } @@ -97,14 +116,15 @@ impl Index for Row { #[inline] fn index(&self, index: Column) -> &T { - &self.0[index.0] + &self.inner[index.0] } } impl IndexMut for Row { #[inline] fn index_mut(&mut self, index: Column) -> &mut T { - &mut self.0[index.0] + self.occ = max(self.occ, *index + 1); + &mut self.inner[index.0] } } @@ -117,14 +137,15 @@ impl Index> for Row { #[inline] fn index(&self, index: Range) -> &[T] { - &self.0[(index.start.0)..(index.end.0)] + &self.inner[(index.start.0)..(index.end.0)] } } impl IndexMut> for Row { #[inline] fn index_mut(&mut self, index: Range) -> &mut [T] { - &mut self.0[(index.start.0)..(index.end.0)] + self.occ = max(self.occ, *index.end); + &mut self.inner[(index.start.0)..(index.end.0)] } } @@ -133,14 +154,15 @@ impl Index> for Row { #[inline] fn index(&self, index: RangeTo) -> &[T] { - &self.0[..(index.end.0)] + &self.inner[..(index.end.0)] } } impl IndexMut> for Row { #[inline] fn index_mut(&mut self, index: RangeTo) -> &mut [T] { - &mut self.0[..(index.end.0)] + self.occ = max(self.occ, *index.end); + &mut self.inner[..(index.end.0)] } } @@ -149,14 +171,15 @@ impl Index> for Row { #[inline] fn index(&self, index: RangeFrom) -> &[T] { - &self.0[(index.start.0)..] + &self.inner[(index.start.0)..] } } impl IndexMut> for Row { #[inline] fn index_mut(&mut self, index: RangeFrom) -> &mut [T] { - &mut self.0[(index.start.0)..] + self.occ = self.len(); + &mut self.inner[(index.start.0)..] } } @@ -165,13 +188,14 @@ impl Index for Row { #[inline] fn index(&self, _: RangeFull) -> &[T] { - &self.0[..] + &self.inner[..] } } impl IndexMut for Row { #[inline] fn index_mut(&mut self, _: RangeFull) -> &mut [T] { - &mut self.0[..] + self.occ = self.len(); + &mut self.inner[..] } } -- cgit From f50ca1a54c94fe324d22d985c1acae1ff7c16a80 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sat, 21 Jul 2018 17:17:41 +0000 Subject: Scrollback cleanup There were some unneeded codeblocks and TODO/XXX comments in the code that have been removed. All issues marked with TODO/XXX have either been already resolved or tracking issues exist. --- src/grid/row.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/grid/row.rs') diff --git a/src/grid/row.rs b/src/grid/row.rs index ea8804a7..69a4f2b2 100644 --- a/src/grid/row.rs +++ b/src/grid/row.rs @@ -71,6 +71,7 @@ impl Row { } } +#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))] impl Row { pub fn shrink(&mut self, cols: Column) { while self.len() != *cols { @@ -84,7 +85,7 @@ impl Row { self.inner.len() } - pub fn iter<'a>(&'a self) -> slice::Iter<'a, T> { + pub fn iter(&self) -> slice::Iter { self.inner.iter() } } -- cgit