Switch to VTE's built-in ansi feature

Co-authored-by: Christian Duerr <contact@christianduerr.com>
This commit is contained in:
Anhad Singh 2023-05-24 06:35:58 +10:00 committed by GitHub
parent f0379f2da7
commit cb7ad5b7e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 211 additions and 2041 deletions

14
Cargo.lock generated
View File

@ -1487,18 +1487,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.57"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.27"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
@ -1945,10 +1945,12 @@ dependencies = [
[[package]]
name = "vte"
version = "0.10.1"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
dependencies = [
"log",
"serde",
"utf8parse",
"vte_generate_state_changes",
]

View File

@ -23,7 +23,7 @@ pub struct BellConfig {
impl Default for BellConfig {
fn default() -> Self {
Self {
color: Rgb { r: 255, g: 255, b: 255 },
color: Rgb::new(255, 255, 255),
animation: Default::default(),
command: Default::default(),
duration: Default::default(),
@ -39,7 +39,7 @@ impl BellConfig {
/// `VisualBellAnimations` are modeled after a subset of CSS transitions and Robert
/// Penner's Easing Functions.
#[derive(ConfigDeserialize, Clone, Copy, Debug, PartialEq, Eq)]
#[derive(ConfigDeserialize, Default, Clone, Copy, Debug, PartialEq, Eq)]
pub enum BellAnimation {
// CSS animation.
Ease,
@ -56,15 +56,10 @@ pub enum BellAnimation {
// Penner animation.
EaseOutQuint,
// Penner animation.
#[default]
EaseOutExpo,
// Penner animation.
EaseOutCirc,
// Penner animation.
Linear,
}
impl Default for BellAnimation {
fn default() -> Self {
BellAnimation::EaseOutExpo
}
}

View File

@ -52,8 +52,8 @@ pub struct HintStartColors {
impl Default for HintStartColors {
fn default() -> Self {
Self {
foreground: CellRgb::Rgb(Rgb { r: 0x1d, g: 0x1f, b: 0x21 }),
background: CellRgb::Rgb(Rgb { r: 0xe9, g: 0xff, b: 0x5e }),
foreground: CellRgb::Rgb(Rgb::new(0x1d, 0x1f, 0x21)),
background: CellRgb::Rgb(Rgb::new(0xe9, 0xff, 0x5e)),
}
}
}
@ -67,8 +67,8 @@ pub struct HintEndColors {
impl Default for HintEndColors {
fn default() -> Self {
Self {
foreground: CellRgb::Rgb(Rgb { r: 0xe9, g: 0xff, b: 0x5e }),
background: CellRgb::Rgb(Rgb { r: 0x1d, g: 0x1f, b: 0x21 }),
foreground: CellRgb::Rgb(Rgb::new(0xe9, 0xff, 0x5e)),
background: CellRgb::Rgb(Rgb::new(0x1d, 0x1f, 0x21)),
}
}
}
@ -139,8 +139,8 @@ pub struct FocusedMatchColors {
impl Default for FocusedMatchColors {
fn default() -> Self {
Self {
background: CellRgb::Rgb(Rgb { r: 0x00, g: 0x00, b: 0x00 }),
foreground: CellRgb::Rgb(Rgb { r: 0xff, g: 0xff, b: 0xff }),
background: CellRgb::Rgb(Rgb::new(0x00, 0x00, 0x00)),
foreground: CellRgb::Rgb(Rgb::new(0xff, 0xff, 0xff)),
}
}
}
@ -154,8 +154,8 @@ pub struct MatchColors {
impl Default for MatchColors {
fn default() -> Self {
Self {
background: CellRgb::Rgb(Rgb { r: 0xff, g: 0xff, b: 0xff }),
foreground: CellRgb::Rgb(Rgb { r: 0x00, g: 0x00, b: 0x00 }),
background: CellRgb::Rgb(Rgb::new(0xff, 0xff, 0xff)),
foreground: CellRgb::Rgb(Rgb::new(0x00, 0x00, 0x00)),
}
}
}
@ -177,8 +177,8 @@ pub struct PrimaryColors {
impl Default for PrimaryColors {
fn default() -> Self {
PrimaryColors {
background: Rgb { r: 0x1d, g: 0x1f, b: 0x21 },
foreground: Rgb { r: 0xc5, g: 0xc8, b: 0xc6 },
background: Rgb::new(0x1d, 0x1f, 0x21),
foreground: Rgb::new(0xc5, 0xc8, 0xc6),
bright_foreground: Default::default(),
dim_foreground: Default::default(),
}
@ -200,14 +200,14 @@ pub struct NormalColors {
impl Default for NormalColors {
fn default() -> Self {
NormalColors {
black: Rgb { r: 0x1d, g: 0x1f, b: 0x21 },
red: Rgb { r: 0xcc, g: 0x66, b: 0x66 },
green: Rgb { r: 0xb5, g: 0xbd, b: 0x68 },
yellow: Rgb { r: 0xf0, g: 0xc6, b: 0x74 },
blue: Rgb { r: 0x81, g: 0xa2, b: 0xbe },
magenta: Rgb { r: 0xb2, g: 0x94, b: 0xbb },
cyan: Rgb { r: 0x8a, g: 0xbe, b: 0xb7 },
white: Rgb { r: 0xc5, g: 0xc8, b: 0xc6 },
black: Rgb::new(0x1d, 0x1f, 0x21),
red: Rgb::new(0xcc, 0x66, 0x66),
green: Rgb::new(0xb5, 0xbd, 0x68),
yellow: Rgb::new(0xf0, 0xc6, 0x74),
blue: Rgb::new(0x81, 0xa2, 0xbe),
magenta: Rgb::new(0xb2, 0x94, 0xbb),
cyan: Rgb::new(0x8a, 0xbe, 0xb7),
white: Rgb::new(0xc5, 0xc8, 0xc6),
}
}
}
@ -227,14 +227,14 @@ pub struct BrightColors {
impl Default for BrightColors {
fn default() -> Self {
BrightColors {
black: Rgb { r: 0x66, g: 0x66, b: 0x66 },
red: Rgb { r: 0xd5, g: 0x4e, b: 0x53 },
green: Rgb { r: 0xb9, g: 0xca, b: 0x4a },
yellow: Rgb { r: 0xe7, g: 0xc5, b: 0x47 },
blue: Rgb { r: 0x7a, g: 0xa6, b: 0xda },
magenta: Rgb { r: 0xc3, g: 0x97, b: 0xd8 },
cyan: Rgb { r: 0x70, g: 0xc0, b: 0xb1 },
white: Rgb { r: 0xea, g: 0xea, b: 0xea },
black: Rgb::new(0x66, 0x66, 0x66),
red: Rgb::new(0xd5, 0x4e, 0x53),
green: Rgb::new(0xb9, 0xca, 0x4a),
yellow: Rgb::new(0xe7, 0xc5, 0x47),
blue: Rgb::new(0x7a, 0xa6, 0xda),
magenta: Rgb::new(0xc3, 0x97, 0xd8),
cyan: Rgb::new(0x70, 0xc0, 0xb1),
white: Rgb::new(0xea, 0xea, 0xea),
}
}
}
@ -254,14 +254,14 @@ pub struct DimColors {
impl Default for DimColors {
fn default() -> Self {
DimColors {
black: Rgb { r: 0x13, g: 0x14, b: 0x15 },
red: Rgb { r: 0x86, g: 0x43, b: 0x43 },
green: Rgb { r: 0x77, g: 0x7c, b: 0x44 },
yellow: Rgb { r: 0x9e, g: 0x82, b: 0x4c },
blue: Rgb { r: 0x55, g: 0x6a, b: 0x7d },
magenta: Rgb { r: 0x75, g: 0x61, b: 0x7b },
cyan: Rgb { r: 0x5b, g: 0x7d, b: 0x78 },
white: Rgb { r: 0x82, g: 0x84, b: 0x82 },
black: Rgb::new(0x13, 0x14, 0x15),
red: Rgb::new(0x86, 0x43, 0x43),
green: Rgb::new(0x77, 0x7c, 0x44),
yellow: Rgb::new(0x9e, 0x82, 0x4c),
blue: Rgb::new(0x55, 0x6a, 0x7d),
magenta: Rgb::new(0x75, 0x61, 0x7b),
cyan: Rgb::new(0x5b, 0x7d, 0x78),
white: Rgb::new(0x82, 0x84, 0x82),
}
}
}

View File

@ -154,8 +154,9 @@ impl Default for Identity {
}
}
#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[derive(ConfigDeserialize, Default, Debug, Copy, Clone, PartialEq, Eq)]
pub enum StartupMode {
#[default]
Windowed,
Maximized,
Fullscreen,
@ -163,14 +164,9 @@ pub enum StartupMode {
SimpleFullscreen,
}
impl Default for StartupMode {
fn default() -> StartupMode {
StartupMode::Windowed
}
}
#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[derive(ConfigDeserialize, Default, Debug, Copy, Clone, PartialEq, Eq)]
pub enum Decorations {
#[default]
Full,
#[cfg(target_os = "macos")]
Transparent,
@ -179,12 +175,6 @@ pub enum Decorations {
None,
}
impl Default for Decorations {
fn default() -> Decorations {
Decorations::Full
}
}
/// Window Dimensions.
///
/// Newtype to avoid passing values incorrectly.

View File

@ -95,11 +95,11 @@ impl List {
{
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 },
};
self[index] = Rgb::new(
if r == 0 { 0 } else { r * 40 + 55 },
if b == 0 { 0 } else { b * 40 + 55 },
if g == 0 { 0 } else { g * 40 + 55 },
);
}
index += 1;
}
@ -126,7 +126,7 @@ impl List {
}
let value = i * 10 + 8;
self[index] = Rgb { r: value, g: value, b: value };
self[index] = Rgb::new(value, value, value);
index += 1;
}

View File

@ -121,7 +121,7 @@ impl<'a> RenderableContent<'a> {
let insufficient_contrast = (!matches!(cursor_color, CellRgb::Rgb(_))
|| !matches!(text_color, CellRgb::Rgb(_)))
&& cell.fg.contrast(cell.bg) < MIN_CURSOR_CONTRAST;
&& cell.fg.contrast(*cell.bg) < MIN_CURSOR_CONTRAST;
// Convert from cell colors to RGB.
let mut text_color = text_color.color(cell.fg, cell.bg);
@ -307,8 +307,11 @@ impl RenderableCell {
let config = &content.config;
match fg {
Color::Spec(rgb) => match flags & Flags::DIM {
Flags::DIM => rgb * DIM_FACTOR,
_ => rgb,
Flags::DIM => {
let rgb: Rgb = rgb.into();
rgb * DIM_FACTOR
},
_ => rgb.into(),
},
Color::Named(ansi) => {
match (config.draw_bold_text_with_bright_colors, flags & Flags::DIM_BOLD) {
@ -350,7 +353,7 @@ impl RenderableCell {
#[inline]
fn compute_bg_rgb(content: &mut RenderableContent<'_>, bg: Color) -> Rgb {
match bg {
Color::Spec(rgb) => rgb,
Color::Spec(rgb) => rgb.into(),
Color::Named(ansi) => content.color(ansi as usize),
Color::Indexed(idx) => content.color(idx as usize),
}

View File

@ -647,25 +647,25 @@ mod tests {
#[test]
fn collect_unique_hyperlinks() {
let mut term = mock_term("000\r\n111");
term.goto(Line(0), Column(0));
term.goto(0, 0);
let hyperlink_foo = Hyperlink::new(Some("1"), String::from("foo"));
let hyperlink_bar = Hyperlink::new(Some("2"), String::from("bar"));
// Create 2 hyperlinks on the first line.
term.set_hyperlink(Some(hyperlink_foo.clone()));
term.set_hyperlink(Some(hyperlink_foo.clone().into()));
term.input('b');
term.input('a');
term.set_hyperlink(Some(hyperlink_bar.clone()));
term.set_hyperlink(Some(hyperlink_bar.clone().into()));
term.input('r');
term.set_hyperlink(Some(hyperlink_foo.clone()));
term.goto(Line(1), Column(0));
term.set_hyperlink(Some(hyperlink_foo.clone().into()));
term.goto(1, 0);
// Ditto for the second line.
term.set_hyperlink(Some(hyperlink_foo));
term.set_hyperlink(Some(hyperlink_foo.into()));
term.input('b');
term.input('a');
term.set_hyperlink(Some(hyperlink_bar));
term.set_hyperlink(Some(hyperlink_bar.into()));
term.input('r');
term.set_hyperlink(None);

View File

@ -73,7 +73,7 @@ const BACKWARD_SEARCH_LABEL: &str = "Backward Search: ";
const SHORTENER: char = '…';
/// Color which is used to highlight damaged rects when debugging.
const DAMAGE_RECT_COLOR: Rgb = Rgb { r: 255, g: 0, b: 255 };
const DAMAGE_RECT_COLOR: Rgb = Rgb::new(255, 0, 255);
#[derive(Debug)]
pub enum Error {

View File

@ -366,7 +366,7 @@ impl RectRenderer {
let y = -rect.y / half_height + 1.0;
let width = rect.width / half_width;
let height = rect.height / half_height;
let Rgb { r, g, b } = rect.color;
let (r, g, b) = rect.color.as_tuple();
let a = (rect.alpha * 255.) as u8;
// Make quad vertices.

View File

@ -30,7 +30,7 @@ regex-automata = "0.1.9"
serde = { version = "1", features = ["derive", "rc"] }
serde_yaml = "0.8"
unicode-width = "0.1"
vte = { version = "0.10.0", default-features = false }
vte = { version = "0.11.1", default-features = false, features = ["ansi", "serde"] }
[target.'cfg(unix)'.dependencies]
nix = { version = "0.26.2", default-features = false, features = ["term"] }

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
mod scrolling;
use crate::ansi::{CursorShape, CursorStyle};
use crate::ansi::{CursorShapeShim, CursorStyle};
pub use crate::config::scrolling::{Scrolling, MAX_SCROLLBACK_LINES};
@ -129,10 +129,10 @@ impl Cursor {
#[derive(SerdeReplace, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[serde(untagged)]
pub enum ConfigCursorStyle {
Shape(CursorShape),
Shape(CursorShapeShim),
WithBlinking {
#[serde(default)]
shape: CursorShape,
shape: CursorShapeShim,
#[serde(default)]
blinking: CursorBlinking,
},
@ -140,7 +140,7 @@ pub enum ConfigCursorStyle {
impl Default for ConfigCursorStyle {
fn default() -> Self {
Self::Shape(CursorShape::default())
Self::Shape(CursorShapeShim::default())
}
}
@ -157,28 +157,23 @@ impl ConfigCursorStyle {
impl From<ConfigCursorStyle> for CursorStyle {
fn from(config_style: ConfigCursorStyle) -> Self {
match config_style {
ConfigCursorStyle::Shape(shape) => Self { shape, blinking: false },
ConfigCursorStyle::Shape(shape) => Self { shape: shape.into(), blinking: false },
ConfigCursorStyle::WithBlinking { shape, blinking } => {
Self { shape, blinking: blinking.into() }
Self { shape: shape.into(), blinking: blinking.into() }
},
}
}
}
#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[derive(ConfigDeserialize, Default, Debug, Copy, Clone, PartialEq, Eq)]
pub enum CursorBlinking {
Never,
#[default]
Off,
On,
Always,
}
impl Default for CursorBlinking {
fn default() -> Self {
CursorBlinking::Off
}
}
impl CursorBlinking {
fn blinking_override(&self) -> Option<bool> {
match self {

View File

@ -333,8 +333,9 @@ where
'event_loop: loop {
// Wakeup the event loop when a synchronized update timeout was reached.
let sync_timeout = state.parser.sync_timeout();
let timeout = sync_timeout.map(|st| st.saturating_duration_since(Instant::now()));
let handler = state.parser.sync_timeout();
let timeout =
handler.sync_timeout().map(|st| st.saturating_duration_since(Instant::now()));
if let Err(err) = self.poll.poll(&mut events, timeout) {
match err.kind() {

View File

@ -3,6 +3,7 @@ use std::sync::Arc;
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use vte::ansi::Hyperlink as VteHyperlink;
use crate::ansi::{Color, NamedColor};
use crate::grid::{self, GridCell};
@ -57,6 +58,18 @@ impl Hyperlink {
}
}
impl From<VteHyperlink> for Hyperlink {
fn from(value: VteHyperlink) -> Self {
Self::new(value.id, value.uri)
}
}
impl From<Hyperlink> for VteHyperlink {
fn from(val: Hyperlink) -> Self {
VteHyperlink { id: Some(val.id().to_owned()), uri: val.uri().to_owned() }
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
struct HyperlinkInner {
/// Identifier for the given hyperlink.

View File

@ -1,89 +1,62 @@
use std::fmt::{self, Display, Formatter};
use std::ops::{Add, Index, IndexMut, Mul};
use std::ops::{Add, Deref, Index, IndexMut, Mul};
use std::str::FromStr;
use log::trace;
use serde::de::{Error as _, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use serde_yaml::Value;
use alacritty_config_derive::SerdeReplace;
use vte::ansi::Rgb as VteRgb;
use crate::ansi::NamedColor;
/// Number of terminal colors.
pub const COUNT: usize = 269;
#[derive(SerdeReplace, Debug, Eq, PartialEq, Copy, Clone, Default, Serialize)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
pub struct Rgb(VteRgb);
impl Rgb {
/// Implementation of W3C's luminance
/// [algorithm](https://www.w3.org/TR/WCAG20/#relativeluminancedef)
fn luminance(self) -> f64 {
let channel_luminance = |channel| {
let channel = channel as f64 / 255.;
if channel <= 0.03928 {
channel / 12.92
} else {
f64::powf((channel + 0.055) / 1.055, 2.4)
}
};
let r_luminance = channel_luminance(self.r);
let g_luminance = channel_luminance(self.g);
let b_luminance = channel_luminance(self.b);
0.2126 * r_luminance + 0.7152 * g_luminance + 0.0722 * b_luminance
#[inline]
pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self(VteRgb { r, g, b })
}
/// Implementation of [W3C's contrast algorithm].
///
/// [W3C's contrast algorithm]: https://www.w3.org/TR/WCAG20/#contrast-ratiodef
pub fn contrast(self, other: Rgb) -> f64 {
let self_luminance = self.luminance();
let other_luminance = other.luminance();
let (darker, lighter) = if self_luminance > other_luminance {
(other_luminance, self_luminance)
} else {
(self_luminance, other_luminance)
};
(lighter + 0.05) / (darker + 0.05)
#[inline]
pub fn as_tuple(self) -> (u8, u8, u8) {
(self.0.r, self.0.g, self.0.b)
}
}
impl From<VteRgb> for Rgb {
fn from(value: VteRgb) -> Self {
Self(value)
}
}
impl Deref for Rgb {
type Target = VteRgb;
fn deref(&self) -> &Self::Target {
&self.0
}
}
// A multiply function for Rgb, as the default dim is just *2/3.
impl Mul<f32> for Rgb {
type Output = Rgb;
fn mul(self, rhs: f32) -> Rgb {
let result = Rgb {
r: (f32::from(self.r) * rhs).clamp(0.0, 255.0) as u8,
g: (f32::from(self.g) * rhs).clamp(0.0, 255.0) as u8,
b: (f32::from(self.b) * rhs).clamp(0.0, 255.0) as u8,
};
trace!("Scaling RGB by {} from {:?} to {:?}", rhs, self, result);
result
fn mul(self, rhs: f32) -> Self::Output {
Rgb(self.0 * rhs)
}
}
impl Add<Rgb> for Rgb {
type Output = Rgb;
fn add(self, rhs: Rgb) -> Rgb {
Rgb {
r: self.r.saturating_add(rhs.r),
g: self.g.saturating_add(rhs.g),
b: self.b.saturating_add(rhs.b),
}
fn add(self, rhs: Rgb) -> Self::Output {
Rgb(self.0 + rhs.0)
}
}
@ -130,7 +103,7 @@ impl<'de> Deserialize<'de> for Rgb {
// Attempt to deserialize from struct form.
if let Ok(RgbDerivedDeser { r, g, b }) = RgbDerivedDeser::deserialize(value.clone()) {
return Ok(Rgb { r, g, b });
return Ok(Rgb::new(r, g, b));
}
// Deserialize from hex notation (either 0xff00ff or #ff00ff).
@ -163,7 +136,7 @@ impl FromStr for Rgb {
let g = (color & 0xff) as u8;
color >>= 8;
let r = color as u8;
Ok(Rgb { r, g, b })
Ok(Rgb::new(r, g, b))
},
Err(_) => Err(()),
}
@ -283,26 +256,3 @@ impl IndexMut<NamedColor> for Colors {
&mut self.0[index as usize]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn contrast() {
let rgb1 = Rgb { r: 0xff, g: 0xff, b: 0xff };
let rgb2 = Rgb { r: 0x00, g: 0x00, b: 0x00 };
assert!((rgb1.contrast(rgb2) - 21.).abs() < f64::EPSILON);
let rgb1 = Rgb { r: 0xff, g: 0xff, b: 0xff };
assert!((rgb1.contrast(rgb1) - 1.).abs() < f64::EPSILON);
let rgb1 = Rgb { r: 0xff, g: 0x00, b: 0xff };
let rgb2 = Rgb { r: 0x00, g: 0xff, b: 0x00 };
assert!((rgb1.contrast(rgb2) - 2.285_543_608_124_253_3).abs() < f64::EPSILON);
let rgb1 = Rgb { r: 0x12, g: 0x34, b: 0x56 };
let rgb2 = Rgb { r: 0xfe, g: 0xdc, b: 0xba };
assert!((rgb1.contrast(rgb2) - 9.786_558_997_257_74).abs() < f64::EPSILON);
}
}

View File

@ -7,6 +7,7 @@ use std::{cmp, mem, ptr, slice, str};
use bitflags::bitflags;
use log::{debug, trace};
use unicode_width::UnicodeWidthChar;
use vte::ansi::{Hyperlink as VteHyperlink, Rgb as VteRgb};
use crate::ansi::{
self, Attr, CharsetIndex, Color, CursorShape, CursorStyle, Handler, NamedColor, StandardCharset,
@ -16,8 +17,8 @@ use crate::event::{Event, EventListener};
use crate::grid::{Dimensions, Grid, GridIterator, Scroll};
use crate::index::{self, Boundary, Column, Direction, Line, Point, Side};
use crate::selection::{Selection, SelectionRange, SelectionType};
use crate::term::cell::{Cell, Flags, Hyperlink, LineLength};
use crate::term::color::{Colors, Rgb};
use crate::term::cell::{Cell, Flags, LineLength};
use crate::term::color::Colors;
use crate::vi_mode::{ViModeCursor, ViMotion};
pub mod cell;
@ -1069,7 +1070,10 @@ impl<T: EventListener> Handler for Term<T> {
}
#[inline]
fn goto(&mut self, line: Line, col: Column) {
fn goto(&mut self, line: i32, col: usize) {
let line = Line(line);
let col = Column(col);
trace!("Going to: line={}, col={}", line, col);
let (y_offset, max_y) = if self.mode.contains(TermMode::ORIGIN) {
(self.scroll_region.start, self.scroll_region.end - 1)
@ -1085,15 +1089,15 @@ impl<T: EventListener> Handler for Term<T> {
}
#[inline]
fn goto_line(&mut self, line: Line) {
fn goto_line(&mut self, line: i32) {
trace!("Going to line: {}", line);
self.goto(line, self.grid.cursor.point.column)
self.goto(line, self.grid.cursor.point.column.0)
}
#[inline]
fn goto_col(&mut self, col: Column) {
fn goto_col(&mut self, col: usize) {
trace!("Going to column: {}", col);
self.goto(self.grid.cursor.point.line, col)
self.goto(self.grid.cursor.point.line.0, col)
}
#[inline]
@ -1127,17 +1131,23 @@ impl<T: EventListener> Handler for Term<T> {
#[inline]
fn move_up(&mut self, lines: usize) {
trace!("Moving up: {}", lines);
self.goto(self.grid.cursor.point.line - lines, self.grid.cursor.point.column)
let line = self.grid.cursor.point.line - lines;
let column = self.grid.cursor.point.column;
self.goto(line.0, column.0)
}
#[inline]
fn move_down(&mut self, lines: usize) {
trace!("Moving down: {}", lines);
self.goto(self.grid.cursor.point.line + lines, self.grid.cursor.point.column)
let line = self.grid.cursor.point.line + lines;
let column = self.grid.cursor.point.column;
self.goto(line.0, column.0)
}
#[inline]
fn move_forward(&mut self, cols: Column) {
fn move_forward(&mut self, cols: usize) {
trace!("Moving forward: {}", cols);
let last_column = cmp::min(self.grid.cursor.point.column + cols, self.last_column());
@ -1149,9 +1159,9 @@ impl<T: EventListener> Handler for Term<T> {
}
#[inline]
fn move_backward(&mut self, cols: Column) {
fn move_backward(&mut self, cols: usize) {
trace!("Moving backward: {}", cols);
let column = self.grid.cursor.point.column.saturating_sub(cols.0);
let column = self.grid.cursor.point.column.saturating_sub(cols);
let cursor_line = self.grid.cursor.point.line.0 as usize;
self.damage.damage_line(cursor_line, column, self.grid.cursor.point.column.0);
@ -1198,13 +1208,17 @@ impl<T: EventListener> Handler for Term<T> {
#[inline]
fn move_down_and_cr(&mut self, lines: usize) {
trace!("Moving down and cr: {}", lines);
self.goto(self.grid.cursor.point.line + lines, Column(0))
let line = self.grid.cursor.point.line + lines;
self.goto(line.0, 0)
}
#[inline]
fn move_up_and_cr(&mut self, lines: usize) {
trace!("Moving up and cr: {}", lines);
self.goto(self.grid.cursor.point.line - lines, Column(0))
let line = self.grid.cursor.point.line - lines;
self.goto(line.0, 0)
}
/// Insert tab at cursor position.
@ -1362,7 +1376,7 @@ impl<T: EventListener> Handler for Term<T> {
}
#[inline]
fn erase_chars(&mut self, count: Column) {
fn erase_chars(&mut self, count: usize) {
let cursor = &self.grid.cursor;
trace!("Erasing chars: count={}, col={}", count, cursor.point.column);
@ -1479,9 +1493,11 @@ impl<T: EventListener> Handler for Term<T> {
/// Set the indexed color value.
#[inline]
fn set_color(&mut self, index: usize, color: Rgb) {
fn set_color(&mut self, index: usize, color: VteRgb) {
trace!("Setting color[{}] = {:?}", index, color);
let color = color.into();
// Damage terminal if the color changed and it's not the cursor.
if index != NamedColor::Cursor as usize && self.colors[index] != Some(color) {
self.mark_fully_damaged();
@ -1679,9 +1695,9 @@ impl<T: EventListener> Handler for Term<T> {
}
#[inline]
fn set_hyperlink(&mut self, hyperlink: Option<Hyperlink>) {
fn set_hyperlink(&mut self, hyperlink: Option<VteHyperlink>) {
trace!("Setting hyperlink: {:?}", hyperlink);
self.grid.cursor.template.set_hyperlink(hyperlink);
self.grid.cursor.template.set_hyperlink(hyperlink.map(|e| e.into()));
}
/// Set a terminal attribute.
@ -1858,7 +1874,7 @@ impl<T: EventListener> Handler for Term<T> {
let screen_lines = Line(self.screen_lines() as i32);
self.scroll_region.start = cmp::min(start, screen_lines);
self.scroll_region.end = cmp::min(end, screen_lines);
self.goto(Line(0), Column(0));
self.goto(0, 0);
}
#[inline]
@ -2756,7 +2772,7 @@ mod tests {
// Reset terminal for partial damage tests since it's initialized as fully damaged.
term.reset_damage();
term.goto(Line(1), Column(1));
term.goto(1, 1);
// NOTE While we can use `[Term::damage]` to access terminal damage information, in the
// following tests we will be accessing `term.damage.lines` directly to avoid adding extra
@ -2766,13 +2782,13 @@ mod tests {
assert_eq!(term.damage.lines[1], LineDamageBounds { line: 1, left: 1, right: 1 });
term.damage.reset(num_cols);
term.move_forward(Column(3));
term.move_forward(3);
assert_eq!(term.damage.lines[1], LineDamageBounds { line: 1, left: 1, right: 4 });
term.damage.reset(num_cols);
term.move_backward(Column(8));
term.move_backward(8);
assert_eq!(term.damage.lines[1], LineDamageBounds { line: 1, left: 0, right: 4 });
term.goto(Line(5), Column(5));
term.goto(5, 5);
term.damage.reset(num_cols);
term.backspace();
@ -2795,7 +2811,7 @@ mod tests {
term.wrapline();
assert_eq!(term.damage.lines[6], LineDamageBounds { line: 6, left: 3, right: 3 });
assert_eq!(term.damage.lines[7], LineDamageBounds { line: 7, left: 0, right: 0 });
term.move_forward(Column(3));
term.move_forward(3);
term.move_up(1);
term.damage.reset(num_cols);
@ -2808,20 +2824,20 @@ mod tests {
assert_eq!(term.damage.lines[7], LineDamageBounds { line: 7, left: 0, right: 3 });
term.damage.reset(num_cols);
term.erase_chars(Column(5));
term.erase_chars(5);
assert_eq!(term.damage.lines[7], LineDamageBounds { line: 7, left: 0, right: 5 });
term.damage.reset(num_cols);
term.delete_chars(3);
let right = term.columns() - 1;
assert_eq!(term.damage.lines[7], LineDamageBounds { line: 7, left: 0, right });
term.move_forward(Column(term.columns()));
term.move_forward(term.columns());
term.damage.reset(num_cols);
term.move_backward_tabs(1);
assert_eq!(term.damage.lines[7], LineDamageBounds { line: 7, left: 8, right });
term.save_cursor_position();
term.goto(Line(1), Column(1));
term.goto(1, 1);
term.damage.reset(num_cols);
term.restore_cursor_position();
@ -2896,12 +2912,12 @@ mod tests {
term.reset_damage();
let color_index = 257;
term.set_color(color_index, Rgb::default());
term.set_color(color_index, VteRgb::default());
assert!(term.damage.is_fully_damaged);
term.reset_damage();
// Setting the same color once again shouldn't trigger full damage.
term.set_color(color_index, Rgb::default());
term.set_color(color_index, VteRgb::default());
assert!(!term.damage.is_fully_damaged);
term.reset_color(color_index);
@ -2909,7 +2925,7 @@ mod tests {
term.reset_damage();
// We shouldn't trigger fully damage when cursor gets update.
term.set_color(NamedColor::Cursor as usize, Rgb::default());
term.set_color(NamedColor::Cursor as usize, VteRgb::default());
assert!(!term.damage.is_fully_damaged);
// However requesting terminal damage should mark terminal as fully damaged in `Insert`

View File

@ -109,7 +109,7 @@ fn ref_test(dir: &Path) {
config.scrolling.set_history(ref_config.history_size);
let mut terminal = Term::new(&config, &size, Mock);
let mut parser = ansi::Processor::new();
let mut parser: ansi::Processor = ansi::Processor::new();
for byte in recording {
parser.advance(&mut terminal, byte);