aboutsummaryrefslogtreecommitdiff
path: root/src/term
diff options
context:
space:
mode:
Diffstat (limited to 'src/term')
-rw-r--r--src/term/color.rs147
-rw-r--r--src/term/mod.rs105
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
)
}