mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-25 14:05:41 -05:00
Make colors configurable from file
Added solarized dark color scheme for testing purposes. Resolves #1.
This commit is contained in:
parent
71de5501c4
commit
d4c1d51e36
5 changed files with 300 additions and 105 deletions
|
@ -7,47 +7,78 @@ dpi:
|
||||||
|
|
||||||
# Font configuration
|
# Font configuration
|
||||||
font:
|
font:
|
||||||
family: DejaVu Sans Mono
|
family: Menlo
|
||||||
style: Book
|
style: Regular
|
||||||
|
bold_style: Bold
|
||||||
|
italic_style: Italic
|
||||||
# Point size of the font
|
# Point size of the font
|
||||||
size: 11.0
|
size: 11.0
|
||||||
# Offset is the extra space around each character. offset.y can be thought of
|
# Offset is the extra space around each character. offset.y can be thought of
|
||||||
# as modifying the linespacing, and offset.x as modifying the letter spacing.
|
# as modifying the linespacing, and offset.x as modifying the letter spacing.
|
||||||
offset:
|
offset:
|
||||||
x: 2.0
|
x: -1.0
|
||||||
y: -7.0
|
y: 1.0
|
||||||
|
|
||||||
# Should display the render timer
|
# Should display the render timer
|
||||||
render_timer: false
|
render_timer: false
|
||||||
|
|
||||||
# Colors
|
# Colors (Tomorrow Night Bright)
|
||||||
colors:
|
colors:
|
||||||
# Default colors
|
# Default colors
|
||||||
default:
|
primary:
|
||||||
background: 0x000000
|
background: '0x000000'
|
||||||
foreground: 0xeaeaea
|
foreground: '0xeaeaea'
|
||||||
|
|
||||||
# Normal colors
|
# Normal colors
|
||||||
normal:
|
normal:
|
||||||
black: 0x000000
|
black: '0x000000'
|
||||||
red: 0xd54e53
|
red: '0xd54e53'
|
||||||
green: 0xb9ca4a
|
green: '0xb9ca4a'
|
||||||
yellow: 0xe6c547
|
yellow: '0xe6c547'
|
||||||
blue: 0x7aa6da
|
blue: '0x7aa6da'
|
||||||
magenta: 0xc397d8
|
magenta: '0xc397d8'
|
||||||
cyan: 0x70c0ba
|
cyan: '0x70c0ba'
|
||||||
white: 0x424242
|
white: '0x424242'
|
||||||
|
|
||||||
# Bright colors
|
# Bright colors
|
||||||
bright:
|
bright:
|
||||||
black: 0x666666
|
black: '0x666666'
|
||||||
red: 0xff3334
|
red: '0xff3334'
|
||||||
green: 0x9ec400
|
green: '0x9ec400'
|
||||||
yellow: 0xe7c547
|
yellow: '0xe7c547'
|
||||||
blue: 0x7aa6da
|
blue: '0x7aa6da'
|
||||||
magenta: 0xb77ee0
|
magenta: '0xb77ee0'
|
||||||
cyan: 0x54ced6
|
cyan: '0x54ced6'
|
||||||
white: 0x2a2a2a
|
white: '0x2a2a2a'
|
||||||
|
|
||||||
# Display tabs using this many cells
|
# Display tabs using this many cells
|
||||||
tabspaces: 8
|
tabspaces: 8
|
||||||
|
|
||||||
|
# Colors (Solarized Dark)
|
||||||
|
# colors:
|
||||||
|
# # Default colors
|
||||||
|
# primary:
|
||||||
|
# background: '0x002b36'
|
||||||
|
# foreground: '0x839496'
|
||||||
|
#
|
||||||
|
# # Normal colors
|
||||||
|
# normal:
|
||||||
|
# black: '0x073642'
|
||||||
|
# red: '0xdc322f'
|
||||||
|
# green: '0x859900'
|
||||||
|
# yellow: '0xb58900'
|
||||||
|
# blue: '0x268bd2'
|
||||||
|
# magenta: '0xd33682'
|
||||||
|
# cyan: '0x2aa198'
|
||||||
|
# white: '0xeee8d5'
|
||||||
|
#
|
||||||
|
# # Bright colors
|
||||||
|
# bright:
|
||||||
|
# black: '0x002b36'
|
||||||
|
# red: '0xcb4b16'
|
||||||
|
# green: '0x586e75'
|
||||||
|
# yellow: '0x657b83'
|
||||||
|
# blue: '0x839496'
|
||||||
|
# magenta: '0x6c71c4'
|
||||||
|
# cyan: '0x93a1a1'
|
||||||
|
# white: '0xfdf6e3'
|
||||||
|
|
163
src/config.rs
163
src/config.rs
|
@ -8,9 +8,10 @@ use std::fs;
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use ::Rgb;
|
||||||
use font::Size;
|
use font::Size;
|
||||||
use serde_yaml;
|
use serde_yaml;
|
||||||
use serde;
|
use serde::{self, Error as SerdeError};
|
||||||
|
|
||||||
/// Top-level config type
|
/// Top-level config type
|
||||||
#[derive(Debug, Deserialize, Default)]
|
#[derive(Debug, Deserialize, Default)]
|
||||||
|
@ -26,6 +27,10 @@ pub struct Config {
|
||||||
/// Should show render timer
|
/// Should show render timer
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
render_timer: bool,
|
render_timer: bool,
|
||||||
|
|
||||||
|
/// The standard ANSI colors to use
|
||||||
|
#[serde(default)]
|
||||||
|
colors: Colors,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors occurring during config loading
|
/// Errors occurring during config loading
|
||||||
|
@ -44,6 +49,124 @@ pub enum Error {
|
||||||
Yaml(serde_yaml::Error),
|
Yaml(serde_yaml::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Colors {
|
||||||
|
primary: PrimaryColors,
|
||||||
|
normal: AnsiColors,
|
||||||
|
bright: AnsiColors,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct PrimaryColors {
|
||||||
|
background: Rgb,
|
||||||
|
foreground: Rgb,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Colors {
|
||||||
|
fn default() -> Colors {
|
||||||
|
Colors {
|
||||||
|
primary: PrimaryColors {
|
||||||
|
background: Rgb { r: 0, g: 0, b: 0 },
|
||||||
|
foreground: Rgb { r: 0xea, g: 0xea, b: 0xea },
|
||||||
|
},
|
||||||
|
normal: AnsiColors {
|
||||||
|
black: Rgb {r: 0x00, g: 0x00, b: 0x00},
|
||||||
|
red: Rgb {r: 0xd5, g: 0x4e, b: 0x53},
|
||||||
|
green: Rgb {r: 0xb9, g: 0xca, b: 0x4a},
|
||||||
|
yellow: Rgb {r: 0xe6, g: 0xc5, b: 0x47},
|
||||||
|
blue: Rgb {r: 0x7a, g: 0xa6, b: 0xda},
|
||||||
|
magenta: Rgb {r: 0xc3, g: 0x97, b: 0xd8},
|
||||||
|
cyan: Rgb {r: 0x70, g: 0xc0, b: 0xba},
|
||||||
|
white: Rgb {r: 0x42, g: 0x42, b: 0x42},
|
||||||
|
},
|
||||||
|
bright: AnsiColors {
|
||||||
|
black: Rgb {r: 0x66, g: 0x66, b: 0x66},
|
||||||
|
red: Rgb {r: 0xff, g: 0x33, b: 0x34},
|
||||||
|
green: Rgb {r: 0x9e, g: 0xc4, b: 0x00},
|
||||||
|
yellow: Rgb {r: 0xe7, g: 0xc5, b: 0x47},
|
||||||
|
blue: Rgb {r: 0x7a, g: 0xa6, b: 0xda},
|
||||||
|
magenta: Rgb {r: 0xb7, g: 0x7e, b: 0xe0},
|
||||||
|
cyan: Rgb {r: 0x54, g: 0xce, b: 0xd6},
|
||||||
|
white: Rgb {r: 0x2a, g: 0x2a, b: 0x2a},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The normal or bright colors section of config
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct AnsiColors {
|
||||||
|
black: Rgb,
|
||||||
|
red: Rgb,
|
||||||
|
green: Rgb,
|
||||||
|
yellow: Rgb,
|
||||||
|
blue: Rgb,
|
||||||
|
magenta: Rgb,
|
||||||
|
cyan: Rgb,
|
||||||
|
white: Rgb,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl serde::de::Deserialize for Rgb {
|
||||||
|
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<Self, D::Error>
|
||||||
|
where D: serde::de::Deserializer
|
||||||
|
{
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct StringVisitor<__D> {
|
||||||
|
_marker: PhantomData<__D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<__D> ::serde::de::Visitor for StringVisitor<__D>
|
||||||
|
where __D: ::serde::de::Deserializer
|
||||||
|
{
|
||||||
|
type Value = String;
|
||||||
|
|
||||||
|
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<Self::Value, E>
|
||||||
|
where E: ::serde::de::Error
|
||||||
|
{
|
||||||
|
Ok(value.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer
|
||||||
|
.deserialize_f64(StringVisitor::<D>{ _marker: PhantomData })
|
||||||
|
.and_then(|v| {
|
||||||
|
Rgb::from_str(&v[..])
|
||||||
|
.map_err(|_| D::Error::custom("failed to parse rgb; expect 0xrrggbb"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rgb {
|
||||||
|
fn from_str(s: &str) -> ::std::result::Result<Rgb, ()> {
|
||||||
|
let mut chars = s.chars();
|
||||||
|
let mut rgb = Rgb::default();
|
||||||
|
|
||||||
|
macro_rules! component {
|
||||||
|
($($c:ident),*) => {
|
||||||
|
$(
|
||||||
|
match chars.next().unwrap().to_digit(16) {
|
||||||
|
Some(val) => rgb.$c = (val as u8) << 4,
|
||||||
|
None => return Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
match chars.next().unwrap().to_digit(16) {
|
||||||
|
Some(val) => rgb.$c |= val as u8,
|
||||||
|
None => return Err(())
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if chars.next().unwrap() != '0' { return Err(()); }
|
||||||
|
if chars.next().unwrap() != 'x' { return Err(()); }
|
||||||
|
|
||||||
|
component!(r, g, b);
|
||||||
|
|
||||||
|
Ok(rgb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ::std::error::Error for Error {
|
impl ::std::error::Error for Error {
|
||||||
fn cause(&self) -> Option<&::std::error::Error> {
|
fn cause(&self) -> Option<&::std::error::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -132,6 +255,44 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get list of colors
|
||||||
|
///
|
||||||
|
/// 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] {
|
||||||
|
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,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fg_color(&self) -> Rgb {
|
||||||
|
self.colors.primary.foreground
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bg_color(&self) -> Rgb {
|
||||||
|
self.colors.primary.background
|
||||||
|
}
|
||||||
|
|
||||||
/// Get font config
|
/// Get font config
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn font(&self) -> &Font {
|
pub fn font(&self) -> &Font {
|
||||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -179,7 +179,13 @@ fn main() {
|
||||||
|
|
||||||
println!("Cell Size: ({} x {})", cell_width, cell_height);
|
println!("Cell Size: ({} x {})", cell_width, cell_height);
|
||||||
|
|
||||||
let terminal = Term::new(width as f32, height as f32, cell_width as f32, cell_height as f32);
|
let terminal = Term::new(
|
||||||
|
&config,
|
||||||
|
width as f32,
|
||||||
|
height as f32,
|
||||||
|
cell_width as f32,
|
||||||
|
cell_height as f32
|
||||||
|
);
|
||||||
let pty_io = terminal.tty().reader();
|
let pty_io = terminal.tty().reader();
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
@ -208,6 +214,7 @@ fn main() {
|
||||||
window.clone(),
|
window.clone(),
|
||||||
renderer,
|
renderer,
|
||||||
glyph_cache,
|
glyph_cache,
|
||||||
|
config.bg_color(),
|
||||||
render_timer,
|
render_timer,
|
||||||
rx
|
rx
|
||||||
);
|
);
|
||||||
|
@ -241,13 +248,14 @@ fn main() {
|
||||||
println!("Goodbye");
|
println!("Goodbye");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Display {
|
struct Display {
|
||||||
window: Arc<glutin::Window>,
|
window: Arc<glutin::Window>,
|
||||||
renderer: QuadRenderer,
|
renderer: QuadRenderer,
|
||||||
glyph_cache: GlyphCache,
|
glyph_cache: GlyphCache,
|
||||||
render_timer: bool,
|
render_timer: bool,
|
||||||
|
clear_red: f32,
|
||||||
|
clear_blue: f32,
|
||||||
|
clear_green: f32,
|
||||||
rx: mpsc::Receiver<(u32, u32)>,
|
rx: mpsc::Receiver<(u32, u32)>,
|
||||||
meter: Meter,
|
meter: Meter,
|
||||||
}
|
}
|
||||||
|
@ -256,6 +264,7 @@ impl Display {
|
||||||
pub fn new(window: Arc<glutin::Window>,
|
pub fn new(window: Arc<glutin::Window>,
|
||||||
renderer: QuadRenderer,
|
renderer: QuadRenderer,
|
||||||
glyph_cache: GlyphCache,
|
glyph_cache: GlyphCache,
|
||||||
|
clear_color: Rgb,
|
||||||
render_timer: bool,
|
render_timer: bool,
|
||||||
rx: mpsc::Receiver<(u32, u32)>)
|
rx: mpsc::Receiver<(u32, u32)>)
|
||||||
-> Display
|
-> Display
|
||||||
|
@ -265,6 +274,9 @@ impl Display {
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
glyph_cache: glyph_cache,
|
glyph_cache: glyph_cache,
|
||||||
render_timer: render_timer,
|
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,
|
rx: rx,
|
||||||
meter: Meter::new(),
|
meter: Meter::new(),
|
||||||
}
|
}
|
||||||
|
@ -285,7 +297,7 @@ impl Display {
|
||||||
|
|
||||||
// TODO should be built into renderer
|
// TODO should be built into renderer
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::ClearColor(0.0, 0.0, 0.00, 1.0);
|
gl::ClearColor(self.clear_red, self.clear_blue, self.clear_green, 1.0);
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +322,8 @@ impl Display {
|
||||||
let size_info = terminal.size_info().clone();
|
let size_info = terminal.size_info().clone();
|
||||||
self.renderer.with_api(&size_info, |mut api| {
|
self.renderer.with_api(&size_info, |mut api| {
|
||||||
// Draw the grid
|
// Draw the grid
|
||||||
api.render_grid(&terminal.render_grid(), glyph_cache);
|
let bg = terminal.bg;
|
||||||
|
api.render_grid(&bg, &terminal.render_grid(), glyph_cache);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +332,8 @@ impl Display {
|
||||||
let timing = format!("{:.3} usec", self.meter.average());
|
let timing = format!("{:.3} usec", self.meter.average());
|
||||||
let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
|
let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
|
||||||
self.renderer.with_api(terminal.size_info(), |mut api| {
|
self.renderer.with_api(terminal.size_info(), |mut api| {
|
||||||
api.render_string(&timing[..], glyph_cache, &color);
|
let bg = terminal.bg;
|
||||||
|
api.render_string(&bg, &timing[..], glyph_cache, &color);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,11 +610,13 @@ impl<'a> RenderApi<'a> {
|
||||||
}
|
}
|
||||||
/// Render a string in a predefined location. Used for printing render time for profiling and
|
/// Render a string in a predefined location. Used for printing render time for profiling and
|
||||||
/// optimization.
|
/// optimization.
|
||||||
pub fn render_string(&mut self,
|
pub fn render_string(
|
||||||
|
&mut self,
|
||||||
|
bg: &Rgb,
|
||||||
s: &str,
|
s: &str,
|
||||||
glyph_cache: &mut GlyphCache,
|
glyph_cache: &mut GlyphCache,
|
||||||
color: &Rgb)
|
color: &Rgb,
|
||||||
{
|
) {
|
||||||
let row = 40.0;
|
let row = 40.0;
|
||||||
let mut col = 100.0;
|
let mut col = 100.0;
|
||||||
|
|
||||||
|
@ -629,7 +631,7 @@ impl<'a> RenderApi<'a> {
|
||||||
let cell = Cell {
|
let cell = Cell {
|
||||||
c: c,
|
c: c,
|
||||||
fg: *color,
|
fg: *color,
|
||||||
bg: term::DEFAULT_BG,
|
bg: *bg,
|
||||||
flags: cell::INVERSE,
|
flags: cell::INVERSE,
|
||||||
};
|
};
|
||||||
self.add_render_item(row, col, &cell, glyph);
|
self.add_render_item(row, col, &cell, glyph);
|
||||||
|
@ -656,12 +658,12 @@ impl<'a> RenderApi<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_grid(&mut self, grid: &Grid<Cell>, glyph_cache: &mut GlyphCache) {
|
pub fn render_grid(&mut self, bg: &Rgb, grid: &Grid<Cell>, glyph_cache: &mut GlyphCache) {
|
||||||
for (i, line) in grid.lines().enumerate() {
|
for (i, line) in grid.lines().enumerate() {
|
||||||
for (j, cell) in line.cells().enumerate() {
|
for (j, cell) in line.cells().enumerate() {
|
||||||
// Skip empty cells
|
// Skip empty cells
|
||||||
if cell.c == ' ' &&
|
if cell.c == ' ' &&
|
||||||
cell.bg == term::DEFAULT_BG &&
|
cell.bg == *bg &&
|
||||||
!cell.flags.contains(cell::INVERSE)
|
!cell.flags.contains(cell::INVERSE)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
119
src/term.rs
119
src/term.rs
|
@ -21,6 +21,7 @@ use ansi::{self, Attr, Handler};
|
||||||
use grid::{Grid, ClearRegion};
|
use grid::{Grid, ClearRegion};
|
||||||
use index::{Cursor, Column, Line};
|
use index::{Cursor, Column, Line};
|
||||||
use tty;
|
use tty;
|
||||||
|
use config::Config;
|
||||||
|
|
||||||
use ::Rgb;
|
use ::Rgb;
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ pub mod cell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Copy)]
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
pub c: char,
|
pub c: char,
|
||||||
pub fg: Rgb,
|
pub fg: Rgb,
|
||||||
|
@ -123,28 +124,6 @@ pub mod cell {
|
||||||
|
|
||||||
pub use self::cell::Cell;
|
pub use self::cell::Cell;
|
||||||
|
|
||||||
/// tomorrow night bright
|
|
||||||
///
|
|
||||||
/// because contrast
|
|
||||||
pub static COLORS: &'static [Rgb] = &[
|
|
||||||
Rgb {r: 0x00, g: 0x00, b: 0x00}, // Black
|
|
||||||
Rgb {r: 0xd5, g: 0x4e, b: 0x53}, // Red
|
|
||||||
Rgb {r: 0xb9, g: 0xca, b: 0x4a}, // Green
|
|
||||||
Rgb {r: 0xe6, g: 0xc5, b: 0x47}, // Yellow
|
|
||||||
Rgb {r: 0x7a, g: 0xa6, b: 0xda}, // Blue
|
|
||||||
Rgb {r: 0xc3, g: 0x97, b: 0xd8}, // Magenta
|
|
||||||
Rgb {r: 0x70, g: 0xc0, b: 0xba}, // Cyan
|
|
||||||
Rgb {r: 0x42, g: 0x42, b: 0x42}, // White
|
|
||||||
Rgb {r: 0x66, g: 0x66, b: 0x66}, // Bright black
|
|
||||||
Rgb {r: 0xff, g: 0x33, b: 0x34}, // Bright red
|
|
||||||
Rgb {r: 0x9e, g: 0xc4, b: 0x00}, // Bright green
|
|
||||||
Rgb {r: 0xe7, g: 0xc5, b: 0x47}, // Bright yellow
|
|
||||||
Rgb {r: 0x7a, g: 0xa6, b: 0xda}, // Bright blue
|
|
||||||
Rgb {r: 0xb7, g: 0x7e, b: 0xe0}, // Bright magenta
|
|
||||||
Rgb {r: 0x54, g: 0xce, b: 0xd6}, // Bright cyan
|
|
||||||
Rgb {r: 0x2a, g: 0x2a, b: 0x2a}, // Bright white
|
|
||||||
];
|
|
||||||
|
|
||||||
pub mod mode {
|
pub mod mode {
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub flags TermMode: u8 {
|
pub flags TermMode: u8 {
|
||||||
|
@ -165,8 +144,6 @@ pub mod mode {
|
||||||
|
|
||||||
pub use self::mode::TermMode;
|
pub use self::mode::TermMode;
|
||||||
|
|
||||||
pub const DEFAULT_FG: Rgb = Rgb { r: 0xea, g: 0xea, b: 0xea};
|
|
||||||
pub const DEFAULT_BG: Rgb = Rgb { r: 0, g: 0, b: 0};
|
|
||||||
pub const TAB_SPACES: usize = 8;
|
pub const TAB_SPACES: usize = 8;
|
||||||
|
|
||||||
pub struct Term {
|
pub struct Term {
|
||||||
|
@ -189,17 +166,14 @@ pub struct Term {
|
||||||
alt_cursor: Cursor,
|
alt_cursor: Cursor,
|
||||||
|
|
||||||
/// Active foreground color
|
/// Active foreground color
|
||||||
fg: Rgb,
|
pub fg: Rgb,
|
||||||
|
|
||||||
/// Active background color
|
/// Active background color
|
||||||
bg: Rgb,
|
pub bg: Rgb,
|
||||||
|
|
||||||
/// Tabstops
|
/// Tabstops
|
||||||
tabs: Vec<bool>,
|
tabs: Vec<bool>,
|
||||||
|
|
||||||
/// Cell attributes
|
|
||||||
attr: cell::Flags,
|
|
||||||
|
|
||||||
/// Mode flags
|
/// Mode flags
|
||||||
mode: TermMode,
|
mode: TermMode,
|
||||||
|
|
||||||
|
@ -212,6 +186,12 @@ pub struct Term {
|
||||||
/// Template cell
|
/// Template cell
|
||||||
template_cell: Cell,
|
template_cell: Cell,
|
||||||
|
|
||||||
|
/// Empty cell
|
||||||
|
empty_cell: Cell,
|
||||||
|
|
||||||
|
/// Text colors
|
||||||
|
colors: [Rgb; 16],
|
||||||
|
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +224,13 @@ impl SizeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Term {
|
impl Term {
|
||||||
pub fn new(width: f32, height: f32, cell_width: f32, cell_height: f32) -> Term {
|
pub fn new(
|
||||||
|
config: &Config,
|
||||||
|
width: f32,
|
||||||
|
height: f32,
|
||||||
|
cell_width: f32,
|
||||||
|
cell_height: f32
|
||||||
|
) -> Term {
|
||||||
let size = SizeInfo {
|
let size = SizeInfo {
|
||||||
width: width as f32,
|
width: width as f32,
|
||||||
height: height as f32,
|
height: height as f32,
|
||||||
|
@ -252,17 +238,19 @@ impl Term {
|
||||||
cell_height: cell_height as f32,
|
cell_height: cell_height as f32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let mut template = Cell::new(' ');
|
let mut template = Cell::new(' ');
|
||||||
template.flags = cell::Flags::empty();
|
template.flags = cell::Flags::empty();
|
||||||
template.bg = DEFAULT_BG;
|
template.bg = config.bg_color();
|
||||||
template.fg = DEFAULT_FG;
|
template.fg = config.fg_color();
|
||||||
|
|
||||||
let num_cols = size.cols();
|
let num_cols = size.cols();
|
||||||
let num_lines = size.lines();
|
let num_lines = size.lines();
|
||||||
|
|
||||||
println!("num_cols, num_lines = {}, {}", num_cols, num_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, &Cell::new(' '));
|
||||||
|
|
||||||
let tty = tty::new(*num_lines as u8, *num_cols as u8);
|
let tty = tty::new(*num_lines as u8, *num_cols as u8);
|
||||||
|
@ -284,15 +272,16 @@ impl Term {
|
||||||
alt: false,
|
alt: false,
|
||||||
cursor: Cursor::default(),
|
cursor: Cursor::default(),
|
||||||
alt_cursor: Cursor::default(),
|
alt_cursor: Cursor::default(),
|
||||||
fg: DEFAULT_FG,
|
fg: config.fg_color(),
|
||||||
bg: DEFAULT_BG,
|
bg: config.bg_color(),
|
||||||
tty: tty,
|
tty: tty,
|
||||||
tabs: tabs,
|
tabs: tabs,
|
||||||
attr: cell::Flags::empty(),
|
|
||||||
mode: Default::default(),
|
mode: Default::default(),
|
||||||
scroll_region: scroll_region,
|
scroll_region: scroll_region,
|
||||||
size_info: size,
|
size_info: size,
|
||||||
template_cell: template,
|
template_cell: template,
|
||||||
|
empty_cell: template,
|
||||||
|
colors: config.color_list(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +337,7 @@ impl Term {
|
||||||
self.tabs[0] = false;
|
self.tabs[0] = false;
|
||||||
|
|
||||||
// Make sure bottom of terminal is clear
|
// Make sure bottom of terminal is clear
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
self.grid.clear_region((self.cursor.line).., |c| c.reset(&template));
|
self.grid.clear_region((self.cursor.line).., |c| c.reset(&template));
|
||||||
self.alt_grid.clear_region((self.cursor.line).., |c| c.reset(&template));
|
self.alt_grid.clear_region((self.cursor.line).., |c| c.reset(&template));
|
||||||
|
|
||||||
|
@ -384,7 +373,7 @@ impl Term {
|
||||||
::std::mem::swap(&mut self.cursor, &mut self.alt_cursor);
|
::std::mem::swap(&mut self.cursor, &mut self.alt_cursor);
|
||||||
|
|
||||||
if self.alt {
|
if self.alt {
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
self.grid.clear(|c| c.reset(&template));
|
self.grid.clear(|c| c.reset(&template));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,7 +386,7 @@ impl Term {
|
||||||
debug_println!("scroll_down: {}", lines);
|
debug_println!("scroll_down: {}", lines);
|
||||||
|
|
||||||
// Copy of cell template; can't have it borrowed when calling clear/scroll
|
// Copy of cell template; can't have it borrowed when calling clear/scroll
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
|
|
||||||
// Clear `lines` lines at bottom of area
|
// Clear `lines` lines at bottom of area
|
||||||
{
|
{
|
||||||
|
@ -422,7 +411,7 @@ impl Term {
|
||||||
debug_println!("scroll_up: {}", lines);
|
debug_println!("scroll_up: {}", lines);
|
||||||
|
|
||||||
// Copy of cell template; can't have it borrowed when calling clear/scroll
|
// Copy of cell template; can't have it borrowed when calling clear/scroll
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
|
|
||||||
// Clear `lines` lines starting from origin to origin + lines
|
// Clear `lines` lines starting from origin to origin + lines
|
||||||
{
|
{
|
||||||
|
@ -473,10 +462,8 @@ impl ansi::Handler for Term {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cell = &mut self.grid[&self.cursor];
|
let cell = &mut self.grid[&self.cursor];
|
||||||
|
*cell = self.template_cell;
|
||||||
cell.c = c;
|
cell.c = c;
|
||||||
cell.fg = self.fg;
|
|
||||||
cell.bg = self.bg;
|
|
||||||
cell.flags = self.attr;
|
|
||||||
self.cursor.col += 1;
|
self.cursor.col += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +507,7 @@ impl ansi::Handler for Term {
|
||||||
|
|
||||||
// Cells were just moved out towards the end of the line; fill in
|
// Cells were just moved out towards the end of the line; fill in
|
||||||
// between source and dest with blanks.
|
// between source and dest with blanks.
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
for c in &mut line[source..destination] {
|
for c in &mut line[source..destination] {
|
||||||
c.reset(&template);
|
c.reset(&template);
|
||||||
}
|
}
|
||||||
|
@ -666,7 +653,7 @@ impl ansi::Handler for Term {
|
||||||
let end = start + count;
|
let end = start + count;
|
||||||
|
|
||||||
let row = &mut self.grid[self.cursor.line];
|
let row = &mut self.grid[self.cursor.line];
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
for c in &mut row[start..end] {
|
for c in &mut row[start..end] {
|
||||||
c.reset(&template);
|
c.reset(&template);
|
||||||
}
|
}
|
||||||
|
@ -692,7 +679,7 @@ impl ansi::Handler for Term {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear last `count` cells in line. If deleting 1 char, need to delete 1 cell.
|
// Clear last `count` cells in line. If deleting 1 char, need to delete 1 cell.
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
let end = self.size_info.cols() - count;
|
let end = self.size_info.cols() - count;
|
||||||
for c in &mut line[end..] {
|
for c in &mut line[end..] {
|
||||||
c.reset(&template);
|
c.reset(&template);
|
||||||
|
@ -722,7 +709,7 @@ impl ansi::Handler for Term {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clear_line(&mut self, mode: ansi::LineClearMode) {
|
fn clear_line(&mut self, mode: ansi::LineClearMode) {
|
||||||
debug_println!("clear_line: {:?}", mode);
|
debug_println!("clear_line: {:?}", mode);
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
match mode {
|
match mode {
|
||||||
ansi::LineClearMode::Right => {
|
ansi::LineClearMode::Right => {
|
||||||
let row = &mut self.grid[self.cursor.line];
|
let row = &mut self.grid[self.cursor.line];
|
||||||
|
@ -748,7 +735,7 @@ impl ansi::Handler for Term {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clear_screen(&mut self, mode: ansi::ClearMode) {
|
fn clear_screen(&mut self, mode: ansi::ClearMode) {
|
||||||
debug_println!("clear_screen: {:?}", mode);
|
debug_println!("clear_screen: {:?}", mode);
|
||||||
let template = self.template_cell.clone();
|
let template = self.empty_cell.clone();
|
||||||
match mode {
|
match mode {
|
||||||
ansi::ClearMode::Below => {
|
ansi::ClearMode::Below => {
|
||||||
for row in &mut self.grid[self.cursor.line..] {
|
for row in &mut self.grid[self.cursor.line..] {
|
||||||
|
@ -793,36 +780,36 @@ impl ansi::Handler for Term {
|
||||||
debug_println!("Set Attribute: {:?}", attr);
|
debug_println!("Set Attribute: {:?}", attr);
|
||||||
match attr {
|
match attr {
|
||||||
Attr::DefaultForeground => {
|
Attr::DefaultForeground => {
|
||||||
self.fg = DEFAULT_FG;
|
self.template_cell.fg = self.fg;
|
||||||
},
|
},
|
||||||
Attr::DefaultBackground => {
|
Attr::DefaultBackground => {
|
||||||
self.bg = DEFAULT_BG;
|
self.template_cell.bg = self.bg;
|
||||||
},
|
},
|
||||||
Attr::Foreground(named_color) => {
|
Attr::Foreground(named_color) => {
|
||||||
self.fg = COLORS[named_color as usize];
|
self.template_cell.fg = self.colors[named_color as usize];
|
||||||
},
|
},
|
||||||
Attr::Background(named_color) => {
|
Attr::Background(named_color) => {
|
||||||
self.bg = COLORS[named_color as usize];
|
self.template_cell.bg = self.colors[named_color as usize];
|
||||||
},
|
},
|
||||||
Attr::ForegroundSpec(rgb) => {
|
Attr::ForegroundSpec(rgb) => {
|
||||||
self.fg = rgb;
|
self.template_cell.fg = rgb;
|
||||||
},
|
},
|
||||||
Attr::BackgroundSpec(rgb) => {
|
Attr::BackgroundSpec(rgb) => {
|
||||||
self.bg = rgb;
|
self.template_cell.bg = rgb;
|
||||||
},
|
},
|
||||||
Attr::Reset => {
|
Attr::Reset => {
|
||||||
self.fg = DEFAULT_FG;
|
self.template_cell.fg = self.fg;
|
||||||
self.bg = DEFAULT_BG;
|
self.template_cell.bg = self.bg;
|
||||||
self.attr = cell::Flags::empty();
|
self.template_cell.flags = cell::Flags::empty();
|
||||||
},
|
},
|
||||||
Attr::Reverse => self.attr.insert(cell::INVERSE),
|
Attr::Reverse => self.template_cell.flags.insert(cell::INVERSE),
|
||||||
Attr::CancelReverse => self.attr.remove(cell::INVERSE),
|
Attr::CancelReverse => self.template_cell.flags.remove(cell::INVERSE),
|
||||||
Attr::Bold => self.attr.insert(cell::BOLD),
|
Attr::Bold => self.template_cell.flags.insert(cell::BOLD),
|
||||||
Attr::CancelBoldDim => self.attr.remove(cell::BOLD),
|
Attr::CancelBoldDim => self.template_cell.flags.remove(cell::BOLD),
|
||||||
Attr::Italic => self.attr.insert(cell::ITALIC),
|
Attr::Italic => self.template_cell.flags.insert(cell::ITALIC),
|
||||||
Attr::CancelItalic => self.attr.remove(cell::ITALIC),
|
Attr::CancelItalic => self.template_cell.flags.remove(cell::ITALIC),
|
||||||
Attr::Underscore => self.attr.insert(cell::UNDERLINE),
|
Attr::Underscore => self.template_cell.flags.insert(cell::UNDERLINE),
|
||||||
Attr::CancelUnderline => self.attr.remove(cell::UNDERLINE),
|
Attr::CancelUnderline => self.template_cell.flags.remove(cell::UNDERLINE),
|
||||||
_ => {
|
_ => {
|
||||||
debug_println!("Term got unhandled attr: {:?}", attr);
|
debug_println!("Term got unhandled attr: {:?}", attr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue