diff options
author | Joe Wilm <joe@jwilm.com> | 2016-12-04 11:14:27 -0800 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-12-11 20:23:41 -0800 |
commit | 23e36f19255db60084c2c240a166d137f6c12c3e (patch) | |
tree | 8f37cb27e0c9ed218e26bddc691b3ae15824e50e /src | |
parent | 3151ef862596bbfc69b2941765f2574348d85a8f (diff) | |
download | alacritty-23e36f19255db60084c2c240a166d137f6c12c3e.tar.gz alacritty-23e36f19255db60084c2c240a166d137f6c12c3e.zip |
Add support for indexed colors
ANSI escape sequences like `\x1b[48;5;10m` were not supported until now.
Specifically, the second attribute, 5, says that the following attribute
is a color index.
The ref tests were updated since `enum Color` variants changed.
Diffstat (limited to 'src')
-rw-r--r-- | src/ansi.rs | 119 | ||||
-rw-r--r-- | src/config.rs | 81 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/renderer/mod.rs | 37 | ||||
-rw-r--r-- | src/term/cell.rs | 11 | ||||
-rw-r--r-- | src/term/mod.rs | 32 |
6 files changed, 163 insertions, 119 deletions
diff --git a/src/ansi.rs b/src/ansi.rs index 32c7751d..089bc277 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -310,7 +310,7 @@ pub enum TabulationClearMode { /// The order here matters since the enum should be castable to a `usize` for /// indexing a color list. #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum Color { +pub enum NamedColor { /// Black Black = 0, /// Red @@ -344,11 +344,18 @@ pub enum Color { /// Bright white BrightWhite, /// The foreground color - Foreground, + Foreground = 256, /// The background color Background, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum Color { + Named(NamedColor), + Spec(Rgb), + Indexed(u8), +} + /// Terminal character attributes #[derive(Debug, Eq, PartialEq)] pub enum Attr { @@ -388,12 +395,8 @@ pub enum Attr { CancelStrike, /// Set indexed foreground color Foreground(Color), - /// Set specific foreground color - ForegroundSpec(Rgb), /// Set indexed background color Background(Color), - /// Set specific background color - BackgroundSpec(Rgb), } impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> { @@ -575,54 +578,54 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> { 27 => Attr::CancelReverse, 28 => Attr::CancelHidden, 29 => Attr::CancelStrike, - 30 => Attr::Foreground(Color::Black), - 31 => Attr::Foreground(Color::Red), - 32 => Attr::Foreground(Color::Green), - 33 => Attr::Foreground(Color::Yellow), - 34 => Attr::Foreground(Color::Blue), - 35 => Attr::Foreground(Color::Magenta), - 36 => Attr::Foreground(Color::Cyan), - 37 => Attr::Foreground(Color::White), + 30 => Attr::Foreground(Color::Named(NamedColor::Black)), + 31 => Attr::Foreground(Color::Named(NamedColor::Red)), + 32 => Attr::Foreground(Color::Named(NamedColor::Green)), + 33 => Attr::Foreground(Color::Named(NamedColor::Yellow)), + 34 => Attr::Foreground(Color::Named(NamedColor::Blue)), + 35 => Attr::Foreground(Color::Named(NamedColor::Magenta)), + 36 => Attr::Foreground(Color::Named(NamedColor::Cyan)), + 37 => Attr::Foreground(Color::Named(NamedColor::White)), 38 => { - if let Some(spec) = parse_color(&args[i..], &mut i) { - Attr::ForegroundSpec(spec) + if let Some(color) = parse_color(&args[i..], &mut i) { + Attr::Foreground(color) } else { break; } }, - 39 => Attr::Foreground(Color::Foreground), - 40 => Attr::Background(Color::Black), - 41 => Attr::Background(Color::Red), - 42 => Attr::Background(Color::Green), - 43 => Attr::Background(Color::Yellow), - 44 => Attr::Background(Color::Blue), - 45 => Attr::Background(Color::Magenta), - 46 => Attr::Background(Color::Cyan), - 47 => Attr::Background(Color::White), + 39 => Attr::Foreground(Color::Named(NamedColor::Foreground)), + 40 => Attr::Background(Color::Named(NamedColor::Black)), + 41 => Attr::Background(Color::Named(NamedColor::Red)), + 42 => Attr::Background(Color::Named(NamedColor::Green)), + 43 => Attr::Background(Color::Named(NamedColor::Yellow)), + 44 => Attr::Background(Color::Named(NamedColor::Blue)), + 45 => Attr::Background(Color::Named(NamedColor::Magenta)), + 46 => Attr::Background(Color::Named(NamedColor::Cyan)), + 47 => Attr::Background(Color::Named(NamedColor::White)), 48 => { - if let Some(spec) = parse_color(&args[i..], &mut i) { - Attr::BackgroundSpec(spec) + if let Some(color) = parse_color(&args[i..], &mut i) { + Attr::Background(color) } else { break; } }, - 49 => Attr::Background(Color::Background), - 90 => Attr::Foreground(Color::BrightBlack), - 91 => Attr::Foreground(Color::BrightRed), - 92 => Attr::Foreground(Color::BrightGreen), - 93 => Attr::Foreground(Color::BrightYellow), - 94 => Attr::Foreground(Color::BrightBlue), - 95 => Attr::Foreground(Color::BrightMagenta), - 96 => Attr::Foreground(Color::BrightCyan), - 97 => Attr::Foreground(Color::BrightWhite), - 100 => Attr::Foreground(Color::BrightBlack), - 101 => Attr::Foreground(Color::BrightRed), - 102 => Attr::Foreground(Color::BrightGreen), - 103 => Attr::Foreground(Color::BrightYellow), - 104 => Attr::Foreground(Color::BrightBlue), - 105 => Attr::Foreground(Color::BrightMagenta), - 106 => Attr::Foreground(Color::BrightCyan), - 107 => Attr::Foreground(Color::BrightWhite), + 49 => Attr::Background(Color::Named(NamedColor::Background)), + 90 => Attr::Foreground(Color::Named(NamedColor::BrightBlack)), + 91 => Attr::Foreground(Color::Named(NamedColor::BrightRed)), + 92 => Attr::Foreground(Color::Named(NamedColor::BrightGreen)), + 93 => Attr::Foreground(Color::Named(NamedColor::BrightYellow)), + 94 => Attr::Foreground(Color::Named(NamedColor::BrightBlue)), + 95 => Attr::Foreground(Color::Named(NamedColor::BrightMagenta)), + 96 => Attr::Foreground(Color::Named(NamedColor::BrightCyan)), + 97 => Attr::Foreground(Color::Named(NamedColor::BrightWhite)), + 100 => Attr::Foreground(Color::Named(NamedColor::BrightBlack)), + 101 => Attr::Foreground(Color::Named(NamedColor::BrightRed)), + 102 => Attr::Foreground(Color::Named(NamedColor::BrightGreen)), + 103 => Attr::Foreground(Color::Named(NamedColor::BrightYellow)), + 104 => Attr::Foreground(Color::Named(NamedColor::BrightBlue)), + 105 => Attr::Foreground(Color::Named(NamedColor::BrightMagenta)), + 106 => Attr::Foreground(Color::Named(NamedColor::BrightCyan)), + 107 => Attr::Foreground(Color::Named(NamedColor::BrightWhite)), _ => unhandled!(), }; @@ -674,7 +677,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> { /// Parse a color specifier from list of attributes -fn parse_color(attrs: &[i64], i: &mut usize) -> Option<Rgb> { +fn parse_color(attrs: &[i64], i: &mut usize) -> Option<Color> { if attrs.len() < 2 { return None; } @@ -699,11 +702,29 @@ fn parse_color(attrs: &[i64], i: &mut usize) -> Option<Rgb> { return None; } - Some(Rgb { + Some(Color::Spec(Rgb { r: r as u8, g: g as u8, b: b as u8 - }) + })) + }, + 5 => { + if attrs.len() < 3 { + err_println!("Expected color index; got {:?}", attrs); + None + } else { + *i = *i + 2; + let idx = attrs[*i]; + match idx { + 0 ... 255 => { + Some(Color::Indexed(idx as u8)) + }, + _ => { + err_println!("Invalid color index: {}", idx); + None + } + } + } }, _ => { err_println!("Unexpected color attr: {}", attrs[*i+1]); @@ -863,7 +884,7 @@ pub mod C1 { #[cfg(test)] mod tests { use index::{Line, Column}; - use super::{Processor, Handler, Attr, TermInfo}; + use super::{Processor, Handler, Attr, TermInfo, Color}; use ::Rgb; #[derive(Default)] @@ -923,7 +944,7 @@ mod tests { b: 255 }; - assert_eq!(handler.attr, Some(Attr::ForegroundSpec(spec))); + assert_eq!(handler.attr, Some(Attr::Foreground(Color::Spec(spec)))); } /// No exactly a test; useful for debugging diff --git a/src/config.rs b/src/config.rs index 8ab6e662..60887720 100644 --- a/src/config.rs +++ b/src/config.rs @@ -665,34 +665,59 @@ impl Config { /// /// The ordering returned here is expected by the terminal. Colors are simply indexed in this /// array for performance. - pub fn color_list(&self) -> [Rgb; 18] { - let colors = &self.colors; - - [ - // Normals - colors.normal.black, - colors.normal.red, - colors.normal.green, - colors.normal.yellow, - colors.normal.blue, - colors.normal.magenta, - colors.normal.cyan, - colors.normal.white, - - // Brights - colors.bright.black, - colors.bright.red, - colors.bright.green, - colors.bright.yellow, - colors.bright.blue, - colors.bright.magenta, - colors.bright.cyan, - colors.bright.white, - - // Foreground and background - colors.primary.foreground, - colors.primary.background, - ] + pub fn color_list(&self) -> Vec<Rgb> { + let mut colors = Vec::with_capacity(258); + + // Normals + colors.push(self.colors.normal.black); + colors.push(self.colors.normal.red); + colors.push(self.colors.normal.green); + colors.push(self.colors.normal.yellow); + colors.push(self.colors.normal.blue); + colors.push(self.colors.normal.magenta); + colors.push(self.colors.normal.cyan); + colors.push(self.colors.normal.white); + + // Brights + colors.push(self.colors.bright.black); + colors.push(self.colors.bright.red); + colors.push(self.colors.bright.green); + colors.push(self.colors.bright.yellow); + colors.push(self.colors.bright.blue); + colors.push(self.colors.bright.magenta); + colors.push(self.colors.bright.cyan); + colors.push(self.colors.bright.white); + + // Build colors + for r in 0..6 { + for g in 0..6 { + for b in 0..6 { + colors.push(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 }, + }); + } + } + } + + // Build grays + for i in 0..24 { + let value = i * 10 + 8; + colors.push(Rgb { + r: value, + g: value, + b: value + }); + } + + debug_assert!(colors.len() == 256); + + // Foreground and background + colors.push(self.colors.primary.foreground); + colors.push(self.colors.primary.background); + + colors } pub fn key_bindings(&self) -> &[KeyBinding] { diff --git a/src/main.rs b/src/main.rs index 04b269e3..f25c2111 100644 --- a/src/main.rs +++ b/src/main.rs @@ -371,7 +371,7 @@ impl Display { // Draw render timer if self.render_timer { let timing = format!("{:.3} usec", self.meter.average()); - let color = alacritty::term::cell::Color::Rgb(Rgb { r: 0xd5, g: 0x4e, b: 0x53 }); + let color = alacritty::ansi::Color::Spec(Rgb { r: 0xd5, g: 0x4e, b: 0x53 }); self.renderer.with_api(terminal.size_info(), |mut api| { api.render_string(&timing[..], glyph_cache, &color); }); diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 5f3fbfc7..2073be30 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -26,6 +26,8 @@ use gl; use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op}; use index::{Line, Column}; +use ansi::{Color, NamedColor}; + use config::Config; use term::{self, cell, IndexedCell, Cell}; @@ -241,7 +243,7 @@ pub struct QuadRenderer { atlas: Vec<Atlas>, active_tex: GLuint, batch: Batch, - colors: [Rgb; 18], + colors: Vec<Rgb>, draw_bold_text_with_bright_colors: bool, rx: mpsc::Receiver<Msg>, } @@ -252,7 +254,7 @@ pub struct RenderApi<'a> { batch: &'a mut Batch, atlas: &'a mut Vec<Atlas>, program: &'a mut ShaderProgram, - colors: &'a [Rgb; 18], + colors: &'a [Rgb], } #[derive(Debug)] @@ -271,7 +273,7 @@ pub struct PackedVertex { pub struct Batch { tex: GLuint, instances: Vec<InstanceData>, - colors: [Rgb; 18], + colors: Vec<Rgb>, draw_bold_text_with_bright_colors: bool, } @@ -292,22 +294,35 @@ impl Batch { } let fg = match cell.fg { - ::term::cell::Color::Rgb(rgb) => rgb, - ::term::cell::Color::Ansi(ansi) => { + Color::Spec(rgb) => rgb, + Color::Named(ansi) => { if self.draw_bold_text_with_bright_colors && cell.bold() - && ansi < ::ansi::Color::BrightBlack + && ansi < NamedColor::BrightBlack { self.colors[ansi as usize + 8] } else { self.colors[ansi as usize] } + }, + Color::Indexed(idx) => { + let idx = if self.draw_bold_text_with_bright_colors + && cell.bold() + && idx < 8 + { + idx + 8 + } else { + idx + }; + + self.colors[idx as usize] } }; let bg = match cell.bg { - ::term::cell::Color::Rgb(rgb) => rgb, - ::term::cell::Color::Ansi(ansi) => self.colors[ansi as usize], + Color::Spec(rgb) => rgb, + Color::Named(ansi) => self.colors[ansi as usize], + Color::Indexed(idx) => self.colors[idx as usize], }; self.instances.push(InstanceData { @@ -620,7 +635,7 @@ impl QuadRenderer { impl<'a> RenderApi<'a> { pub fn clear(&self) { - let color = self.colors[::ansi::Color::Background as usize]; + let color = self.colors[NamedColor::Background as usize]; unsafe { gl::ClearColor( color.r as f32 / 255.0, @@ -666,7 +681,7 @@ impl<'a> RenderApi<'a> { &mut self, string: &str, glyph_cache: &mut GlyphCache, - color: &::term::cell::Color, + color: &Color, ) { let line = Line(23); let col = Column(0); @@ -679,7 +694,7 @@ impl<'a> RenderApi<'a> { inner: Cell { c: c, bg: *color, - fg: cell::Color::Rgb(Rgb { r: 0, g: 0, b: 0}), + fg: Color::Spec(Rgb { r: 0, g: 0, b: 0}), flags: cell::Flags::empty(), } }) diff --git a/src/term/cell.rs b/src/term/cell.rs index 506fde0e..df648294 100644 --- a/src/term/cell.rs +++ b/src/term/cell.rs @@ -15,8 +15,7 @@ use std::mem; -use ansi; -use Rgb; +use ansi::{NamedColor, Color}; bitflags! { #[derive(Serialize, Deserialize)] @@ -28,12 +27,6 @@ bitflags! { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum Color { - Rgb(Rgb), - Ansi(ansi::Color), -} - #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Cell { pub c: char, @@ -59,7 +52,7 @@ impl Cell { #[inline] pub fn is_empty(&self) -> bool { self.c == ' ' && - self.bg == Color::Ansi(ansi::Color::Background) && + self.bg == Color::Named(NamedColor::Background) && !self.flags.contains(INVERSE) } diff --git a/src/term/mod.rs b/src/term/mod.rs index acbb70ac..9ed19c81 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -20,7 +20,7 @@ use std::cmp; use ansi::{self, Attr, Handler}; use grid::{Grid, ClearRegion}; use index::{Cursor, Column, Line}; -use ansi::Color; +use ansi::{Color, NamedColor}; pub mod cell; pub use self::cell::Cell; @@ -250,8 +250,8 @@ impl Term { pub fn new(size: SizeInfo) -> Term { let template = Cell::new( ' ', - cell::Color::Ansi(Color::Foreground), - cell::Color::Ansi(Color::Background) + Color::Named(NamedColor::Foreground), + Color::Named(NamedColor::Background) ); let num_cols = size.cols(); @@ -800,21 +800,11 @@ impl ansi::Handler for Term { fn terminal_attribute(&mut self, attr: Attr) { debug_println!("Set Attribute: {:?}", attr); match attr { - Attr::Foreground(named_color) => { - self.template_cell.fg = cell::Color::Ansi(named_color); - }, - Attr::Background(named_color) => { - self.template_cell.bg = cell::Color::Ansi(named_color); - }, - Attr::ForegroundSpec(rgb) => { - self.template_cell.fg = cell::Color::Rgb(rgb); - }, - Attr::BackgroundSpec(rgb) => { - self.template_cell.bg = cell::Color::Rgb(rgb); - }, + Attr::Foreground(color) => self.template_cell.fg = color, + Attr::Background(color) => self.template_cell.bg = color, Attr::Reset => { - self.template_cell.fg = cell::Color::Ansi(Color::Foreground); - self.template_cell.bg = cell::Color::Ansi(Color::Background); + self.template_cell.fg = Color::Named(NamedColor::Foreground); + self.template_cell.bg = Color::Named(NamedColor::Background); self.template_cell.flags = cell::Flags::empty(); }, Attr::Reverse => self.template_cell.flags.insert(cell::INVERSE), @@ -888,10 +878,10 @@ mod tests { use super::limit; - use ansi::{Color}; + use ansi::{Color, NamedColor}; use grid::Grid; use index::{Line, Column}; - use term::{cell, Cell}; + use term::{Cell}; /// Check that the grid can be serialized back and forth losslessly /// @@ -901,8 +891,8 @@ mod tests { fn grid_serde() { let template = Cell::new( ' ', - cell::Color::Ansi(Color::Foreground), - cell::Color::Ansi(Color::Background) + Color::Named(NamedColor::Foreground), + Color::Named(NamedColor::Background) ); let grid = Grid::new(Line(24), Column(80), &template); |