diff options
Diffstat (limited to 'src/term')
-rw-r--r-- | src/term/color.rs | 147 | ||||
-rw-r--r-- | src/term/mod.rs | 105 |
2 files changed, 218 insertions, 34 deletions
diff --git a/src/term/color.rs b/src/term/color.rs new file mode 100644 index 00000000..8e15ad41 --- /dev/null +++ b/src/term/color.rs @@ -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] + } +} diff --git a/src/term/mod.rs b/src/term/mod.rs index 26ed2fad..3a86f887 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -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 ) } |