aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-12-04 11:14:27 -0800
committerJoe Wilm <joe@jwilm.com>2016-12-11 20:23:41 -0800
commit23e36f19255db60084c2c240a166d137f6c12c3e (patch)
tree8f37cb27e0c9ed218e26bddc691b3ae15824e50e /src
parent3151ef862596bbfc69b2941765f2574348d85a8f (diff)
downloadalacritty-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.rs119
-rw-r--r--src/config.rs81
-rw-r--r--src/main.rs2
-rw-r--r--src/renderer/mod.rs37
-rw-r--r--src/term/cell.rs11
-rw-r--r--src/term/mod.rs32
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);