summaryrefslogtreecommitdiffstats
path: root/alacritty_terminal
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2020-07-09 21:45:22 +0000
committerGitHub <noreply@github.com>2020-07-09 21:45:22 +0000
commit46c0f352c40ecb68653421cb178a297acaf00c6d (patch)
tree3e1985f8237f7c8268703634f8c8ccb25f7823a5 /alacritty_terminal
parent9974bc8baa45fda0b4ba3db2ae615fb7f90f7029 (diff)
Add regex scrollback buffer search
This adds a new regex search which allows searching the entire scrollback and jumping between matches using the vi mode. All visible matches should be highlighted unless their lines are excessively long. This should help with performance since highlighting is done during render time. Fixes #1017.
Diffstat (limited to 'alacritty_terminal')
-rw-r--r--alacritty_terminal/Cargo.toml1
-rw-r--r--alacritty_terminal/src/ansi.rs34
-rw-r--r--alacritty_terminal/src/config/colors.rs124
-rw-r--r--alacritty_terminal/src/config/mod.rs27
-rw-r--r--alacritty_terminal/src/grid/mod.rs209
-rw-r--r--alacritty_terminal/src/grid/resize.rs26
-rw-r--r--alacritty_terminal/src/grid/storage.rs4
-rw-r--r--alacritty_terminal/src/grid/tests.rs19
-rw-r--r--alacritty_terminal/src/index.rs177
-rw-r--r--alacritty_terminal/src/selection.rs79
-rw-r--r--alacritty_terminal/src/term/cell.rs28
-rw-r--r--alacritty_terminal/src/term/color.rs87
-rw-r--r--alacritty_terminal/src/term/mod.rs677
-rw-r--r--alacritty_terminal/src/term/search.rs794
-rw-r--r--alacritty_terminal/src/vi_mode.rs182
-rw-r--r--alacritty_terminal/tests/ref.rs9
16 files changed, 1797 insertions, 680 deletions
diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml
index 65a12c6f..9345a76f 100644
--- a/alacritty_terminal/Cargo.toml
+++ b/alacritty_terminal/Cargo.toml
@@ -22,6 +22,7 @@ log = "0.4"
unicode-width = "0.1"
base64 = "0.12.0"
terminfo = "0.7.1"
+regex-automata = "0.1.9"
[target.'cfg(unix)'.dependencies]
nix = "0.17.0"
diff --git a/alacritty_terminal/src/ansi.rs b/alacritty_terminal/src/ansi.rs
index 8240ff00..5f24dcff 100644
--- a/alacritty_terminal/src/ansi.rs
+++ b/alacritty_terminal/src/ansi.rs
@@ -89,13 +89,13 @@ struct ProcessorState {
///
/// Processor creates a Performer when running advance and passes the Performer
/// to `vte::Parser`.
-struct Performer<'a, H: Handler + TermInfo, W: io::Write> {
+struct Performer<'a, H: Handler, W: io::Write> {
state: &'a mut ProcessorState,
handler: &'a mut H,
writer: &'a mut W,
}
-impl<'a, H: Handler + TermInfo + 'a, W: io::Write> Performer<'a, H, W> {
+impl<'a, H: Handler + 'a, W: io::Write> Performer<'a, H, W> {
/// Create a performer.
#[inline]
pub fn new<'b>(
@@ -121,7 +121,7 @@ impl Processor {
#[inline]
pub fn advance<H, W>(&mut self, handler: &mut H, byte: u8, writer: &mut W)
where
- H: Handler + TermInfo,
+ H: Handler,
W: io::Write,
{
let mut performer = Performer::new(&mut self.state, handler, writer);
@@ -129,12 +129,6 @@ impl Processor {
}
}
-/// Trait that provides properties of terminal.
-pub trait TermInfo {
- fn lines(&self) -> Line;
- fn cols(&self) -> Column;
-}
-
/// Type that handles actions from the parser.
///
/// XXX Should probably not provide default impls for everything, but it makes
@@ -278,7 +272,7 @@ pub trait Handler {
fn unset_mode(&mut self, _: Mode) {}
/// DECSTBM - Set the terminal scrolling region.
- fn set_scrolling_region(&mut self, _top: usize, _bottom: usize) {}
+ fn set_scrolling_region(&mut self, _top: usize, _bottom: Option<usize>) {}
/// DECKPAM - Set keypad to applications mode (ESCape instead of digits).
fn set_keypad_application_mode(&mut self) {}
@@ -731,7 +725,7 @@ impl StandardCharset {
impl<'a, H, W> vte::Perform for Performer<'a, H, W>
where
- H: Handler + TermInfo + 'a,
+ H: Handler + 'a,
W: io::Write + 'a,
{
#[inline]
@@ -945,9 +939,7 @@ where
macro_rules! arg_or_default {
(idx: $idx:expr, default: $default:expr) => {
- args.get($idx)
- .and_then(|v| if *v == 0 { None } else { Some(*v) })
- .unwrap_or($default)
+ args.get($idx).copied().filter(|&v| v != 0).unwrap_or($default)
};
}
@@ -1099,7 +1091,7 @@ where
},
('r', None) => {
let top = arg_or_default!(idx: 0, default: 1) as usize;
- let bottom = arg_or_default!(idx: 1, default: handler.lines().0 as _) as usize;
+ let bottom = args.get(1).map(|&b| b as usize).filter(|&b| b != 0);
handler.set_scrolling_region(top, bottom);
},
@@ -1391,9 +1383,7 @@ pub mod C0 {
mod tests {
use super::{
parse_number, xparse_color, Attr, CharsetIndex, Color, Handler, Processor, StandardCharset,
- TermInfo,
};
- use crate::index::{Column, Line};
use crate::term::color::Rgb;
use std::io;
@@ -1427,16 +1417,6 @@ mod tests {
}
}
- impl TermInfo for MockHandler {
- fn lines(&self) -> Line {
- Line(200)
- }
-
- fn cols(&self) -> Column {
- Column(90)
- }
- }
-
impl Default for MockHandler {
fn default() -> MockHandler {
MockHandler {
diff --git a/alacritty_terminal/src/config/colors.rs b/alacritty_terminal/src/config/colors.rs
index ccea9536..13a30bef 100644
--- a/alacritty_terminal/src/config/colors.rs
+++ b/alacritty_terminal/src/config/colors.rs
@@ -1,8 +1,9 @@
use log::error;
use serde::{Deserialize, Deserializer};
+use serde_yaml::Value;
use crate::config::{failure_default, LOG_TARGET_CONFIG};
-use crate::term::color::Rgb;
+use crate::term::color::{CellRgb, Rgb};
#[serde(default)]
#[derive(Deserialize, Clone, Debug, Default, PartialEq, Eq)]
@@ -23,6 +24,8 @@ pub struct Colors {
pub dim: Option<AnsiColors>,
#[serde(deserialize_with = "failure_default")]
pub indexed_colors: Vec<IndexedColor>,
+ #[serde(deserialize_with = "failure_default")]
+ pub search: SearchColors,
}
impl Colors {
@@ -33,6 +36,32 @@ impl Colors {
pub fn bright(&self) -> &AnsiColors {
&self.bright.0
}
+
+ pub fn search_bar_foreground(&self) -> Rgb {
+ self.search.bar.foreground.unwrap_or(self.primary.background)
+ }
+
+ pub fn search_bar_background(&self) -> Rgb {
+ self.search.bar.background.unwrap_or(self.primary.foreground)
+ }
+}
+
+#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
+struct DefaultForegroundCellRgb(CellRgb);
+
+impl Default for DefaultForegroundCellRgb {
+ fn default() -> Self {
+ Self(CellRgb::CellForeground)
+ }
+}
+
+#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
+struct DefaultBackgroundCellRgb(CellRgb);
+
+impl Default for DefaultBackgroundCellRgb {
+ fn default() -> Self {
+ Self(CellRgb::CellBackground)
+ }
}
#[serde(default)]
@@ -44,11 +73,11 @@ pub struct IndexedColor {
pub color: Rgb,
}
-fn deserialize_color_index<'a, D>(deserializer: D) -> ::std::result::Result<u8, D::Error>
+fn deserialize_color_index<'a, D>(deserializer: D) -> Result<u8, D::Error>
where
D: Deserializer<'a>,
{
- let value = serde_yaml::Value::deserialize(deserializer)?;
+ let value = Value::deserialize(deserializer)?;
match u8::deserialize(value) {
Ok(index) => {
if index < 16 {
@@ -78,26 +107,91 @@ where
#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct CursorColors {
#[serde(deserialize_with = "failure_default")]
- pub text: Option<Rgb>,
+ text: DefaultBackgroundCellRgb,
#[serde(deserialize_with = "failure_default")]
- pub cursor: Option<Rgb>,
+ cursor: DefaultForegroundCellRgb,
+}
+
+impl CursorColors {
+ pub fn text(self) -> CellRgb {
+ self.text.0
+ }
+
+ pub fn cursor(self) -> CellRgb {
+ self.cursor.0
+ }
}
#[serde(default)]
#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct SelectionColors {
#[serde(deserialize_with = "failure_default")]
- pub text: Option<Rgb>,
+ text: DefaultBackgroundCellRgb,
+ #[serde(deserialize_with = "failure_default")]
+ background: DefaultForegroundCellRgb,
+}
+
+impl SelectionColors {
+ pub fn text(self) -> CellRgb {
+ self.text.0
+ }
+
+ pub fn background(self) -> CellRgb {
+ self.background.0
+ }
+}
+
+#[serde(default)]
+#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)]
+pub struct SearchColors {
+ #[serde(deserialize_with = "failure_default")]
+ pub matches: MatchColors,
#[serde(deserialize_with = "failure_default")]
- pub background: Option<Rgb>,
+ bar: BarColors,
+}
+
+#[serde(default)]
+#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
+pub struct MatchColors {
+ #[serde(deserialize_with = "failure_default")]
+ pub foreground: CellRgb,
+ #[serde(deserialize_with = "deserialize_match_background")]
+ pub background: CellRgb,
+}
+
+impl Default for MatchColors {
+ fn default() -> Self {
+ Self { foreground: CellRgb::default(), background: default_match_background() }
+ }
+}
+
+fn deserialize_match_background<'a, D>(deserializer: D) -> Result<CellRgb, D::Error>
+where
+ D: Deserializer<'a>,
+{
+ let value = Value::deserialize(deserializer)?;
+ Ok(CellRgb::deserialize(value).unwrap_or_else(|_| default_match_background()))
+}
+
+fn default_match_background() -> CellRgb {
+ CellRgb::Rgb(Rgb { r: 0xff, g: 0xff, b: 0xff })
+}
+
+#[serde(default)]
+#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)]
+pub struct BarColors {
+ #[serde(deserialize_with = "failure_default")]
+ foreground: Option<Rgb>,
+ #[serde(deserialize_with = "failure_default")]
+ background: Option<Rgb>,
}
#[serde(default)]
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct PrimaryColors {
- #[serde(default = "default_background", deserialize_with = "failure_default")]
+ #[serde(deserialize_with = "failure_default")]
pub background: Rgb,
- #[serde(default = "default_foreground", deserialize_with = "failure_default")]
+ #[serde(deserialize_with = "failure_default")]
pub foreground: Rgb,
#[serde(deserialize_with = "failure_default")]
pub bright_foreground: Option<Rgb>,
@@ -108,22 +202,14 @@ pub struct PrimaryColors {
impl Default for PrimaryColors {
fn default() -> Self {
PrimaryColors {
- background: default_background(),
- foreground: default_foreground(),
+ background: Rgb { r: 0x1d, g: 0x1f, b: 0x21 },
+ foreground: Rgb { r: 0xc5, g: 0xc8, b: 0xc6 },
bright_foreground: Default::default(),
dim_foreground: Default::default(),
}
}
}
-fn default_background() -> Rgb {
- Rgb { r: 0x1d, g: 0x1f, b: 0x21 }
-}
-
-fn default_foreground() -> Rgb {
- Rgb { r: 0xc5, g: 0xc8, b: 0xc6 }
-}
-
/// The 8-colors sections of config.
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct AnsiColors {
diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs
index c3936c0c..e3d72fda 100644
--- a/alacritty_terminal/src/config/mod.rs
+++ b/alacritty_terminal/src/config/mod.rs
@@ -13,7 +13,7 @@ mod scrolling;
mod visual_bell;
mod window;
-use crate::ansi::{CursorStyle, NamedColor};
+use crate::ansi::CursorStyle;
pub use crate::config::colors::Colors;
pub use crate::config::debug::Debug;
@@ -21,7 +21,6 @@ pub use crate::config::font::{Font, FontDescription};
pub use crate::config::scrolling::Scrolling;
pub use crate::config::visual_bell::{VisualBellAnimation, VisualBellConfig};
pub use crate::config::window::{Decorations, Dimensions, StartupMode, WindowConfig, DEFAULT_NAME};
-use crate::term::color::Rgb;
pub const LOG_TARGET_CONFIG: &str = "alacritty_config";
const MAX_SCROLLBACK_LINES: u32 = 100_000;
@@ -156,30 +155,6 @@ impl<T> Config<T> {
self.dynamic_title.0
}
- /// Cursor foreground color.
- #[inline]
- pub fn cursor_text_color(&self) -> Option<Rgb> {
- self.colors.cursor.text
- }
-
- /// Cursor background color.
- #[inline]
- pub fn cursor_cursor_color(&self) -> Option<NamedColor> {
- self.colors.cursor.cursor.map(|_| NamedColor::Cursor)
- }
-
- /// Vi mode cursor foreground color.
- #[inline]
- pub fn vi_mode_cursor_text_color(&self) -> Option<Rgb> {
- self.colors.vi_mode_cursor.text
- }
-
- /// Vi mode cursor background color.
- #[inline]
- pub fn vi_mode_cursor_cursor_color(&self) -> Option<Rgb> {
- self.colors.vi_mode_cursor.cursor
- }
-
#[inline]
pub fn set_dynamic_title(&mut self, dynamic_title: bool) {
self.dynamic_title.0 = dynamic_title;
diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs
index 5ad7e8d6..c1f980e8 100644
--- a/alacritty_terminal/src/grid/mod.rs
+++ b/alacritty_terminal/src/grid/mod.rs
@@ -160,7 +160,7 @@ pub struct Grid<T> {
#[derive(Debug, Copy, Clone)]
pub enum Scroll {
- Lines(isize),
+ Delta(isize),
PageUp,
PageDown,
Top,
@@ -180,23 +180,6 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
}
}
- /// Clamp a buffer point to the visible region.
- pub fn clamp_buffer_to_visible(&self, point: Point<usize>) -> Point {
- if point.line < self.display_offset {
- Point::new(self.lines - 1, self.cols - 1)
- } else if point.line >= self.display_offset + self.lines.0 {
- Point::new(Line(0), Column(0))
- } else {
- // Since edge-cases are handled, conversion is identical as visible to buffer.
- self.visible_to_buffer(point.into()).into()
- }
- }
-
- /// Convert viewport relative point to global buffer indexing.
- pub fn visible_to_buffer(&self, point: Point) -> Point<usize> {
- Point { line: self.lines.0 + self.display_offset - point.line.0 - 1, col: point.col }
- }
-
/// Update the size of the scrollback history.
pub fn update_history(&mut self, history_size: usize) {
let current_history_size = self.history_size();
@@ -208,22 +191,16 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
}
pub fn scroll_display(&mut self, scroll: Scroll) {
- match scroll {
- Scroll::Lines(count) => {
- self.display_offset = min(
- max((self.display_offset as isize) + count, 0isize) as usize,
- self.history_size(),
- );
- },
- Scroll::PageUp => {
- self.display_offset = min(self.display_offset + self.lines.0, self.history_size());
- },
- Scroll::PageDown => {
- self.display_offset -= min(self.display_offset, self.lines.0);
- },
- Scroll::Top => self.display_offset = self.history_size(),
- Scroll::Bottom => self.display_offset = 0,
- }
+ self.display_offset = match scroll {
+ Scroll::Delta(count) => min(
+ max((self.display_offset as isize) + count, 0isize) as usize,
+ self.history_size(),
+ ),
+ Scroll::PageUp => min(self.display_offset + self.lines.0, self.history_size()),
+ Scroll::PageDown => self.display_offset.saturating_sub(self.lines.0),
+ Scroll::Top => self.history_size(),
+ Scroll::Bottom => 0,
+ };
}
fn increase_scroll_limit(&mut self, count: usize, template: T) {
@@ -279,7 +256,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
///
/// This is the performance-sensitive part of scrolling.
pub fn scroll_up(&mut self, region: &Range<Line>, positions: Line, template: T) {
- let num_lines = self.num_lines().0;
+ let num_lines = self.screen_lines().0;
if region.start == Line(0) {
// Update display offset when not pinned to active area.
@@ -324,7 +301,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
pub fn clear_viewport(&mut self, template: T) {
// Determine how many lines to scroll up by.
- let end = Point { line: 0, col: self.num_cols() };
+ let end = Point { line: 0, col: self.cols() };
let mut iter = self.iter_from(end);
while let Some(cell) = iter.prev() {
if !cell.is_empty() || iter.cur.line >= *self.lines {
@@ -333,7 +310,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
}
debug_assert!(iter.cur.line <= *self.lines);
let positions = self.lines - iter.cur.line;
- let region = Line(0)..self.num_lines();
+ let region = Line(0)..self.screen_lines();
// Reset display offset.
self.display_offset = 0;
@@ -364,19 +341,27 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
#[allow(clippy::len_without_is_empty)]
impl<T> Grid<T> {
- #[inline]
- pub fn num_lines(&self) -> Line {
- self.lines
+ /// Clamp a buffer point to the visible region.
+ pub fn clamp_buffer_to_visible(&self, point: Point<usize>) -> Point {
+ if point.line < self.display_offset {
+ Point::new(self.lines - 1, self.cols - 1)
+ } else if point.line >= self.display_offset + self.lines.0 {
+ Point::new(Line(0), Column(0))
+ } else {
+ // Since edgecases are handled, conversion is identical as visible to buffer.
+ self.visible_to_buffer(point.into()).into()
+ }
}
+ /// Convert viewport relative point to global buffer indexing.
#[inline]
- pub fn display_iter(&self) -> DisplayIter<'_, T> {
- DisplayIter::new(self)
+ pub fn visible_to_buffer(&self, point: Point) -> Point<usize> {
+ Point { line: self.lines.0 + self.display_offset - point.line.0 - 1, col: point.col }
}
#[inline]
- pub fn num_cols(&self) -> Column {
- self.cols
+ pub fn display_iter(&self) -> DisplayIter<'_, T> {
+ DisplayIter::new(self)
}
#[inline]
@@ -385,17 +370,6 @@ impl<T> Grid<T> {
self.raw.shrink_lines(self.history_size());
}
- /// Total number of lines in the buffer, this includes scrollback + visible lines.
- #[inline]
- pub fn len(&self) -> usize {
- self.raw.len()
- }
-
- #[inline]
- pub fn history_size(&self) -> usize {
- self.raw.len() - *self.lines
- }
-
/// This is used only for initializing after loading ref-tests.
#[inline]
pub fn initialize_all(&mut self, template: T)
@@ -432,6 +406,56 @@ impl<T> Grid<T> {
}
}
+/// Grid dimensions.
+pub trait Dimensions {
+ /// Total number of lines in the buffer, this includes scrollback and visible lines.
+ fn total_lines(&self) -> usize;
+
+ /// Height of the viewport in lines.
+ fn screen_lines(&self) -> Line;
+
+ /// Width of the terminal in columns.
+ fn cols(&self) -> Column;
+
+ /// Number of invisible lines part of the scrollback history.
+ #[inline]
+ fn history_size(&self) -> usize {
+ self.total_lines() - self.screen_lines().0
+ }
+}
+
+impl<G> Dimensions for Grid<G> {
+ #[inline]
+ fn total_lines(&self) -> usize {
+ self.raw.len()
+ }
+
+ #[inline]
+ fn screen_lines(&self) -> Line {
+ self.lines
+ }
+
+ #[inline]
+ fn cols(&self) -> Column {
+ self.cols
+ }
+}
+
+#[cfg(test)]
+impl Dimensions for (Line, Column) {
+ fn total_lines(&self) -> usize {
+ *self.0
+ }
+
+ fn screen_lines(&self) -> Line {
+ self.0
+ }
+
+ fn cols(&self) -> Column {
+ self.1
+ }
+}
+
pub struct GridIterator<'a, T> {
/// Immutable grid reference.
grid: &'a Grid<T>,
@@ -446,7 +470,7 @@ impl<'a, T> GridIterator<'a, T> {
}
pub fn cell(&self) -> &'a T {
- &self.grid[self.cur.line][self.cur.col]
+ &self.grid[self.cur]
}
}
@@ -454,38 +478,35 @@ impl<'a, T> Iterator for GridIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
- let last_col = self.grid.num_cols() - Column(1);
+ let last_col = self.grid.cols() - 1;
+
match self.cur {
- Point { line, col } if line == 0 && col == last_col => None,
+ Point { line, col } if line == 0 && col == last_col => return None,
Point { col, .. } if (col == last_col) => {
self.cur.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])
},
+ _ => self.cur.col += Column(1),
}
+
+ Some(&self.grid[self.cur])
}
}
impl<'a, T> BidirectionalIterator for GridIterator<'a, T> {
fn prev(&mut self) -> Option<Self::Item> {
- let num_cols = self.grid.num_cols();
+ let last_col = self.grid.cols() - 1;
match self.cur {
- Point { line, col: Column(0) } if line == self.grid.len() - 1 => None,
+ Point { line, col: Column(0) } if line == self.grid.total_lines() - 1 => return None,
Point { col: Column(0), .. } => {
self.cur.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])
+ self.cur.col = last_col;
},
+ _ => self.cur.col -= Column(1),
}
+
+ Some(&self.grid[self.cur])
}
}
@@ -539,6 +560,22 @@ impl<'point, T> IndexMut<&'point Point> for Grid<T> {
}
}
+impl<T> Index<Point<usize>> for Grid<T> {
+ type Output = T;
+
+ #[inline]
+ fn index(&self, point: Point<usize>) -> &T {
+ &self[point.line][point.col]
+ }
+}
+
+impl<T> IndexMut<Point<usize>> for Grid<T> {
+ #[inline]
+ fn index_mut(&mut self, point: Point<usize>) -> &mut T {
+ &mut self[point.line][point.col]
+ }
+}
+
/// A subset of lines in the grid.
///
/// May be constructed using Grid::region(..).
@@ -578,15 +615,15 @@ pub trait IndexRegion<I, T> {
impl<T> IndexRegion<Range<Line>, T> for Grid<T> {
fn region(&self, index: Range<Line>) -> Region<'_, T> {
- assert!(index.start < self.num_lines());
- assert!(index.end <= self.num_lines());
+ assert!(index.start < self.screen_lines());
+ assert!(index.end <= self.screen_lines());
assert!(index.start <= index.end);
Region { start: index.start, end: index.end, raw: &self.raw }
}
fn region_mut(&mut self, index: Range<Line>) -> RegionMut<'_, T> {
- assert!(index.start < self.num_lines());
- assert!(index.end <= self.num_lines());
+ assert!(index.start < self.screen_lines());
+ assert!(index.end <= self.screen_lines());
assert!(index.start <= index.end);
RegionMut { start: index.start, end: index.end, raw: &mut self.raw }
}
@@ -594,35 +631,35 @@ impl<T> IndexRegion<Range<Line>, T> for Grid<T> {
impl<T> IndexRegion<RangeTo<Line>, T> for Grid<T> {
fn region(&self, index: RangeTo<Line>) -> Region<'_, T> {
- assert!(index.end <= self.num_lines());
+ assert!(index.end <= self.screen_lines());
Region { start: Line(0), end: index.end, raw: &self.raw }
}
fn region_mut(&mut self, index: RangeTo<Line>) -> RegionMut<'_, T> {
- assert!(index.end <= self.num_lines());
+ assert!(index.end <= self.screen_lines());
RegionMut { start: Line(0), end: index.end, raw: &mut self.raw }
}
}
impl<T> IndexRegion<RangeFrom<Line>, T> for Grid<T> {
fn region(&self, index: RangeFrom<Line>) -> Region<'_, T> {
- assert!(index.start < self.num_lines());
- Region { start: index.start, end: self.num_lines(), raw: &self.raw }
+ assert!(index.start < self.screen_lines());
+ Region { start: index.start, end: self.screen_lines(), raw: &self.raw }
}
fn region_mut(&mut self, index: RangeFrom<Line>) -> RegionMut<'_, T> {
- assert!(index.start < self.num_lines());
- RegionMut { start: index.start, end: self.num_lines(), raw: &mut self.raw }
+ assert!(index.start < self.screen_lines());
+ RegionMut { start: index.start, end: self.screen_lines(), raw: &mut self.raw }
}
}
impl<T> IndexRegion<RangeFull, T> for Grid<T> {
fn region(&self, _: RangeFull) -> Region<'_, T> {
- Region { start: Line(0), end: self.num_lines(), raw: &self.raw }
+ Region { start: Line(0), end: self.screen_lines(), raw: &self.raw }
}
fn region_mut(&mut self, _: RangeFull) -> RegionMut<'_, T> {
- RegionMut { start: Line(0), end: self.num_lines(), raw: &mut self.raw }
+ RegionMut { start: Line(0), end: self.screen_lines(), raw: &mut self.raw }
}
}
@@ -695,7 +732,7 @@ pub struct DisplayIter<'a, T> {
impl<'a, T: 'a> DisplayIter<'a, T> {
pub fn new(grid: &'a Grid<T>) -> DisplayIter<'a, T> {
- let offset = grid.display_offset + *grid.num_lines() - 1;
+ let offset = grid.display_offset + *grid.screen_lines() - 1;
let limit = grid.display_offset;
let col = Column(0);
let line = Line(0);
@@ -722,7 +759,7 @@ impl<'a, T: Copy + 'a> Iterator for DisplayIter<'a, T> {
#[inline]
fn next(&mut self) -> Option<Self::Item> {
// Return None if we've reached the end.
- if self.offset == self.limit && self.grid.num_cols() == self.col {
+ if self.offset == self.limit && self.grid.cols() == self.col {
return None;
}
@@ -735,7 +772,7 @@ impl<'a, T: Copy + 'a> Iterator for DisplayIter<'a, T> {
// Update line/col to point to next item.
self.col += 1;
- if self.col == self.grid.num_cols() && self.offset != self.limit {
+ if self.col == self.grid.cols() && self.offset != self.limit {
self.offset -= 1;
self.col = Column(0);
diff --git a/alacritty_terminal/src/grid/resize.rs b/alacritty_terminal/src/grid/resize.rs
index a0493fc0..079fcf19 100644
--- a/alacritty_terminal/src/grid/resize.rs
+++ b/alacritty_terminal/src/grid/resize.rs
@@ -6,7 +6,7 @@ use crate::index::{Column, Line};
use crate::term::cell::Flags;
use crate::grid::row::Row;
-use crate::grid::{Grid, GridCell};
+use crate::grid::{Dimensions, Grid, GridCell};
impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
/// Resize the grid's width and/or height.
@@ -18,8 +18,8 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
}
match self.cols.cmp(&cols) {
- Ordering::Less => self.grow_cols(cols, reflow),
- Ordering::Greater => self.shrink_cols(cols, reflow),
+ Ordering::Less => self.grow_cols(reflow, cols),
+ Ordering::Greater => self.shrink_cols(reflow, cols),
Ordering::Equal => (),
}
}
@@ -79,7 +79,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
}
/// Grow number of columns in each row, reflowing if necessary.
- fn grow_cols(&mut self, cols: Column, reflow: bool) {
+ fn grow_cols(&mut self, reflow: bool, cols: Column) {
// Check if a row needs to be wrapped.
let should_reflow = |row: &Row<T>| -> bool {
let len = Column(row.len());
@@ -116,9 +116,8 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
// Remove leading spacers when reflowing wide char to the previous line.
let mut last_len = last_row.len();
- if last_len >= 2
- && !last_row[Column(last_len - 2)].flags().contains(Flags::WIDE_CHAR)
- && last_row[Column(last_len - 1)].flags().contains(Flags::WIDE_CHAR_SPACER)
+ if last_len >= 1
+ && last_row[Column(last_len - 1)].flags().contains(Flags::LEADING_WIDE_CHAR_SPACER)
{
last_row.shrink(Column(last_len - 1));
last_len -= 1;
@@ -135,7 +134,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
let mut cells = row.front_split_off(len - 1);
let mut spacer = T::default();
- spacer.flags_mut().insert(Flags::WIDE_CHAR_SPACER);
+ spacer.flags_mut().insert(Flags::LEADING_WIDE_CHAR_SPACER);
cells.push(spacer);
cells
@@ -143,7 +142,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
row.front_split_off(len)
};
- // Reflow cells to previous row.
+ // Add removed cells to previous row and reflow content.
last_row.append(&mut cells);
let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
@@ -219,7 +218,7 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
}
/// Shrink number of columns in each row, reflowing if necessary.
- fn shrink_cols(&mut self, cols: Column, reflow: bool) {
+ fn shrink_cols(&mut self, reflow: bool, cols: Column) {
self.cols = cols;
// Remove the linewrap special case, by moving the cursor outside of the grid.
@@ -268,17 +267,14 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
wrapped.insert(0, row[cols - 1]);
let mut spacer = T::default();
- spacer.flags_mut().insert(Flags::WIDE_CHAR_SPACER);
+ spacer.flags_mut().insert(Flags::LEADING_WIDE_CHAR_SPACER);