aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-10-28 08:52:56 -0700
committerJoe Wilm <joe@jwilm.com>2016-10-28 08:52:56 -0700
commit7cd8a6ca12cd37ae354084c7246060219b1e3af8 (patch)
treeaa23a6355e0550161b957d61d50a663b288c6c2f
parente503baf2e753a1cc8c287f10fb1460635d093168 (diff)
parentf8cb6d42cc0947e93d8913b894d7105afdfe1a2e (diff)
downloadr-alacritty-7cd8a6ca12cd37ae354084c7246060219b1e3af8.tar.gz
r-alacritty-7cd8a6ca12cd37ae354084c7246060219b1e3af8.tar.bz2
r-alacritty-7cd8a6ca12cd37ae354084c7246060219b1e3af8.zip
Merge branch 'reload-colors'
-rw-r--r--src/ansi.rs12
-rw-r--r--src/config.rs74
-rw-r--r--src/main.rs76
-rw-r--r--src/renderer/mod.rs124
-rw-r--r--src/term.rs115
5 files changed, 272 insertions, 129 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index 45cc66f9..c419d7e5 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -337,6 +337,10 @@ pub enum Color {
BrightCyan,
/// Bright white
BrightWhite,
+ /// The foreground color
+ Foreground,
+ /// The background color
+ Background,
}
/// Terminal character attributes
@@ -384,10 +388,6 @@ pub enum Attr {
Background(Color),
/// Set specific background color
BackgroundSpec(Rgb),
- /// Set default foreground
- DefaultForeground,
- /// Set default background
- DefaultBackground,
}
impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
@@ -584,7 +584,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
break;
}
},
- 39 => Attr::DefaultForeground,
+ 39 => Attr::Foreground(Color::Foreground),
40 => Attr::Background(Color::Black),
41 => Attr::Background(Color::Red),
42 => Attr::Background(Color::Green),
@@ -600,7 +600,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
break;
}
},
- 49 => Attr::DefaultBackground,
+ 49 => Attr::Background(Color::Background),
90 => Attr::Foreground(Color::BrightBlack),
91 => Attr::Foreground(Color::BrightRed),
92 => Attr::Foreground(Color::BrightGreen),
diff --git a/src/config.rs b/src/config.rs
index 56f96e80..f3e68dca 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -7,11 +7,13 @@ use std::env;
use std::fs;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
+use std::sync::mpsc;
use ::Rgb;
use font::Size;
use serde_yaml;
use serde::{self, Error as SerdeError};
+use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op};
/// Top-level config type
#[derive(Debug, Deserialize, Default)]
@@ -232,7 +234,7 @@ impl Config {
///
/// 1. `$HOME/.config/alacritty.yml`
/// 2. `$HOME/.alacritty.yml`
- pub fn load() -> Result<Config> {
+ pub fn load() -> Result<(Config, PathBuf)> {
let home = env::var("HOME")?;
// First path
@@ -240,15 +242,17 @@ impl Config {
path.push(".config");
path.push("alacritty.yml");
- // Fallback path
- let mut alt_path = PathBuf::from(&home);
- alt_path.push(".alacritty.yml");
-
- match Config::load_from(&path) {
+ match Config::load_from(path) {
Ok(c) => Ok(c),
Err(e) => {
match e {
- Error::NotFound => Config::load_from(&alt_path),
+ Error::NotFound => {
+ // Fallback path
+ let mut alt_path = PathBuf::from(&home);
+ alt_path.push(".alacritty.yml");
+
+ Config::load_from(alt_path)
+ },
_ => Err(e),
}
}
@@ -259,7 +263,7 @@ 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; 16] {
+ pub fn color_list(&self) -> [Rgb; 18] {
let colors = &self.colors;
[
@@ -282,6 +286,10 @@ impl Config {
colors.bright.magenta,
colors.bright.cyan,
colors.bright.white,
+
+ // Foreground and background
+ colors.primary.foreground,
+ colors.primary.background,
]
}
@@ -311,9 +319,10 @@ impl Config {
self.render_timer
}
- fn load_from<P: AsRef<Path>>(path: P) -> Result<Config> {
- let raw = Config::read_file(path)?;
- Ok(serde_yaml::from_str(&raw[..])?)
+ fn load_from<P: Into<PathBuf>>(path: P) -> Result<(Config, PathBuf)> {
+ let path = path.into();
+ let raw = Config::read_file(path.as_path())?;
+ Ok((serde_yaml::from_str(&raw[..])?, path))
}
fn read_file<P: AsRef<Path>>(path: P) -> Result<String> {
@@ -521,3 +530,46 @@ impl Default for Font {
}
}
}
+
+pub struct Watcher(::std::thread::JoinHandle<()>);
+
+pub trait OnConfigReload {
+ fn on_config_reload(&mut self, Config);
+}
+
+impl Watcher {
+ pub fn new<H: OnConfigReload + Send + 'static>(path: PathBuf, mut handler: H) -> Watcher {
+ Watcher(::util::thread::spawn_named("config watcher", move || {
+ let (tx, rx) = mpsc::channel();
+ let mut watcher = FileWatcher::new(tx).unwrap();
+ watcher.watch(&path).expect("watch alacritty yml");
+
+ let config_path = path.as_path();
+
+ loop {
+ let event = rx.recv().expect("watcher event");
+ let ::notify::Event { path, op } = event;
+
+ if let Ok(op) = op {
+ if op.contains(op::RENAME) {
+ continue;
+ }
+
+ if op.contains(op::IGNORED) {
+ if let Some(path) = path.as_ref() {
+ if let Err(err) = watcher.watch(&path) {
+ err_println!("failed to establish watch on {:?}: {:?}", path, err);
+ }
+
+ if path == config_path {
+ if let Ok((config, _)) = Config::load() {
+ handler.on_config_reload(config);
+ };
+ }
+ }
+ }
+ }
+ }
+ }))
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 9639fd29..b8bc5d07 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -75,7 +75,7 @@ use term::Term;
use tty::process_should_exit;
/// Channel used by resize handling on mac
-static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None;
+static mut RESIZE_SENDER: Option<mpsc::Sender<(u32, u32)>> = None;
#[derive(Clone)]
pub struct Flag(Arc<AtomicBool>);
@@ -98,7 +98,7 @@ impl Flag {
/// Resize handling for Mac
fn window_resize_handler(width: u32, height: u32) {
unsafe {
- if let Some(ref tx) = resize_sender {
+ if let Some(ref tx) = RESIZE_SENDER {
let _ = tx.send((width, height));
}
}
@@ -112,19 +112,20 @@ pub struct Rgb {
}
mod gl {
+ #![allow(non_upper_case_globals)]
include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}
fn main() {
// Load configuration
- let config = match Config::load() {
+ let (config, config_path) = match Config::load() {
Err(err) => match err {
// Use default config when not found
- config::Error::NotFound => Config::default(),
+ config::Error::NotFound => (Config::default(), None),
// Exit when there's a problem with it
_ => die!("{}", err),
},
- Ok(config) => config,
+ Ok((config, path)) => (config, Some(path)),
};
let font = config.font();
@@ -155,7 +156,7 @@ fn main() {
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);
// Create renderer
- let mut renderer = QuadRenderer::new(width, height);
+ let mut renderer = QuadRenderer::new(&config, width, height);
// Initialize glyph cache
let glyph_cache = {
@@ -180,7 +181,6 @@ fn main() {
println!("Cell Size: ({} x {})", cell_width, cell_height);
let terminal = Term::new(
- &config,
width as f32,
height as f32,
cell_width as f32,
@@ -190,7 +190,7 @@ fn main() {
let (tx, rx) = mpsc::channel();
unsafe {
- resize_sender = Some(tx.clone());
+ RESIZE_SENDER = Some(tx.clone());
}
let signal_flag = Flag::new(false);
@@ -214,7 +214,6 @@ fn main() {
window.clone(),
renderer,
glyph_cache,
- config.bg_color(),
render_timer,
rx
);
@@ -226,11 +225,25 @@ fn main() {
tx
);
+ let (config_tx, config_rx) = mpsc::channel();
+
+ // create a config watcher when config is loaded from disk
+ let _config_reloader = config_path.map(|config_path| {
+ config::Watcher::new(config_path, ConfigHandler {
+ tx: config_tx,
+ window: window.create_window_proxy(),
+ })
+ });
+
// Main loop
loop {
// Wait for something to happen
processor.process_events(&window);
+ if let Ok(config) = config_rx.try_recv() {
+ display.update_config(&config);
+ }
+
// Maybe draw the terminal
let terminal = terminal.lock();
signal_flag.set(false);
@@ -243,28 +256,49 @@ fn main() {
}
}
+ // FIXME need file watcher to work with custom delegates before
+ // joining config reloader is possible
+ // config_reloader.join().ok();
+
// shutdown
event_loop_handle.join().ok();
println!("Goodbye");
}
+struct ConfigHandler {
+ tx: mpsc::Sender<config::Config>,
+ window: ::glutin::WindowProxy,
+}
+
+impl config::OnConfigReload for ConfigHandler {
+ fn on_config_reload(&mut self, config: Config) {
+ if let Err(..) = self.tx.send(config) {
+ err_println!("Failed to notify of new config");
+ return;
+ }
+
+ self.window.wakeup_event_loop();
+ }
+}
+
struct Display {
window: Arc<glutin::Window>,
renderer: QuadRenderer,
glyph_cache: GlyphCache,
render_timer: bool,
- clear_red: f32,
- clear_blue: f32,
- clear_green: f32,
rx: mpsc::Receiver<(u32, u32)>,
meter: Meter,
}
impl Display {
+ pub fn update_config(&mut self, config: &Config) {
+ self.renderer.update_config(config);
+ self.render_timer = config.render_timer();
+ }
+
pub fn new(window: Arc<glutin::Window>,
renderer: QuadRenderer,
glyph_cache: GlyphCache,
- clear_color: Rgb,
render_timer: bool,
rx: mpsc::Receiver<(u32, u32)>)
-> Display
@@ -274,9 +308,6 @@ impl Display {
renderer: renderer,
glyph_cache: glyph_cache,
render_timer: render_timer,
- clear_red: clear_color.r as f32 / 255.0,
- clear_blue: clear_color.g as f32 / 255.0,
- clear_green: clear_color.b as f32 / 255.0,
rx: rx,
meter: Meter::new(),
}
@@ -295,11 +326,6 @@ impl Display {
// events into one.
let mut new_size = None;
- // TODO should be built into renderer
- unsafe {
- gl::ClearColor(self.clear_red, self.clear_blue, self.clear_green, 1.0);
- gl::Clear(gl::COLOR_BUFFER_BIT);
- }
// Check for any out-of-band resize events (mac only)
while let Ok(sz) = self.rx.try_recv() {
@@ -322,18 +348,16 @@ impl Display {
let size_info = terminal.size_info().clone();
self.renderer.with_api(&size_info, |mut api| {
// Draw the grid
- let bg = terminal.bg;
- api.render_grid(&bg, &terminal.render_grid(), glyph_cache);
+ api.render_grid(&terminal.render_grid(), glyph_cache);
});
}
// Draw render timer
if self.render_timer {
let timing = format!("{:.3} usec", self.meter.average());
- let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
+ let color = ::term::cell::Color::Rgb(Rgb { r: 0xd5, g: 0x4e, b: 0x53 });
self.renderer.with_api(terminal.size_info(), |mut api| {
- let bg = terminal.bg;
- api.render_string(&bg, &timing[..], glyph_cache, &color);
+ api.render_string(&timing[..], glyph_cache, &color);
});
}
}
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index f1b30373..4e23c0ed 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -17,8 +17,7 @@ use std::io::{self, Read};
use std::mem::size_of;
use std::path::{PathBuf};
use std::ptr;
-use std::sync::Arc;
-use std::sync::atomic::{Ordering, AtomicBool};
+use std::sync::mpsc;
use cgmath;
use font::{self, Rasterizer, RasterizedGlyph, FontDesc, GlyphKey, FontKey};
@@ -50,6 +49,10 @@ pub trait LoadGlyph {
fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph;
}
+enum Msg {
+ ShaderReload,
+}
+
/// Text drawing program
///
/// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".
@@ -70,7 +73,7 @@ pub struct ShaderProgram {
/// Background pass flag
///
/// Rendering is split into two passes; 1 for backgrounds, and one for text
- u_background: GLint
+ u_background: GLint,
}
@@ -201,6 +204,7 @@ impl GlyphCache {
}
#[derive(Debug)]
+#[repr(C)]
struct InstanceData {
// coords
col: f32,
@@ -230,7 +234,6 @@ struct InstanceData {
#[derive(Debug)]
pub struct QuadRenderer {
program: ShaderProgram,
- should_reload: Arc<AtomicBool>,
vao: GLuint,
vbo: GLuint,
ebo: GLuint,
@@ -238,6 +241,8 @@ pub struct QuadRenderer {
atlas: Vec<Atlas>,
active_tex: GLuint,
batch: Batch,
+ colors: [Rgb; 18],
+ rx: mpsc::Receiver<Msg>,
}
#[derive(Debug)]
@@ -246,6 +251,7 @@ pub struct RenderApi<'a> {
batch: &'a mut Batch,
atlas: &'a mut Vec<Atlas>,
program: &'a mut ShaderProgram,
+ colors: &'a [Rgb; 18],
}
#[derive(Debug)]
@@ -264,14 +270,16 @@ pub struct PackedVertex {
pub struct Batch {
tex: GLuint,
instances: Vec<InstanceData>,
+ colors: [Rgb; 18],
}
impl Batch {
#[inline]
- pub fn new() -> Batch {
+ pub fn new(colors: [Rgb; 18]) -> Batch {
Batch {
tex: 0,
instances: Vec::with_capacity(BATCH_MAX),
+ colors: colors,
}
}
@@ -280,6 +288,16 @@ impl Batch {
self.tex = glyph.tex_id;
}
+ let fg = match cell.fg {
+ ::term::cell::Color::Rgb(rgb) => rgb,
+ ::term::cell::Color::Ansi(ansi) => self.colors[ansi as usize],
+ };
+
+ let bg = match cell.bg {
+ ::term::cell::Color::Rgb(rgb) => rgb,
+ ::term::cell::Color::Ansi(ansi) => self.colors[ansi as usize],
+ };
+
let mut instance = InstanceData {
col: col,
row: row,
@@ -294,23 +312,23 @@ impl Batch {
uv_width: glyph.uv_width,
uv_height: glyph.uv_height,
- r: cell.fg.r as f32,
- g: cell.fg.g as f32,
- b: cell.fg.b as f32,
+ r: fg.r as f32,
+ g: fg.g as f32,
+ b: fg.b as f32,
- bg_r: cell.bg.r as f32,
- bg_g: cell.bg.g as f32,
- bg_b: cell.bg.b as f32,
+ bg_r: bg.r as f32,
+ bg_g: bg.g as f32,
+ bg_b: bg.b as f32,
};
if cell.flags.contains(cell::INVERSE) {
- instance.r = cell.bg.r as f32;
- instance.g = cell.bg.g as f32;
- instance.b = cell.bg.b as f32;
+ instance.r = bg.r as f32;
+ instance.g = bg.g as f32;
+ instance.b = bg.b as f32;
- instance.bg_r = cell.fg.r as f32;
- instance.bg_g = cell.fg.g as f32;
- instance.bg_b = cell.fg.b as f32;
+ instance.bg_r = fg.r as f32;
+ instance.bg_g = fg.g as f32;
+ instance.bg_b = fg.b as f32;
}
self.instances.push(instance);
@@ -353,7 +371,7 @@ const ATLAS_SIZE: i32 = 1024;
impl QuadRenderer {
// TODO should probably hand this a transform instead of width/height
- pub fn new(width: u32, height: u32) -> QuadRenderer {
+ pub fn new(config: &Config, width: u32, height: u32) -> QuadRenderer {
let program = ShaderProgram::new(width, height).unwrap();
let mut vao: GLuint = 0;
@@ -453,8 +471,7 @@ impl QuadRenderer {
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
}
- let should_reload = Arc::new(AtomicBool::new(false));
- let should_reload2 = should_reload.clone();
+ let (msg_tx, msg_rx) = mpsc::channel();
if cfg!(feature = "live-shader-reload") {
::std::thread::spawn(move || {
@@ -479,8 +496,8 @@ impl QuadRenderer {
}
}
- // This is last event we see after saving in vim
- should_reload2.store(true, Ordering::Relaxed);
+ msg_tx.send(Msg::ShaderReload)
+ .expect("msg send ok");
}
}
}
@@ -489,14 +506,15 @@ impl QuadRenderer {
let mut renderer = QuadRenderer {
program: program,
- should_reload: should_reload,
vao: vao,
vbo: vbo,
ebo: ebo,
vbo_instance: vbo_instance,
atlas: Vec::new(),
active_tex: 0,
- batch: Batch::new(),
+ batch: Batch::new(config.color_list()),
+ colors: config.color_list(),
+ rx: msg_rx,
};
let atlas = Atlas::new(ATLAS_SIZE);
@@ -505,11 +523,20 @@ impl QuadRenderer {
renderer
}
+ pub fn update_config(&mut self, config: &Config) {
+ self.colors = config.color_list();
+ self.batch.colors = config.color_list();
+ }
+
pub fn with_api<F, T>(&mut self, props: &term::SizeInfo, func: F) -> T
where F: FnOnce(RenderApi) -> T
{
- if self.should_reload.load(Ordering::Relaxed) {
- self.reload_shaders(props.width as u32, props.height as u32);
+ while let Ok(msg) = self.rx.try_recv() {
+ match msg {
+ Msg::ShaderReload => {
+ self.reload_shaders(props.width as u32, props.height as u32);
+ }
+ }
}
unsafe {
@@ -527,6 +554,7 @@ impl QuadRenderer {
batch: &mut self.batch,
atlas: &mut self.atlas,
program: &mut self.program,
+ colors: &self.colors,
});
unsafe {
@@ -554,7 +582,6 @@ impl QuadRenderer {
}
pub fn reload_shaders(&mut self, width: u32, height: u32) {
- self.should_reload.store(false, Ordering::Relaxed);
let program = match ShaderProgram::new(width, height) {
Ok(program) => program,
Err(err) => {
@@ -622,10 +649,9 @@ impl<'a> RenderApi<'a> {
/// optimization.
pub fn render_string(
&mut self,
- bg: &Rgb,
s: &str,
glyph_cache: &mut GlyphCache,
- color: &Rgb,
+ color: &::term::cell::Color,
) {
let row = 40.0;
let mut col = 100.0;
@@ -640,8 +666,8 @@ impl<'a> RenderApi<'a> {
if let Some(glyph) = glyph_cache.get(&glyph_key, self) {
let cell = Cell {
c: c,
- fg: *color,
- bg: *bg,
+ fg: color.clone(),
+ bg: cell::Color::Rgb(Rgb { r: 0, g: 0, b: 0}),
flags: cell::INVERSE,
};
self.add_render_item(row, col, &cell, glyph);
@@ -668,12 +694,27 @@ impl<'a> RenderApi<'a> {
}
}
- pub fn render_grid(&mut self, bg: &Rgb, grid: &Grid<Cell>, glyph_cache: &mut GlyphCache) {
+ pub fn render_grid(
+ &mut self,
+ grid: &Grid<Cell>,
+ glyph_cache: &mut GlyphCache
+ ) {
+ // TODO should be built into renderer
+ let color = self.colors[::ansi::Color::Background as usize];
+ unsafe {
+ gl::ClearColor(
+ color.r as f32 / 255.0,
+ color.g as f32 / 255.0,
+ color.b as f32 / 255.0,
+ 1.0
+ );
+ gl::Clear(gl::COLOR_BUFFER_BIT);
+ }
+
for (i, line) in grid.lines().enumerate() {
for (j, cell) in line.cells().enumerate() {
// Skip empty cells
- if cell.c == ' ' &&
- cell.bg == *bg &&
+ if cell.c == ' ' && cell.bg == cell::Color::Ansi(::ansi::Color::Background) &&
!cell.flags.contains(cell::INVERSE)
{
continue;
@@ -760,7 +801,10 @@ impl ShaderProgram {
}
}
- pub fn new(width: u32, height: u32) -> Result<ShaderProgram, ShaderCreationError> {
+ pub fn new(
+ width: u32,
+ height: u32
+ ) -> Result<ShaderProgram, ShaderCreationError> {
let vertex_source = if cfg!(feature = "live-shader-reload") {
None
} else {
@@ -815,6 +859,16 @@ impl ShaderProgram {
assert_uniform_valid!(projection, term_dim, cell_dim);
+ let mut color_uniforms: [GLint; 18] = unsafe { ::std::mem::uninitialized() };
+ for i in 0..18 {
+ color_uniforms[i] = unsafe {
+ let s = format!("colors[{}]\0", i).into_bytes();
+ gl::GetUniformLocation(program, cptr!(&s[..]))
+ };
+
+ assert_uniform_valid!(color_uniforms[i]);
+ }
+
let shader = ShaderProgram {
id: program,
u_projection: projection,
diff --git a/src/term.rs b/src/term.rs
index 898251d7..bcd78814 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -21,9 +21,7 @@ use ansi::{self, Attr, Handler};
use grid::{Grid, ClearRegion};
use index::{Cursor, Column, Line};
use tty;
-use config::Config;
-
-use ::Rgb;
+use ansi::Color;
/// RAII type which manages grid state for render
///
@@ -90,20 +88,26 @@ pub mod cell {
}
}
- #[derive(Clone, Debug, Copy)]
+ #[derive(Debug, Clone, PartialEq, Eq)]
+ pub enum Color {
+ Rgb(Rgb),
+ Ansi(::ansi::Color),
+ }
+
+ #[derive(Clone, Debug)]
pub struct Cell {
pub c: char,
- pub fg: Rgb,
- pub bg: Rgb,
+ pub fg: Color,
+ pub bg: Color,
pub flags: Flags,
}
impl Cell {
- pub fn new(c: char) -> Cell {
+ pub fn new(c: char, fg: Color, bg: Color) -> Cell {
Cell {
c: c.into(),
- bg: Default::default(),
- fg: Default::default(),
+ bg: bg,
+ fg: fg,
flags: Flags::empty(),
}
}
@@ -111,12 +115,41 @@ pub mod cell {
#[inline]
pub fn reset(&mut self, template: &Cell) {
// memcpy template to self
+ *self = template.clone();
+ }
+ }
+
+ #[cfg(test)]
+ mod tests {
+ use super::Color;
+ use std::mem;
+
+ // Ensure memory layout is well defined so components like renderer
+ // can exploit it.
+ //
+ // Thankfully, everything is just a u8 for now so no endianness
+ // considerations are needed.
+ #[test]
+ fn color_memory_layout() {
+ let rgb_color = Color::Rgb(::Rgb { r: 1, g: 2, b: 3 });
+ let ansi_color = Color::Ansi(::ansi::Color::Foreground);
+
unsafe {
- ::std::ptr::copy_nonoverlapping(
- template as *const Cell,
- self as *mut Cell,
- 1
- );
+ // Color::Rgb
+ // [discriminant(0), red, green ,blue]
+ let bytes: [u8; 4] = mem::transmute_copy(&rgb_color);
+ assert_eq!(bytes[0], 0);
+ assert_eq!(bytes[1], 1);
+ assert_eq!(bytes[2], 2);
+ assert_eq!(bytes[3], 3);
+
+ // Color::Ansi
+ // [discriminant(1), ansi::Color, 0, 0]
+ let bytes: [u8; 4] = mem::transmute_copy(&ansi_color);
+ assert_eq!(bytes[0], 1);
+ assert_eq!(bytes[1], ::ansi::Color::Foreground as u8);
+ assert_eq!(bytes[2], 0);
+ assert_eq!(bytes[3], 0);
}
}
}
@@ -165,12 +198,6 @@ pub struct Term {
/// Alt cursor
alt_cursor: Cursor,
- /// Active foreground color
- pub fg: Rgb,
-
- /// Active background color
- pub bg: Rgb,
-
/// Tabstops
tabs: Vec<bool>,
@@ -189,9 +216,6 @@ pub struct Term {
/// Empty cell
empty_cell: Cell,
- /// Text colors
- colors: [Rgb; 16],
-
pub dirty: bool,
}
@@ -225,7 +249,6 @@ impl SizeInfo {
impl Term {
pub fn new(
- config: &Config,
width: f32,
height: f32,
cell_width: f32,
@@ -238,20 +261,18 @@ impl Term {
cell_height: cell_height as f32,
};
- let mut template = Cell::new(' ');
- template.flags = cell::Flags::empty();
- template.bg = config.bg_color();
- template.fg = config.fg_color();
+ let template = Cell::new(
+ ' ',
+ cell::Color::Ansi(Color::Foreground),
+ cell::Color::Ansi(Color::Background)
+ );
let num_cols = size.cols();
let num_lines = size.lines();
println!("num_cols, num_lines = {}, {}", num_cols, num_lines);
- println!("bg: {:?}, fg: {:?}", template.bg, template.fg);
- println!("colors: {:?}", config.color_list());
-
- let grid = Grid::new(num_lines, num_cols, &Cell::new(' '));
+ let grid = Grid::new(num_lines, num_cols, &template);
let tty = tty::new(*num_lines as u8, *num_cols as u8);
tty.resize(*num_lines as usize, *num_cols as usize, size.width as usize, size.height as usize);
@@ -272,16 +293,13 @@ impl Term {
alt: false,
cursor: Cursor::default(),
alt_cursor: Cursor::default(),
- fg: config.fg_color(),
- bg: config.bg_color(),
tty: tty,
tabs: tabs,
mode: Default::default(),
scroll_region: scroll_region,
size_info: size,
- template_cell: template,
+ template_cell: template.clone(),
empty_cell: template,
- colors: config.color_list(),
}
}
@@ -323,8 +341,9 @@ impl Term {
println!("num_cols, num_lines = {}, {}", num_cols, num_lines);
// Resize grids to new size
- self.grid.resize(num_lines, num_cols, &Cell::new(' '));
- self.alt_grid.resize(num_lines, num_cols, &Cell::new(' '));
+ let template = self.template_cell.clone();
+ self.grid.resize(num_lines, num_cols, &template);
+ self.alt_grid.resize(num_lines, num_cols, &template);
// Ensure cursor is in-bounds
self.cursor.line = limit(self.cursor.line, Line(0), num_lines);
@@ -462,7 +481,7 @@ impl ansi::Handler for Term {
}
let cell = &mut self.grid[&self.cursor];
- *cell = self.template_cell;
+ *cell = self.template_cell.clone();
cell.c = c;
self.cursor.col += 1;
}
@@ -779,27 +798,21 @@ impl ansi::Handler for Term {
fn terminal_attribute(&mut self, attr: Attr) {
debug_println!("Set Attribute: {:?}", attr);
match attr {
- Attr::DefaultForeground => {
- self.template_cell.fg = self.fg;
- },
- Attr::DefaultBackground => {
- self.template_cell.bg = self.bg;
- },
Attr::Foreground(named_color) => {
- self.template_cell.fg = self.colors[named_color as usize];
+ self.template_cell.fg = cell::Color::Ansi(named_color);
},
Attr::Background(named_color) => {
- self.template_cell.bg = self.colors[named_color as usize];
+ self.template_cell.bg = cell::Color::Ansi(named_color);
},
Attr::ForegroundSpec(rgb) => {
- self.template_cell.fg = rgb;
+ self.template_cell.fg = cell::Color::Rgb(rgb);
},
Attr::BackgroundSpec(rgb) => {
- self.template_cell.bg = rgb;
+ self.template_cell.bg = cell::Color::Rgb(rgb);
},
Attr::Reset => {
- self.template_cell.fg = self.fg;
- self.template_cell.bg = self.bg;
+ self.template_cell.fg = cell::Color::Ansi(Color::Foreground);
+ self.template_cell.bg = cell::Color::Ansi(Color::Background);
self.template_cell.flags = cell::Flags::empty();
},
Attr::Reverse => self.template_cell.flags.insert(cell::INVERSE),