Move color list to Term struct

The color list needs to be updated by the parser, and this isn't
possible if it's on the config. This change makes sense semantically as
well since it's really part of the terminal state.

This is in preparation for OSC color parsing.
This commit is contained in:
Joe Wilm 2017-02-11 12:49:40 -08:00 committed by Joe Wilm
parent d2e8a0cd10
commit 908ea5543a
6 changed files with 289 additions and 290 deletions

View File

@ -7,7 +7,6 @@ use std::borrow::Cow;
use std::{env, fmt};
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::ops::{Index, IndexMut};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::mpsc;
@ -24,8 +23,6 @@ use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op};
use input::{Action, Binding, MouseBinding, KeyBinding};
use index::{Line, Column};
use ansi;
/// Function that returns true for serde default
fn true_bool() -> bool {
true
@ -77,148 +74,6 @@ impl Default for Mouse {
}
}
/// 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, item 257 is the configured background
/// color, item 258 is the cursor foreground color, item 259 is the cursor
//background color.
pub struct ColorList([Rgb; 260]);
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;
// Foreground and background for custom cursor colors
self[ansi::NamedColor::CursorForeground] = colors.cursor.foreground;
self[ansi::NamedColor::CursorBackground] = colors.cursor.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]
}
}
/// VisulBellAnimations are modeled after a subset of CSS transitions and Robert
/// Penner's Easing Functions.
#[derive(Clone, Copy, Debug, Deserialize)]
@ -341,7 +196,7 @@ pub struct Config {
draw_bold_text_with_bright_colors: bool,
#[serde(default)]
colors: ColorList,
colors: Colors,
/// Keybindings
#[serde(default="default_key_bindings")]
@ -789,15 +644,6 @@ impl de::Deserialize for RawBinding {
}
}
impl de::Deserialize for ColorList {
fn deserialize<D>(deserializer: 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: D) -> ::std::result::Result<Self, D::Error>
where D: de::Deserializer
@ -836,11 +682,11 @@ pub enum Error {
#[derive(Debug, Deserialize)]
pub struct Colors {
primary: PrimaryColors,
pub primary: PrimaryColors,
#[serde(default="default_cursor_colors")]
cursor: PrimaryColors,
normal: AnsiColors,
bright: AnsiColors,
pub cursor: PrimaryColors,
pub normal: AnsiColors,
pub bright: AnsiColors,
}
fn default_cursor_colors() -> PrimaryColors {
@ -853,9 +699,9 @@ fn default_cursor_colors() -> PrimaryColors {
#[derive(Debug, Deserialize)]
pub struct PrimaryColors {
#[serde(deserialize_with = "rgb_from_hex")]
background: Rgb,
pub background: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
foreground: Rgb,
pub foreground: Rgb,
}
impl Default for Colors {
@ -894,21 +740,21 @@ impl Default for Colors {
#[derive(Debug, Deserialize)]
pub struct AnsiColors {
#[serde(deserialize_with = "rgb_from_hex")]
black: Rgb,
pub black: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
red: Rgb,
pub red: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
green: Rgb,
pub green: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
yellow: Rgb,
pub yellow: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
blue: Rgb,
pub blue: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
magenta: Rgb,
pub magenta: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
cyan: Rgb,
pub cyan: Rgb,
#[serde(deserialize_with = "rgb_from_hex")]
white: Rgb,
pub white: Rgb,
}
/// Deserialize an Rgb from a hex string
@ -1076,7 +922,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) -> &ColorList {
pub fn colors(&self) -> &Colors {
&self.colors
}

View File

@ -19,7 +19,6 @@ use std::sync::mpsc;
use parking_lot::{MutexGuard};
use Rgb;
use ansi::Color;
use cli;
use config::Config;
use font::{self, Rasterize};
@ -120,7 +119,6 @@ impl Display {
}
pub fn update_config(&mut self, config: &Config) {
self.renderer.update_config(config);
self.render_timer = config.render_timer();
}
@ -151,7 +149,7 @@ impl Display {
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr, config.use_thin_strokes())?;
// Create renderer
let mut renderer = QuadRenderer::new(config, size)?;
let mut renderer = QuadRenderer::new(size)?;
// Initialize glyph cache
let glyph_cache = {
@ -280,6 +278,9 @@ impl Display {
{
let glyph_cache = &mut self.glyph_cache;
let size_info = *terminal.size_info();
let visual_bell_intensity = terminal.visual_bell.intensity();
// Draw grid
{
let _sampler = self.meter.sampler();
@ -289,23 +290,20 @@ impl Display {
//
// TODO I wonder if the renderable cells iter could avoid the
// mutable borrow
let size_info = *terminal.size_info();
self.renderer.with_api(config, &size_info, |mut api| {
api.set_visual_bell(terminal.visual_bell.intensity() as f32);
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
api.clear();
// Draw the grid
api.render_cells(terminal.renderable_cells(selection), glyph_cache);
api.render_cells(terminal.renderable_cells(config, selection), glyph_cache);
});
}
// Draw render timer
if self.render_timer {
let timing = format!("{:.3} usec", self.meter.average());
let color = Color::Spec(Rgb { r: 0xd5, g: 0x4e, b: 0x53 });
self.renderer.with_api(config, terminal.size_info(), |mut api| {
api.render_string(&timing[..], glyph_cache, &color);
let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
api.render_string(&timing[..], glyph_cache, color);
});
}
}

View File

@ -38,6 +38,21 @@ pub trait BidirectionalIterator: Iterator {
fn prev(&mut self) -> Option<Self::Item>;
}
pub struct Indexed<T> {
pub line: Line,
pub column: Column,
pub inner: T
}
impl<T> Deref for Indexed<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.inner
}
}
/// Represents the terminal display contents
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
pub struct Grid<T> {

View File

@ -28,9 +28,8 @@ use gl;
use index::{Line, Column, RangeInclusive};
use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op};
use ansi::{Color, NamedColor};
use config::{Config, ColorList};
use term::{self, cell, IndexedCell, Cell};
use config::Config;
use term::{self, cell, RenderableCell};
use window::{Size, Pixels};
use Rgb;
@ -313,7 +312,6 @@ pub struct QuadRenderer {
atlas: Vec<Atlas>,
active_tex: GLuint,
batch: Batch,
draw_bold_text_with_bright_colors: bool,
rx: mpsc::Receiver<Msg>,
}
@ -323,8 +321,8 @@ pub struct RenderApi<'a> {
batch: &'a mut Batch,
atlas: &'a mut Vec<Atlas>,
program: &'a mut ShaderProgram,
colors: &'a ColorList,
visual_bell: f32,
config: &'a Config,
visual_bell_intensity: f32
}
#[derive(Debug)]
@ -343,58 +341,26 @@ pub struct PackedVertex {
pub struct Batch {
tex: GLuint,
instances: Vec<InstanceData>,
draw_bold_text_with_bright_colors: bool,
}
impl Batch {
#[inline]
pub fn new(config: &Config) -> Batch {
pub fn new() -> Batch {
Batch {
tex: 0,
instances: Vec::with_capacity(BATCH_MAX),
draw_bold_text_with_bright_colors: config.draw_bold_text_with_bright_colors(),
}
}
pub fn add_item(
&mut self,
cell: &IndexedCell,
cell: &RenderableCell,
glyph: &Glyph,
colors: &ColorList
) {
if self.is_empty() {
self.tex = glyph.tex_id;
}
let fg = match cell.fg {
Color::Spec(rgb) => rgb,
Color::Named(ansi) => {
if self.draw_bold_text_with_bright_colors && cell.bold() {
colors[ansi.to_bright()]
} else {
colors[ansi]
}
},
Color::Indexed(idx) => {
let idx = if self.draw_bold_text_with_bright_colors
&& cell.bold()
&& idx < 8
{
idx + 8
} else {
idx
};
colors[idx]
}
};
let bg = match cell.bg {
Color::Spec(rgb) => rgb,
Color::Named(ansi) => colors[ansi],
Color::Indexed(idx) => colors[idx],
};
self.instances.push(InstanceData {
col: cell.column.0 as f32,
row: cell.line.0 as f32,
@ -409,13 +375,13 @@ impl Batch {
uv_width: glyph.uv_width,
uv_height: glyph.uv_height,
r: fg.r as f32,
g: fg.g as f32,
b: fg.b as f32,
r: cell.fg.r as f32,
g: cell.fg.g as f32,
b: cell.fg.b as f32,
bg_r: bg.r as f32,
bg_g: bg.g as f32,
bg_b: bg.b as f32,
bg_r: cell.bg.r as f32,
bg_g: cell.bg.g as f32,
bg_b: cell.bg.b as f32,
});
}
@ -456,7 +422,7 @@ const ATLAS_SIZE: i32 = 1024;
impl QuadRenderer {
// TODO should probably hand this a transform instead of width/height
pub fn new(config: &Config, size: Size<Pixels<u32>>) -> Result<QuadRenderer, Error> {
pub fn new(size: Size<Pixels<u32>>) -> Result<QuadRenderer, Error> {
let program = ShaderProgram::new(size)?;
let mut vao: GLuint = 0;
@ -600,9 +566,8 @@ impl QuadRenderer {
vbo_instance: vbo_instance,
atlas: Vec::new(),
active_tex: 0,
batch: Batch::new(config),
batch: Batch::new(),
rx: msg_rx,
draw_bold_text_with_bright_colors: config.draw_bold_text_with_bright_colors(),
};
let atlas = Atlas::new(ATLAS_SIZE);
@ -611,14 +576,11 @@ impl QuadRenderer {
Ok(renderer)
}
pub fn update_config(&mut self, config: &Config) {
self.batch.draw_bold_text_with_bright_colors = config.draw_bold_text_with_bright_colors();
}
pub fn with_api<F, T>(
&mut self,
config: &Config,
props: &term::SizeInfo,
visual_bell_intensity: f64,
func: F
) -> T
where F: FnOnce(RenderApi) -> T
@ -637,6 +599,7 @@ impl QuadRenderer {
unsafe {
self.program.activate();
self.program.set_term_uniforms(props);
self.program.set_visual_bell(visual_bell_intensity as _);
gl::BindVertexArray(self.vao);
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
@ -649,8 +612,8 @@ impl QuadRenderer {
batch: &mut self.batch,
atlas: &mut self.atlas,
program: &mut self.program,
colors: config.color_list(),
visual_bell: 0.0,
visual_bell_intensity: visual_bell_intensity as _,
config: config,
});
unsafe {
@ -713,18 +676,13 @@ impl QuadRenderer {
}
impl<'a> RenderApi<'a> {
pub fn set_visual_bell(&mut self, visual_bell: f32) {
self.visual_bell = visual_bell;
self.program.set_visual_bell(visual_bell);
}
pub fn clear(&self) {
let color = self.colors[NamedColor::Background];
let color = self.config.colors().primary.background;
unsafe {
gl::ClearColor(
(self.visual_bell + color.r as f32 / 255.0).min(1.0),
(self.visual_bell + color.g as f32 / 255.0).min(1.0),
(self.visual_bell + color.b as f32 / 255.0).min(1.0),
(self.visual_bell_intensity + color.r as f32 / 255.0).min(1.0),
(self.visual_bell_intensity + color.g as f32 / 255.0).min(1.0),
(self.visual_bell_intensity + color.b as f32 / 255.0).min(1.0),
1.0
);
gl::Clear(gl::COLOR_BUFFER_BIT);
@ -764,22 +722,20 @@ impl<'a> RenderApi<'a> {
&mut self,
string: &str,
glyph_cache: &mut GlyphCache,
color: &Color,
color: Rgb,
) {
let line = Line(23);
let col = Column(0);
let cells = string.chars()
.enumerate()
.map(|(i, c)| IndexedCell {
.map(|(i, c)| RenderableCell {
line: line,
column: col + i,
inner: Cell {
c: c,
bg: *color,
fg: Color::Spec(Rgb { r: 0, g: 0, b: 0}),
flags: cell::Flags::empty(),
}
c: c,
bg: color,
fg: Rgb { r: 0, g: 0, b: 0 },
flags: cell::Flags::empty(),
})
.collect::<Vec<_>>();
@ -787,13 +743,13 @@ impl<'a> RenderApi<'a> {
}
#[inline]
fn add_render_item(&mut self, cell: &IndexedCell, glyph: &Glyph) {
fn add_render_item(&mut self, cell: &RenderableCell, glyph: &Glyph) {
// Flush batch if tex changing
if !self.batch.is_empty() && self.batch.tex != glyph.tex_id {
self.render_batch();
}
self.batch.add_item(cell, glyph, self.colors);
self.batch.add_item(cell, glyph);
// Render batch and clear if it's full
if self.batch.full() {
@ -806,7 +762,7 @@ impl<'a> RenderApi<'a> {
cells: I,
glyph_cache: &mut GlyphCache
)
where I: Iterator<Item=::term::IndexedCell>
where I: Iterator<Item=RenderableCell>
{
for cell in cells {
// Get font key for cell

147
src/term/color.rs Normal file
View File

@ -0,0 +1,147 @@
use std::ops::{Index, IndexMut};
use std::fmt;
use {Rgb, ansi};
use config::Colors;
/// 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, item 257 is the configured background
/// color, item 258 is the cursor foreground color, item 259 is the cursor
/// background color.
pub struct List([Rgb; 260]);
impl<'a> From<&'a Colors> for List {
fn from(colors: &Colors) -> List {
// Type inference fails without this annotation
let mut list: List = unsafe { ::std::mem::uninitialized() };
list.fill_named(&colors);
list.fill_cube();
list.fill_gray_ramp();
list
}
}
impl List {
pub 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;
// Foreground and background for custom cursor colors
self[ansi::NamedColor::CursorForeground] = colors.cursor.foreground;
self[ansi::NamedColor::CursorBackground] = colors.cursor.background;
}
fn fill_cube(&mut self) {
let mut index: usize = 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: usize = 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 fmt::Debug for List {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("List[..]")
}
}
impl Index<ansi::NamedColor> for List {
type Output = Rgb;
#[inline]
fn index(&self, idx: ansi::NamedColor) -> &Self::Output {
&self.0[idx as usize]
}
}
impl IndexMut<ansi::NamedColor> for List {
#[inline]
fn index_mut(&mut self, idx: ansi::NamedColor) -> &mut Self::Output {
&mut self.0[idx as usize]
}
}
impl Index<usize> for List {
type Output = Rgb;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
&self.0[idx]
}
}
impl IndexMut<usize> for List {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.0[idx]
}
}
impl Index<u8> for List {
type Output = Rgb;
#[inline]
fn index(&self, idx: u8) -> &Self::Output {
&self.0[idx as usize]
}
}
impl IndexMut<u8> for List {
#[inline]
fn index_mut(&mut self, idx: u8) -> &mut Self::Output {
&mut self.0[idx as usize]
}
}

View File

@ -14,19 +14,21 @@
//
//! Exports the `Term` type which is a high-level API for the Grid
use std::mem;
use std::ops::{Deref, Range, Index, IndexMut};
use std::ops::{Range, Index, IndexMut};
use std::ptr;
use std::cmp::min;
use std::io;
use std::time::{Duration, Instant};
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset};
use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange};
use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed};
use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side};
use selection::{Span, Selection};
use config::{Config, VisualBellAnimation};
use Rgb;
pub mod cell;
pub mod color;
pub use self::cell::Cell;
use self::cell::LineLength;
@ -44,8 +46,10 @@ pub struct RenderableCellsIter<'a> {
mode: TermMode,
line: Line,
column: Column,
config: &'a Config,
colors: &'a color::List,
selection: Option<RangeInclusive<index::Linear>>,
cursor_original: Option<IndexedCell>
cursor_original: Option<Indexed<Cell>>
}
impl<'a> RenderableCellsIter<'a> {
@ -56,9 +60,10 @@ impl<'a> RenderableCellsIter<'a> {
fn new<'b>(
grid: &'b mut Grid<Cell>,
cursor: &'b Point,
colors: &'b color::List,
mode: TermMode,
config: &'b Config,
selection: &Selection,
custom_cursor_colors: bool,
) -> RenderableCellsIter<'b> {
let selection = selection.span()
.map(|span| span.to_range(grid.num_cols()));
@ -70,18 +75,21 @@ impl<'a> RenderableCellsIter<'a> {
line: Line(0),
column: Column(0),
selection: selection,
config: config,
colors: colors,
cursor_original: None,
}.initialize(custom_cursor_colors)
}.initialize()
}
fn initialize(mut self, custom_cursor_colors: bool) -> Self {
fn initialize(mut self) -> Self {
if self.cursor_is_visible() {
self.cursor_original = Some(IndexedCell {
self.cursor_original = Some(Indexed {
line: self.cursor.line,
column: self.cursor.col,
inner: self.grid[self.cursor]
});
if custom_cursor_colors {
if self.config.custom_cursor_colors() {
let cell = &mut self.grid[self.cursor];
cell.fg = Color::Named(NamedColor::CursorForeground);
cell.bg = Color::Named(NamedColor::CursorBackground);
@ -112,23 +120,17 @@ impl<'a> Drop for RenderableCellsIter<'a> {
}
}
pub struct IndexedCell {
pub struct RenderableCell {
pub line: Line,
pub column: Column,
pub inner: Cell
}
impl Deref for IndexedCell {
type Target = Cell;
#[inline]
fn deref(&self) -> &Cell {
&self.inner
}
pub c: char,
pub fg: Rgb,
pub bg: Rgb,
pub flags: cell::Flags,
}
impl<'a> Iterator for RenderableCellsIter<'a> {
type Item = IndexedCell;
type Item = RenderableCell;
/// Gets the next renderable cell
///
@ -159,22 +161,50 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
// fg, bg are dependent on INVERSE flag
let invert = cell.flags.contains(cell::INVERSE) || selected;
let (fg, bg) = if invert {
(&cell.bg, &cell.fg)
} else {
(&cell.fg, &cell.bg)
};
return Some(IndexedCell {
// Get Rgb value for foreground
let fg = match *fg {
Color::Spec(rgb) => rgb,
Color::Named(ansi) => {
if self.config.draw_bold_text_with_bright_colors() && cell.bold() {
self.colors[ansi.to_bright()]
} else {
self.colors[ansi]
}
},
Color::Indexed(idx) => {
let idx = if self.config.draw_bold_text_with_bright_colors()
&& cell.bold()
&& idx < 8
{
idx + 8
} else {
idx
};
self.colors[idx]
}
};
// Get Rgb value for background
let bg = match *bg {
Color::Spec(rgb) => rgb,
Color::Named(ansi) => self.colors[ansi],
Color::Indexed(idx) => self.colors[idx],
};
return Some(RenderableCell {
line: line,
column: column,
inner: Cell {
flags: cell.flags,
c: cell.c,
fg: *fg,
bg: *bg,
}
flags: cell.flags,
c: cell.c,
fg: fg,
bg: bg,
})
}
@ -461,8 +491,6 @@ pub struct Term {
pub visual_bell: VisualBell,
custom_cursor_colors: bool,
/// Saved cursor from main grid
cursor_save: Cursor,
@ -470,6 +498,9 @@ pub struct Term {
cursor_save_alt: Cursor,
semantic_escape_chars: String,
/// Colors used for rendering
colors: color::List,
}
/// Terminal size info
@ -514,6 +545,7 @@ impl SizeInfo {
}
}
impl Term {
#[inline]
pub fn get_next_title(&mut self) -> Option<String> {
@ -554,14 +586,14 @@ impl Term {
scroll_region: scroll_region,
size_info: size,
empty_cell: template,
custom_cursor_colors: config.custom_cursor_colors(),
colors: color::List::from(config.colors()),
semantic_escape_chars: config.selection().semantic_escape_chars.clone(),
}
}
pub fn update_config(&mut self, config: &Config) {
self.custom_cursor_colors = config.custom_cursor_colors();
self.semantic_escape_chars = config.selection().semantic_escape_chars.clone();
self.colors.fill_named(config.colors());
self.visual_bell.update_config(config);
}
@ -772,13 +804,18 @@ impl Term {
/// A renderable cell is any cell which has content other than the default
/// background color. Cells with an alternate background color are
/// considered renderable as are cells with any text content.
pub fn renderable_cells(&mut self, selection: &Selection) -> RenderableCellsIter {
pub fn renderable_cells<'b>(
&'b mut self,
config: &'b Config,
selection: &'b Selection
) -> RenderableCellsIter {
RenderableCellsIter::new(
&mut self.grid,
&self.cursor.point,
&self.colors,
self.mode,
config,
selection,
self.custom_cursor_colors
)
}