summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2021-01-24 21:45:36 +0000
committerGitHub <noreply@github.com>2021-01-24 21:45:36 +0000
commit530de00049c2afcc562d36ccdb3e6afa2fe396a5 (patch)
tree3dabbcef3fc4a2041f9027d82243aa0d70928153
parent7291702f6b4fff10f2470f084abe0785b95659a0 (diff)
Move renderable cell transformation to alacritty
This refactors a large chunk of the alacritty_terminal API to expose all data necessary for rendering uniformly through the `renderable_content` call. This also no longer transforms the cells for rendering by a GUI but instead just reports the content from a terminal emulation perspective. The transformation into renderable cells is now done inside the alacritty crate. Since the terminal itself only ever needs to know about modified color RGB values, the configuration for colors was moved to the alacritty UI code.
-rw-r--r--CHANGELOG.md8
-rw-r--r--Cargo.lock2
-rw-r--r--alacritty/Cargo.toml2
-rw-r--r--alacritty/src/config/bell.rs (renamed from alacritty_terminal/src/config/bell.rs)4
-rw-r--r--alacritty/src/config/color.rs (renamed from alacritty_terminal/src/config/colors.rs)3
-rw-r--r--alacritty/src/config/mod.rs14
-rw-r--r--alacritty/src/config/ui_config.rs14
-rw-r--r--alacritty/src/display/bell.rs122
-rw-r--r--alacritty/src/display/color.rs167
-rw-r--r--alacritty/src/display/content.rs (renamed from alacritty_terminal/src/term/render.rs)261
-rw-r--r--alacritty/src/display/cursor.rs (renamed from alacritty/src/cursor.rs)4
-rw-r--r--alacritty/src/display/meter.rs (renamed from alacritty/src/meter.rs)0
-rw-r--r--alacritty/src/display/mod.rs (renamed from alacritty/src/display.rs)71
-rw-r--r--alacritty/src/display/wayland_theme.rs (renamed from alacritty/src/wayland_theme.rs)3
-rw-r--r--alacritty/src/display/window.rs (renamed from alacritty/src/window.rs)11
-rw-r--r--alacritty/src/event.rs249
-rw-r--r--alacritty/src/input.rs157
-rw-r--r--alacritty/src/main.rs6
-rw-r--r--alacritty/src/renderer/mod.rs9
-rw-r--r--alacritty/src/renderer/rects.rs16
-rw-r--r--alacritty/src/url.rs37
-rw-r--r--alacritty_terminal/Cargo.toml2
-rw-r--r--alacritty_terminal/src/ansi.rs10
-rw-r--r--alacritty_terminal/src/config/mod.rs28
-rw-r--r--alacritty_terminal/src/event.rs38
-rw-r--r--alacritty_terminal/src/grid/mod.rs506
-rw-r--r--alacritty_terminal/src/grid/resize.rs26
-rw-r--r--alacritty_terminal/src/grid/tests.rs28
-rw-r--r--alacritty_terminal/src/index.rs51
-rw-r--r--alacritty_terminal/src/selection.rs125
-rw-r--r--alacritty_terminal/src/term/color.rs203
-rw-r--r--alacritty_terminal/src/term/mod.rs529
-rw-r--r--alacritty_terminal/src/term/search.rs232
-rw-r--r--alacritty_terminal/src/vi_mode.rs42
-rw-r--r--alacritty_terminal/tests/ref.rs2
35 files changed, 1434 insertions, 1548 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67b8acda..d31bf64c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 0.8.0-dev
+### Packaging
+
+- Updated shell completions
+
### Added
- IME composition preview not appearing on Windows
@@ -15,9 +19,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Crash due to assertion failure on 32-bit architectures
-### Packaging
+### Removed
-- Updated shell completions
+- Config field `visual_bell`, you should use `bell` instead
## 0.7.1
diff --git a/Cargo.lock b/Cargo.lock
index 9e8f0cd7..7a3c8b5c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,7 +61,7 @@ dependencies = [
[[package]]
name = "alacritty_terminal"
-version = "0.12.1-dev"
+version = "0.13.0-dev"
dependencies = [
"alacritty_config_derive",
"base64 0.12.3",
diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml
index 73724fbe..923659d2 100644
--- a/alacritty/Cargo.toml
+++ b/alacritty/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2018"
[dependencies.alacritty_terminal]
path = "../alacritty_terminal"
-version = "0.12.1-dev"
+version = "0.13.0-dev"
default-features = false
[dependencies.alacritty_config_derive]
diff --git a/alacritty_terminal/src/config/bell.rs b/alacritty/src/config/bell.rs
index 825a7b1f..2516e2b3 100644
--- a/alacritty_terminal/src/config/bell.rs
+++ b/alacritty/src/config/bell.rs
@@ -2,8 +2,8 @@ use std::time::Duration;
use alacritty_config_derive::ConfigDeserialize;
-use crate::config::Program;
-use crate::term::color::Rgb;
+use alacritty_terminal::config::Program;
+use alacritty_terminal::term::color::Rgb;
#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)]
pub struct BellConfig {
diff --git a/alacritty_terminal/src/config/colors.rs b/alacritty/src/config/color.rs
index 88ca5057..cd5d964d 100644
--- a/alacritty_terminal/src/config/colors.rs
+++ b/alacritty/src/config/color.rs
@@ -2,8 +2,7 @@ use serde::de::Error as SerdeError;
use serde::{Deserialize, Deserializer};
use alacritty_config_derive::ConfigDeserialize;
-
-use crate::term::color::{CellRgb, Rgb};
+use alacritty_terminal::term::color::{CellRgb, Rgb};
#[derive(ConfigDeserialize, Clone, Debug, Default, PartialEq, Eq)]
pub struct Colors {
diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs
index 0673ffd5..a782f5fe 100644
--- a/alacritty/src/config/mod.rs
+++ b/alacritty/src/config/mod.rs
@@ -1,5 +1,5 @@
use std::fmt::{self, Display, Formatter};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::{env, fs, io};
use log::{error, info};
@@ -9,6 +9,8 @@ use serde_yaml::Value;
use alacritty_terminal::config::{Config as TermConfig, LOG_TARGET_CONFIG};
+pub mod bell;
+pub mod color;
pub mod debug;
pub mod font;
pub mod monitor;
@@ -123,10 +125,10 @@ pub fn load(options: &Options) -> Config {
}
/// Attempt to reload the configuration file.
-pub fn reload(config_path: &PathBuf, options: &Options) -> Result<Config> {
+pub fn reload(config_path: &Path, options: &Options) -> Result<Config> {
// Load config, propagating errors.
let config_options = options.config_options().clone();
- let mut config = load_from(&config_path, config_options)?;
+ let mut config = load_from(config_path, config_options)?;
// Override config with CLI options.
options.override_config(&mut config);
@@ -135,7 +137,7 @@ pub fn reload(config_path: &PathBuf, options: &Options) -> Result<Config> {
}
/// Load configuration file and log errors.
-fn load_from(path: &PathBuf, cli_config: Value) -> Result<Config> {
+fn load_from(path: &Path, cli_config: Value) -> Result<Config> {
match read_config(path, cli_config) {
Ok(config) => Ok(config),
Err(err) => {
@@ -146,7 +148,7 @@ fn load_from(path: &PathBuf, cli_config: Value) -> Result<Config> {
}
/// Deserialize configuration file from path.
-fn read_config(path: &PathBuf, cli_config: Value) -> Result<Config> {
+fn read_config(path: &Path, cli_config: Value) -> Result<Config> {
let mut config_paths = Vec::new();
let mut config_value = parse_config(&path, &mut config_paths, IMPORT_RECURSION_LIMIT)?;
@@ -162,7 +164,7 @@ fn read_config(path: &PathBuf, cli_config: Value) -> Result<Config> {
/// Deserialize all configuration files as generic Value.
fn parse_config(
- path: &PathBuf,
+ path: &Path,
config_paths: &mut Vec<PathBuf>,
recursion_limit: usize,
) -> Result<Value> {
diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs
index 25f9fb91..b3b3021a 100644
--- a/alacritty/src/config/ui_config.rs
+++ b/alacritty/src/config/ui_config.rs
@@ -6,7 +6,9 @@ use serde::{Deserialize, Deserializer};
use alacritty_config_derive::ConfigDeserialize;
use alacritty_terminal::config::{Percentage, LOG_TARGET_CONFIG};
+use crate::config::bell::BellConfig;
use crate::config::bindings::{self, Binding, KeyBinding, MouseBinding};
+use crate::config::color::Colors;
use crate::config::debug::Debug;
use crate::config::font::Font;
use crate::config::mouse::Mouse;
@@ -31,6 +33,15 @@ pub struct UIConfig {
/// Live config reload.
pub live_config_reload: bool,
+ /// Bell configuration.
+ pub bell: BellConfig,
+
+ /// RGB values for colors.
+ pub colors: Colors,
+
+ /// Should draw bold text with brighter colors instead of bold font.
+ pub draw_bold_text_with_bright_colors: bool,
+
/// Path where config was loaded from.
#[config(skip)]
pub config_paths: Vec<PathBuf>,
@@ -58,6 +69,9 @@ impl Default for UIConfig {
key_bindings: Default::default(),
mouse_bindings: Default::default(),
background_opacity: Default::default(),
+ bell: Default::default(),
+ colors: Default::default(),
+ draw_bold_text_with_bright_colors: Default::default(),
}
}
}
diff --git a/alacritty/src/display/bell.rs b/alacritty/src/display/bell.rs
new file mode 100644
index 00000000..1aee3ba6
--- /dev/null
+++ b/alacritty/src/display/bell.rs
@@ -0,0 +1,122 @@
+use std::time::{Duration, Instant};
+
+use crate::config::bell::{BellAnimation, BellConfig};
+
+pub struct VisualBell {
+ /// Visual bell animation.
+ animation: BellAnimation,
+
+ /// Visual bell duration.
+ duration: Duration,
+
+ /// The last time the visual bell rang, if at all.
+ start_time: Option<Instant>,
+}
+
+impl VisualBell {
+ /// Ring the visual bell, and return its intensity.
+ pub fn ring(&mut self) -> f64 {
+ let now = Instant::now();
+ self.start_time = Some(now);
+ self.intensity_at_instant(now)
+ }
+
+ /// Get the currently intensity of the visual bell. The bell's intensity
+ /// ramps down from 1.0 to 0.0 at a rate determined by the bell's duration.
+ pub fn intensity(&self) -> f64 {
+ self.intensity_at_instant(Instant::now())
+ }
+
+ /// Check whether or not the visual bell has completed "ringing".
+ pub fn completed(&mut self) -> bool {
+ match self.start_time {
+ Some(earlier) => {
+ if Instant::now().duration_since(earlier) >= self.duration {
+ self.start_time = None;
+ }
+ false
+ },
+ None => true,
+ }
+ }
+
+ /// Get the intensity of the visual bell at a particular instant. The bell's
+ /// intensity ramps down from 1.0 to 0.0 at a rate determined by the bell's
+ /// duration.
+ pub fn intensity_at_instant(&self, instant: Instant) -> f64 {
+ // If `duration` is zero, then the VisualBell is disabled; therefore,
+ // its `intensity` is zero.
+ if self.duration == Duration::from_secs(0) {
+ return 0.0;
+ }
+
+ match self.start_time {
+ // Similarly, if `start_time` is `None`, then the VisualBell has not
+ // been "rung"; therefore, its `intensity` is zero.
+ None => 0.0,
+
+ Some(earlier) => {
+ // Finally, if the `instant` at which we wish to compute the
+ // VisualBell's `intensity` occurred before the VisualBell was
+ // "rung", then its `intensity` is also zero.
+ if instant < earlier {
+ return 0.0;
+ }
+
+ let elapsed = instant.duration_since(earlier);
+ let elapsed_f =
+ elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9f64;
+ let duration_f = self.duration.as_secs() as f64
+ + f64::from(self.duration.subsec_nanos()) / 1e9f64;
+
+ // Otherwise, we compute a value `time` from 0.0 to 1.0
+ // inclusive that represents the ratio of `elapsed` time to the
+ // `duration` of the VisualBell.
+ let time = (elapsed_f / duration_f).min(1.0);
+
+ // We use this to compute the inverse `intensity` of the
+ // VisualBell. When `time` is 0.0, `inverse_intensity` is 0.0,
+ // and when `time` is 1.0, `inverse_intensity` is 1.0.
+ let inverse_intensity = match self.animation {
+ BellAnimation::Ease | BellAnimation::EaseOut => {
+ cubic_bezier(0.25, 0.1, 0.25, 1.0, time)
+ },
+ BellAnimation::EaseOutSine => cubic_bezier(0.39, 0.575, 0.565, 1.0, time),
+ BellAnimation::EaseOutQuad => cubic_bezier(0.25, 0.46, 0.45, 0.94, time),
+ BellAnimation::EaseOutCubic => cubic_bezier(0.215, 0.61, 0.355, 1.0, time),
+ BellAnimation::EaseOutQuart => cubic_bezier(0.165, 0.84, 0.44, 1.0, time),
+ BellAnimation::EaseOutQuint => cubic_bezier(0.23, 1.0, 0.32, 1.0, time),
+ BellAnimation::EaseOutExpo => cubic_bezier(0.19, 1.0, 0.22, 1.0, time),
+ BellAnimation::EaseOutCirc => cubic_bezier(0.075, 0.82, 0.165, 1.0, time),
+ BellAnimation::Linear => time,
+ };
+
+ // Since we want the `intensity` of the VisualBell to decay over
+ // `time`, we subtract the `inverse_intensity` from 1.0.
+ 1.0 - inverse_intensity
+ },
+ }
+ }
+
+ pub fn update_config(&mut self, bell_config: &BellConfig) {
+ self.animation = bell_config.animation;
+ self.duration = bell_config.duration();
+ }
+}
+
+impl From<&BellConfig> for VisualBell {
+ fn from(bell_config: &BellConfig) -> VisualBell {
+ VisualBell {
+ animation: bell_config.animation,
+ duration: bell_config.duration(),
+ start_time: None,
+ }
+ }
+}
+
+fn cubic_bezier(p0: f64, p1: f64, p2: f64, p3: f64, x: f64) -> f64 {
+ (1.0 - x).powi(3) * p0
+ + 3.0 * (1.0 - x).powi(2) * x * p1
+ + 3.0 * (1.0 - x) * x.powi(2) * p2
+ + x.powi(3) * p3
+}
diff --git a/alacritty/src/display/color.rs b/alacritty/src/display/color.rs
new file mode 100644
index 00000000..6e0de048
--- /dev/null
+++ b/alacritty/src/display/color.rs
@@ -0,0 +1,167 @@
+use std::ops::{Index, IndexMut};
+
+use log::trace;
+
+use alacritty_terminal::ansi::NamedColor;
+use alacritty_terminal::term::color::{Rgb, COUNT};
+
+use crate::config::color::Colors;
+
+/// Factor for automatic computation of dim colors.
+pub const DIM_FACTOR: f32 = 0.66;
+
+#[derive(Copy, Clone)]
+pub struct List([Rgb; COUNT]);
+
+impl<'a> From<&'a Colors> for List {
+ fn from(colors: &Colors) -> List {
+ // Type inference fails without this annotation.
+ let mut list = List([Rgb::default(); COUNT]);
+
+ list.fill_named(colors);
+ list.fill_cube(colors);
+ list.fill_gray_ramp(colors);
+
+ list
+ }
+}
+
+impl List {
+ pub fn fill_named(&mut self, colors: &Colors) {
+ // Normals.
+ self[NamedColor::Black] = colors.normal.black;
+ self[NamedColor::Red] = colors.normal.red;
+ self[NamedColor::Green] = colors.normal.green;
+ self[NamedColor::Yellow] = colors.normal.yellow;
+ self[NamedColor::Blue] = colors.normal.blue;
+ self[NamedColor::Magenta] = colors.normal.magenta;
+ self[NamedColor::Cyan] = colors.normal.cyan;
+ self[NamedColor::White] = colors.normal.white;
+
+ // Brights.
+ self[NamedColor::BrightBlack] = colors.bright.black;
+ self[NamedColor::BrightRed] = colors.bright.red;
+ self[NamedColor::BrightGreen] = colors.bright.green;
+ self[NamedColor::BrightYellow] = colors.bright.yellow;
+ self[NamedColor::BrightBlue] = colors.bright.blue;
+ self[NamedColor::BrightMagenta] = colors.bright.magenta;
+ self[NamedColor::BrightCyan] = colors.bright.cyan;
+ self[NamedColor::BrightWhite] = colors.bright.white;
+ self[NamedColor::BrightForeground] =
+ colors.primary.bright_foreground.unwrap_or(colors.primary.foreground);
+
+ // Foreground and background.
+ self[NamedColor::Foreground] = colors.primary.foreground;
+ self[NamedColor::Background] = colors.primary.background;
+
+ // Dims.
+ self[NamedColor::DimForeground] =
+ colors.primary.dim_foreground.unwrap_or(colors.primary.foreground * DIM_FACTOR);
+ match colors.dim {
+ Some(ref dim) => {
+ trace!("Using config-provided dim colors");
+ self[NamedColor::DimBlack] = dim.black;
+ self[NamedColor::DimRed] = dim.red;
+ self[NamedColor::DimGreen] = dim.green;
+ self[NamedColor::DimYellow] = dim.yellow;
+ self[NamedColor::DimBlue] = dim.blue;
+ self[NamedColor::DimMagenta] = dim.magenta;
+ self[NamedColor::DimCyan] = dim.cyan;
+ self[NamedColor::DimWhite] = dim.white;
+ },
+ None => {
+ trace!("Deriving dim colors from normal colors");
+ self[NamedColor::DimBlack] = colors.normal.black * DIM_FACTOR;
+ self[NamedColor::DimRed] = colors.normal.red * DIM_FACTOR;
+ self[NamedColor::DimGreen] = colors.normal.green * DIM_FACTOR;
+ self[NamedColor::DimYellow] = colors.normal.yellow * DIM_FACTOR;
+ self[NamedColor::DimBlue] = colors.normal.blue * DIM_FACTOR;
+ self[NamedColor::DimMagenta] = colors.normal.magenta * DIM_FACTOR;
+ self[NamedColor::DimCyan] = colors.normal.cyan * DIM_FACTOR;
+ self[NamedColor::DimWhite] = colors.normal.white * DIM_FACTOR;
+ },
+ }
+ }
+
+ pub fn fill_cube(&mut self, colors: &Colors) {
+ let mut index: usize = 16;
+ // Build colors.
+ for r in 0..6 {
+ for g in 0..6 {
+ for b in 0..6 {
+ // Override colors 16..232 with the config (if present).
+ if let Some(indexed_color) =
+ colors.indexed_colors.iter().find(|ic| ic.index() == index as u8)
+ {
+ self[index] = indexed_color.color;
+ } else {
+ self[index] = Rgb {
+ r: if r == 0 { 0 } else { r * 40 + 55 },
+ b: if b == 0 { 0 } else { b * 40 + 55 },
+ g: if g == 0 { 0 } else { g * 40 + 55 },
+ };
+ }
+ index += 1;
+ }
+ }
+ }
+
+ debug_assert!(index == 232);
+ }
+
+ pub fn fill_gray_ramp(&mut self, colors: &Colors) {
+ let mut index: usize = 232;
+
+ for i in 0..24 {
+ // Index of the color is number of named colors + number of cube colors + i.
+ let color_index = 16 + 216 + i;
+
+ // Override colors 232..256 with the config (if present).
+ if let Some(indexed_color) =
+ colors.indexed_colors.iter().find(|ic| ic.index() == color_index)
+ {
+ self[index] = indexed_color.color;
+ index += 1;
+ continue;
+ }
+
+ let value = i * 10 + 8;
+ self[index] = Rgb { r: value, g: value, b: value };
+ index += 1;
+ }
+
+ debug_assert!(index == 256);
+ }
+}
+
+impl Index<usize> for List {
+ type Output = Rgb;
+
+ #[inline]
+ fn index(&self, idx: usize) -> &Self::Output {
+ &self.0[idx]
+ }
+}
+
+impl IndexMut<usize> for List {
+ #[inline]
+ fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
+ &mut self.0[idx]
+ }
+}
+
+impl Index<NamedColor> for List {
+ type Output = Rgb;
+
+ #[inline]
+ fn index(&self, idx: NamedColor) -> &Self::Output {
+ &self.0[idx as usize]
+ }
+}
+
+impl IndexMut<NamedColor> for List {
+ #[inline]
+ fn index_mut(&mut self, idx: NamedColor) -> &mut Self::Output {
+ &mut self.0[idx as usize]
+ }
+}
diff --git a/alacritty_terminal/src/term/render.rs b/alacritty/src/display/content.rs
index fbb5a732..81c2977f 100644
--- a/alacritty_terminal/src/term/render.rs
+++ b/alacritty/src/display/content.rs
@@ -1,18 +1,21 @@
use std::cmp::max;
-use std::iter;
-use std::iter::Peekable;
use std::mem;
use std::ops::RangeInclusive;
-use crate::ansi::{Color, CursorShape, NamedColor};
-use crate::config::Config;
-use crate::grid::{Dimensions, DisplayIter, Indexed};
-use crate::index::{Column, Direction, Line, Point};
-use crate::selection::SelectionRange;
-use crate::term::cell::{Cell, Flags};
-use crate::term::color::{self, CellRgb, Rgb, DIM_FACTOR};
-use crate::term::search::RegexIter;
-use crate::term::{Term, TermMode};
+use alacritty_terminal::ansi::{Color, CursorShape, NamedColor};
+use alacritty_terminal::config::Config;
+use alacritty_terminal::event::EventListener;
+use alacritty_terminal::grid::{Dimensions, Indexed};
+use alacritty_terminal::index::{Column, Direction, Line, Point};
+use alacritty_terminal::term::cell::{Cell, Flags};
+use alacritty_terminal::term::color::{CellRgb, Rgb};
+use alacritty_terminal::term::search::{RegexIter, RegexSearch};
+use alacritty_terminal::term::{
+ RenderableContent as TerminalContent, RenderableCursor as TerminalCursor, Term, TermMode,
+};
+
+use crate::config::ui_config::UIConfig;
+use crate::display::color::{List, DIM_FACTOR};
/// Minimum contrast between a fixed cursor color and the cell's background.
pub const MIN_CURSOR_CONTRAST: f64 = 1.5;
@@ -23,58 +26,40 @@ const MAX_SEARCH_LINES: usize = 100;
/// Renderable terminal content.
///
/// This provides the terminal cursor and an iterator over all non-empty cells.
-pub struct RenderableContent<'a, T, C> {
- term: &'a Term<T>,
- config: &'a Config<C>,
- display_iter: DisplayIter<'a, Cell>,
- selection: Option<SelectionRange<Line>>,
- search: RenderableSearch<'a>,
+pub struct RenderableContent<'a> {
+ terminal_content: TerminalContent<'a>,
+ terminal_cursor: TerminalCursor,
cursor: Option<RenderableCursor>,
- cursor_shape: CursorShape,
- cursor_point: Point,
+ search: RenderableSearch,
+ config: &'a Config<UIConfig>,
+ colors: &'a List,
}
-impl<'a, T, C> RenderableContent<'a, T, C> {
- pub fn new(term: &'a Term<T>, config: &'a Config<C>, show_cursor: bool) -> Self {
- // Cursor position.
- let vi_mode = term.mode.contains(TermMode::VI);
- let mut cursor_point = if vi_mode {
- term.vi_mode_cursor.point
- } else {
- let mut point = term.grid.cursor.point;
- point.line += term.grid.display_offset();
- point
- };
-
- // Cursor shape.
- let cursor_shape = if !show_cursor
- || (!term.mode.contains(TermMode::SHOW_CURSOR) && !vi_mode)
- || cursor_point.line >= term.screen_lines()
- {
- cursor_point.line = Line(0);
- CursorShape::Hidden
+impl<'a> RenderableContent<'a> {
+ pub fn new<T: EventListener>(
+ term: &'a Term<T>,
+ dfas: Option<&RegexSearch>,
+ config: &'a Config<UIConfig>,
+ colors: &'a List,
+ show_cursor: bool,
+ ) -> Self {
+ let search = dfas.map(|dfas| RenderableSearch::new(&term, dfas)).unwrap_or_default();
+ let terminal_content = term.renderable_content();
+
+ // Copy the cursor and override its shape if necessary.
+ let mut terminal_cursor = terminal_content.cursor;
+ if !show_cursor {
+ terminal_cursor.shape = CursorShape::Hidden;
} else if !term.is_focused && config.cursor.unfocused_hollow {
- CursorShape::HollowBlock
- } else {
- let cursor_style = term.cursor_style.unwrap_or(term.default_cursor_style);
+ terminal_cursor.shape = CursorShape::HollowBlock;
+ }
- if vi_mode {
- term.vi_mode_cursor_style.unwrap_or(cursor_style).shape
- } else {
- cursor_style.shape
- }
- };
+ Self { cursor: None, terminal_content, terminal_cursor, search, config, colors }
+ }
- Self {
- display_iter: term.grid.display_iter(),
- selection: term.visible_selection(),
- search: RenderableSearch::new(term),
- cursor: None,
- cursor_shape,
- cursor_point,
- config,
- term,
- }
+ /// Viewport offset.
+ pub fn display_offset(&self) -> usize {
+ self.terminal_content.display_offset
}
/// Get the terminal cursor.
@@ -85,33 +70,35 @@ impl<'a, T, C> RenderableContent<'a, T, C> {
self.cursor
}
+ /// Get the RGB value for a color index.
+ pub fn color(&self, color: usize) -> Rgb {
+ self.terminal_content.colors[color].unwrap_or(self.colors[color])
+ }
+
/// Assemble the information required to render the terminal cursor.
///
/// This will return `None` when there is no cursor visible.
fn renderable_cursor(&mut self, cell: &RenderableCell) -> Option<RenderableCursor> {
- if self.cursor_shape == CursorShape::Hidden {
+ if self.terminal_cursor.shape == CursorShape::Hidden {
return None;
}
// Expand across wide cell when inside wide char or spacer.
let is_wide = if cell.flags.contains(Flags::WIDE_CHAR_SPACER) {
- self.cursor_point.col -= 1;
+ self.terminal_cursor.point.column -= 1;
true
} else {
cell.flags.contains(Flags::WIDE_CHAR)
};
// Cursor colors.
- let color = if self.term.mode.contains(TermMode::VI) {
- self.config.colors.vi_mode_cursor
- } else {
- self.config.colors.cursor
- };
- let mut cursor_color = if self.term.color_modified[NamedColor::Cursor as usize] {
- CellRgb::Rgb(self.term.colors[NamedColor::Cursor])
+ let color = if self.terminal_content.mode.contains(TermMode::VI) {
+ self.config.ui_config.colors.vi_mode_cursor
} else {
- color.background
+ self.config.ui_config.colors.cursor
};
+ let mut cursor_color =
+ self.terminal_content.colors[NamedColor::Cursor].map_or(color.background, CellRgb::Rgb);
let mut text_color = color.foreground;
// Invert the cursor if it has a fixed background close to the cell's background.
@@ -128,8 +115,8 @@ impl<'a, T, C> RenderableContent<'a, T, C> {
let cursor_color = cursor_color.color(cell.fg, cell.bg);
Some(RenderableCursor {
- point: self.cursor_point,
- shape: self.cursor_shape,
+ point: self.terminal_cursor.point,
+ shape: self.terminal_cursor.shape,
cursor_color,
text_color,
is_wide,
@@ -137,7 +124,7 @@ impl<'a, T, C> RenderableContent<'a, T, C> {
}
}
-impl<'a, T, C> Iterator for RenderableContent<'a, T, C> {
+impl<'a> Iterator for RenderableContent<'a> {
type Item = RenderableCell;
/// Gets the next renderable cell.
@@ -147,11 +134,10 @@ impl<'a, T, C> Iterator for RenderableContent<'a, T, C> {
#[inline]
fn next(&mut