summaryrefslogtreecommitdiffstats
path: root/src/grid/row.rs
diff options
context:
space:
mode:
authorChristian Duerr <chrisduerr@users.noreply.github.com>2019-03-13 18:55:18 +0000
committerGitHub <noreply@github.com>2019-03-13 18:55:18 +0000
commitb1032bcc6b79135f87f327548e43563da05657fb (patch)
tree94915b15d11094006dcd3381b8ff0d0d3ed5de9b /src/grid/row.rs
parent0b9ae4ce936dfafbf5ea1929a170c97391cdea0b (diff)
Add text reflow
Alacritty will now automatically reflow lines and shrink them when they would usually exceed the new width of the terminal instead of truncation. If a line had to be truncated, it will also be reflown into the previous line after growing the terminal width. The reflow behavior when not at the bottom of the history is similar to that of VTE and aims to keep the viewport stationary whenever possible. Opposed to VTE, reflow will also be performed in the alternate screen buffer. There will be bugs when resizing the terminal emulator to a size smaller than the prompt, though these issues were present in all terminal emulators with reflow support. This fixes #591.
Diffstat (limited to 'src/grid/row.rs')
-rw-r--r--src/grid/row.rs93
1 files changed, 72 insertions, 21 deletions
diff --git a/src/grid/row.rs b/src/grid/row.rs
index 72c79b02..ef27f040 100644
--- a/src/grid/row.rs
+++ b/src/grid/row.rs
@@ -16,9 +16,10 @@
use std::ops::{Index, IndexMut};
use std::ops::{Range, RangeTo, RangeFrom, RangeFull, RangeToInclusive};
-use std::cmp::{max, min};
+use std::cmp::{min, max};
use std::slice;
+use crate::grid::GridCell;
use crate::index::Column;
/// A row in the grid
@@ -43,7 +44,7 @@ impl<T: PartialEq> PartialEq for Row<T> {
}
}
-impl<T: Copy + Clone> Row<T> {
+impl<T: Copy> Row<T> {
pub fn new(columns: Column, template: &T) -> Row<T> {
Row {
inner: vec![*template; *columns],
@@ -52,52 +53,102 @@ impl<T: Copy + Clone> Row<T> {
}
pub fn grow(&mut self, cols: Column, template: &T) {
- assert!(self.len() < * cols);
+ if self.inner.len() >= cols.0 {
+ return;
+ }
+
+ self.inner.append(&mut vec![*template; cols.0 - self.len()]);
+ }
+
+ pub fn shrink(&mut self, cols: Column) -> Option<Vec<T>>
+ where
+ T: GridCell
+ {
+ if self.inner.len() <= cols.0 {
+ return None;
+ }
+
+ // Split off cells for a new row
+ let mut new_row = self.inner.split_off(cols.0);
+ let index = new_row.iter().rposition(|c| !c.is_empty()).map(|i| i + 1).unwrap_or(0);
+ new_row.truncate(index);
+
+ self.occ = min(self.occ, *cols);
- while self.len() != *cols {
- self.inner.push(*template);
+ if new_row.is_empty() {
+ None
+ } else {
+ Some(new_row)
}
}
/// Resets contents to the contents of `other`
#[inline(never)]
pub fn reset(&mut self, other: &T) {
- let occ = self.occ;
- for item in &mut self.inner[..occ] {
+ for item in &mut self.inner[..self.occ] {
*item = *other;
}
-
self.occ = 0;
}
}
#[allow(clippy::len_without_is_empty)]
impl<T> Row<T> {
- pub fn shrink(&mut self, cols: Column) {
- while self.len() != *cols {
- self.inner.pop();
+ #[inline]
+ pub fn from_vec(vec: Vec<T>, occ: usize) -> Row<T> {
+ Row {
+ inner: vec,
+ occ,
}
-
- self.occ = min(self.occ, *cols);
}
+ #[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
- pub fn iter(&self) -> slice::Iter<'_, T> {
- self.inner.iter()
+ #[inline]
+ pub fn last(&self) -> Option<&T> {
+ self.inner.last()
}
-}
+ #[inline]
+ pub fn last_mut(&mut self) -> Option<&mut T> {
+ self.occ = self.inner.len();
+ self.inner.last_mut()
+ }
-impl<'a, T> IntoIterator for &'a Row<T> {
- type Item = &'a T;
- type IntoIter = slice::Iter<'a, T>;
+ #[inline]
+ pub fn append(&mut self, vec: &mut Vec<T>)
+ where
+ T: GridCell
+ {
+ self.inner.append(vec);
+ self.occ = self.inner.iter().rposition(|c| !c.is_empty()).map(|i| i + 1).unwrap_or(0);
+ }
#[inline]
- fn into_iter(self) -> slice::Iter<'a, T> {
- self.iter()
+ pub fn append_front(&mut self, mut vec: Vec<T>) {
+ self.occ += vec.len();
+ vec.append(&mut self.inner);
+ self.inner = vec;
+ }
+
+ #[inline]
+ pub fn is_empty(&self) -> bool
+ where
+ T: GridCell
+ {
+ self.inner.iter().all(|c| c.is_empty())
+ }
+
+ #[inline]
+ pub fn front_split_off(&mut self, at: usize) -> Vec<T> {
+ self.occ = self.occ.saturating_sub(at);
+
+ let mut split = self.inner.split_off(at);
+ std::mem::swap(&mut split, &mut self.inner);
+ split
}
}