diff options
author | Anhad Singh <62820092+Andy-Python-Programmer@users.noreply.github.com> | 2023-05-24 06:35:58 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-23 20:35:58 +0000 |
commit | cb7ad5b7e6893787c2006cc8cb09fbbc4711c0f7 (patch) | |
tree | e8c5315bb620e6d4e1564dfd6825303b498a3d6d /alacritty_terminal/src/term | |
parent | f0379f2da751e81ba05bbf65ecb5e59590f39be4 (diff) | |
download | alacritty-cb7ad5b7e6893787c2006cc8cb09fbbc4711c0f7.tar.gz alacritty-cb7ad5b7e6893787c2006cc8cb09fbbc4711c0f7.zip |
Switch to VTE's built-in ansi feature
Co-authored-by: Christian Duerr <contact@christianduerr.com>
Diffstat (limited to 'alacritty_terminal/src/term')
-rw-r--r-- | alacritty_terminal/src/term/cell.rs | 13 | ||||
-rw-r--r-- | alacritty_terminal/src/term/color.rs | 104 | ||||
-rw-r--r-- | alacritty_terminal/src/term/mod.rs | 76 |
3 files changed, 86 insertions, 107 deletions
diff --git a/alacritty_terminal/src/term/cell.rs b/alacritty_terminal/src/term/cell.rs index 5253ede1..ddf6a745 100644 --- a/alacritty_terminal/src/term/cell.rs +++ b/alacritty_terminal/src/term/cell.rs @@ -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. diff --git a/alacritty_terminal/src/term/color.rs b/alacritty_terminal/src/term/color.rs index 8f193b39..b4bdba3a 100644 --- a/alacritty_terminal/src/term/color.rs +++ b/alacritty_terminal/src/term/color.rs @@ -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); + #[inline] + pub const fn new(r: u8, g: u8, b: u8) -> Self { + Self(VteRgb { r, g, b }) + } - 0.2126 * r_luminance + 0.7152 * g_luminance + 0.0722 * b_luminance + #[inline] + pub fn as_tuple(self) -> (u8, u8, u8) { + (self.0.r, self.0.g, self.0.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(); +impl From<VteRgb> for Rgb { + fn from(value: VteRgb) -> Self { + Self(value) + } +} - let (darker, lighter) = if self_luminance > other_luminance { - (other_luminance, self_luminance) - } else { - (self_luminance, other_luminance) - }; +impl Deref for Rgb { + type Target = VteRgb; - (lighter + 0.05) / (darker + 0.05) + 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); - } -} diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index bdfd6c9b..7c4abb57 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -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` |