aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ansi.rs16
-rw-r--r--src/config.rs216
-rw-r--r--src/main.rs8
-rw-r--r--src/renderer/mod.rs45
4 files changed, 196 insertions, 89 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index 089bc277..8ff0a2e4 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -349,6 +349,22 @@ pub enum NamedColor {
Background,
}
+impl NamedColor {
+ pub fn to_bright(&self) -> Self {
+ match *self {
+ NamedColor::Black => NamedColor::BrightBlack,
+ NamedColor::Red => NamedColor::BrightRed,
+ NamedColor::Green => NamedColor::BrightGreen,
+ NamedColor::Yellow => NamedColor::BrightYellow,
+ NamedColor::Blue => NamedColor::BrightBlue,
+ NamedColor::Magenta => NamedColor::BrightMagenta,
+ NamedColor::Cyan => NamedColor::BrightCyan,
+ NamedColor::White => NamedColor::BrightWhite,
+ val => val
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Color {
Named(NamedColor),
diff --git a/src/config.rs b/src/config.rs
index 60887720..5911fdb9 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -4,11 +4,13 @@
//! parameters including font family and style, font size, etc. In the future,
//! the config file will also hold user and platform specific keybindings.
use std::env;
+use std::fmt;
use std::fs;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::mpsc;
+use std::ops::{Index, IndexMut};
use ::Rgb;
use font::Size;
@@ -19,11 +21,150 @@ use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op};
use input::{Action, Binding, MouseBinding, KeyBinding};
+use ansi;
+
/// Function that returns true for serde default
fn true_bool() -> bool {
true
}
+/// List of indexed colors
+///
+/// The first 16 entries are the standard ansi named colors. Items 16..232 are
+/// the color cube. Items 233..256 are the grayscale ramp. Finally, item 256 is
+/// the configured foreground color, and item 257 is the configured background
+/// color.
+pub struct ColorList([Rgb; 258]);
+
+impl fmt::Debug for ColorList {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("ColorList[..]")
+ }
+}
+
+impl Default for ColorList {
+ fn default() -> ColorList {
+ ColorList::from(Colors::default())
+ }
+}
+
+impl From<Colors> for ColorList {
+ fn from(colors: Colors) -> ColorList {
+ // Type inference fails without this annotation
+ let mut list: ColorList = unsafe { ::std::mem::uninitialized() };
+
+ list.fill_named(&colors);
+ list.fill_cube();
+ list.fill_gray_ramp();
+
+ list
+ }
+}
+
+impl ColorList {
+ fn fill_named(&mut self, colors: &Colors) {
+ // Normals
+ self[ansi::NamedColor::Black] = colors.normal.black;
+ self[ansi::NamedColor::Red] = colors.normal.red;
+ self[ansi::NamedColor::Green] = colors.normal.green;
+ self[ansi::NamedColor::Yellow] = colors.normal.yellow;
+ self[ansi::NamedColor::Blue] = colors.normal.blue;
+ self[ansi::NamedColor::Magenta] = colors.normal.magenta;
+ self[ansi::NamedColor::Cyan] = colors.normal.cyan;
+ self[ansi::NamedColor::White] = colors.normal.white;
+
+ // Brights
+ self[ansi::NamedColor::BrightBlack] = colors.bright.black;
+ self[ansi::NamedColor::BrightRed] = colors.bright.red;
+ self[ansi::NamedColor::BrightGreen] = colors.bright.green;
+ self[ansi::NamedColor::BrightYellow] = colors.bright.yellow;
+ self[ansi::NamedColor::BrightBlue] = colors.bright.blue;
+ self[ansi::NamedColor::BrightMagenta] = colors.bright.magenta;
+ self[ansi::NamedColor::BrightCyan] = colors.bright.cyan;
+ self[ansi::NamedColor::BrightWhite] = colors.bright.white;
+
+ // Foreground and background
+ self[ansi::NamedColor::Foreground] = colors.primary.foreground;
+ self[ansi::NamedColor::Background] = colors.primary.background;
+ }
+
+ fn fill_cube(&mut self) {
+ let mut index = 16;
+ // Build colors
+ for r in 0..6 {
+ for g in 0..6 {
+ for b in 0..6 {
+ 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);
+ }
+
+ fn fill_gray_ramp(&mut self) {
+ let mut index = 232;
+
+ for i in 0..24 {
+ let value = i * 10 + 8;
+ self[index] = Rgb {
+ r: value,
+ g: value,
+ b: value
+ };
+ index += 1;
+ }
+
+ debug_assert!(index == 256);
+ }
+}
+
+impl Index<ansi::NamedColor> for ColorList {
+ type Output = Rgb;
+
+ #[inline]
+ fn index(&self, idx: ansi::NamedColor) -> &Self::Output {
+ &self.0[idx as usize]
+ }
+}
+
+impl IndexMut<ansi::NamedColor> for ColorList {
+ #[inline]
+ fn index_mut(&mut self, idx: ansi::NamedColor) -> &mut Self::Output {
+ &mut self.0[idx as usize]
+ }
+}
+
+impl Index<usize> for ColorList {
+ type Output = Rgb;
+
+ #[inline]
+ fn index(&self, idx: usize) -> &Self::Output {
+ &self.0[idx]
+ }
+}
+
+impl Index<u8> for ColorList {
+ type Output = Rgb;
+
+ #[inline]
+ fn index(&self, idx: u8) -> &Self::Output {
+ &self.0[idx as usize]
+ }
+}
+
+impl IndexMut<usize> for ColorList {
+ #[inline]
+ fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
+ &mut self.0[idx]
+ }
+}
+
/// Top-level config type
#[derive(Debug, Deserialize)]
pub struct Config {
@@ -43,9 +184,8 @@ pub struct Config {
#[serde(default="true_bool")]
draw_bold_text_with_bright_colors: bool,
- /// The standard ANSI colors to use
#[serde(default)]
- colors: Colors,
+ colors: ColorList,
/// Keybindings
#[serde(default)]
@@ -415,6 +555,15 @@ impl de::Deserialize for RawBinding {
}
}
+impl de::Deserialize for ColorList {
+ fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<Self, D::Error>
+ where D: de::Deserializer
+ {
+ let named_colors = Colors::deserialize(deserializer)?;
+ Ok(ColorList::from(named_colors))
+ }
+}
+
impl de::Deserialize for MouseBinding {
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<Self, D::Error>
where D: de::Deserializer
@@ -665,59 +814,8 @@ 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) -> 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 color_list(&self) -> &ColorList {
+ &self.colors
}
pub fn key_bindings(&self) -> &[KeyBinding] {
@@ -728,14 +826,6 @@ impl Config {
&self.mouse_bindings[..]
}
- pub fn fg_color(&self) -> Rgb {
- self.colors.primary.foreground
- }
-
- pub fn bg_color(&self) -> Rgb {
- self.colors.primary.background
- }
-
#[inline]
pub fn draw_bold_text_with_bright_colors(&self) -> bool {
self.draw_bold_text_with_bright_colors
diff --git a/src/main.rs b/src/main.rs
index f25c2111..80389b2b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -256,7 +256,7 @@ fn main() {
let terminal = terminal.lock();
signal_flag.set(false);
if terminal.dirty {
- display.draw(terminal);
+ display.draw(terminal, &config);
}
if process_should_exit() {
@@ -330,7 +330,7 @@ impl Display {
/// A reference to Term whose state is being drawn must be provided.
///
/// This call may block if vsync is enabled
- pub fn draw(&mut self, mut terminal: MutexGuard<Term>) {
+ pub fn draw(&mut self, mut terminal: MutexGuard<Term>, config: &Config) {
terminal.dirty = false;
// Resize events new_size and are handled outside the poll_events
@@ -360,7 +360,7 @@ impl Display {
let _sampler = self.meter.sampler();
let size_info = terminal.size_info().clone();
- self.renderer.with_api(&size_info, |mut api| {
+ self.renderer.with_api(config, &size_info, |mut api| {
api.clear();
// Draw the grid
@@ -372,7 +372,7 @@ impl Display {
if self.render_timer {
let timing = format!("{:.3} usec", self.meter.average());
let color = alacritty::ansi::Color::Spec(Rgb { r: 0xd5, g: 0x4e, b: 0x53 });
- self.renderer.with_api(terminal.size_info(), |mut api| {
+ self.renderer.with_api(config, 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 2073be30..2728ad5f 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -28,7 +28,7 @@ use index::{Line, Column};
use ansi::{Color, NamedColor};
-use config::Config;
+use config::{Config, ColorList};
use term::{self, cell, IndexedCell, Cell};
use super::Rgb;
@@ -243,7 +243,6 @@ pub struct QuadRenderer {
atlas: Vec<Atlas>,
active_tex: GLuint,
batch: Batch,
- colors: Vec<Rgb>,
draw_bold_text_with_bright_colors: bool,
rx: mpsc::Receiver<Msg>,
}
@@ -254,7 +253,7 @@ pub struct RenderApi<'a> {
batch: &'a mut Batch,
atlas: &'a mut Vec<Atlas>,
program: &'a mut ShaderProgram,
- colors: &'a [Rgb],
+ colors: &'a ColorList,
}
#[derive(Debug)]
@@ -273,7 +272,6 @@ pub struct PackedVertex {
pub struct Batch {
tex: GLuint,
instances: Vec<InstanceData>,
- colors: Vec<Rgb>,
draw_bold_text_with_bright_colors: bool,
}
@@ -283,12 +281,16 @@ impl Batch {
Batch {
tex: 0,
instances: Vec::with_capacity(BATCH_MAX),
- colors: config.color_list(),
draw_bold_text_with_bright_colors: config.draw_bold_text_with_bright_colors(),
}
}
- pub fn add_item(&mut self, cell: &IndexedCell, glyph: &Glyph) {
+ pub fn add_item(
+ &mut self,
+ cell: &IndexedCell,
+ glyph: &Glyph,
+ colors: &ColorList
+ ) {
if self.is_empty() {
self.tex = glyph.tex_id;
}
@@ -296,13 +298,10 @@ impl Batch {
let fg = match cell.fg {
Color::Spec(rgb) => rgb,
Color::Named(ansi) => {
- if self.draw_bold_text_with_bright_colors
- && cell.bold()
- && ansi < NamedColor::BrightBlack
- {
- self.colors[ansi as usize + 8]
+ if self.draw_bold_text_with_bright_colors && cell.bold() {
+ colors[ansi.to_bright()]
} else {
- self.colors[ansi as usize]
+ colors[ansi]
}
},
Color::Indexed(idx) => {
@@ -315,14 +314,14 @@ impl Batch {
idx
};
- self.colors[idx as usize]
+ colors[idx]
}
};
let bg = match cell.bg {
Color::Spec(rgb) => rgb,
- Color::Named(ansi) => self.colors[ansi as usize],
- Color::Indexed(idx) => self.colors[idx as usize],
+ Color::Named(ansi) => colors[ansi],
+ Color::Indexed(idx) => colors[idx],
};
self.instances.push(InstanceData {
@@ -528,7 +527,6 @@ impl QuadRenderer {
atlas: Vec::new(),
active_tex: 0,
batch: Batch::new(config),
- colors: config.color_list(),
rx: msg_rx,
draw_bold_text_with_bright_colors: config.draw_bold_text_with_bright_colors(),
};
@@ -540,12 +538,15 @@ impl QuadRenderer {
}
pub fn update_config(&mut self, config: &Config) {
- self.colors = config.color_list();
- self.batch.colors = config.color_list();
self.batch.draw_bold_text_with_bright_colors = config.draw_bold_text_with_bright_colors();
}
- pub fn with_api<F, T>(&mut self, props: &term::SizeInfo, func: F) -> T
+ pub fn with_api<F, T>(
+ &mut self,
+ config: &Config,
+ props: &term::SizeInfo,
+ func: F
+ ) -> T
where F: FnOnce(RenderApi) -> T
{
while let Ok(msg) = self.rx.try_recv() {
@@ -571,7 +572,7 @@ impl QuadRenderer {
batch: &mut self.batch,
atlas: &mut self.atlas,
program: &mut self.program,
- colors: &self.colors,
+ colors: &config.color_list(),
});
unsafe {
@@ -635,7 +636,7 @@ impl QuadRenderer {
impl<'a> RenderApi<'a> {
pub fn clear(&self) {
- let color = self.colors[NamedColor::Background as usize];
+ let color = self.colors[NamedColor::Background];
unsafe {
gl::ClearColor(
color.r as f32 / 255.0,
@@ -712,7 +713,7 @@ impl<'a> RenderApi<'a> {
}
}
- self.batch.add_item(cell, glyph);
+ self.batch.add_item(cell, glyph, self.colors);
// Render batch and clear if it's full
if self.batch.full() {