diff --git a/alacritty.yml b/alacritty.yml index c08713c6..96fe6e24 100644 --- a/alacritty.yml +++ b/alacritty.yml @@ -48,12 +48,19 @@ font: # Should display the render timer render_timer: false +# Use custom cursor colors. If true, display the cursor in the cursor.foreground +# and cursor.background colors, otherwise invert the colors of the cursor. +custom_cursor_colors: false + # Colors (Tomorrow Night Bright) colors: # Default colors primary: background: '0x000000' foreground: '0xeaeaea' + cursor: + background: '0xffffff' + foreground: '0x000000' # Normal colors normal: diff --git a/alacritty_macos.yml b/alacritty_macos.yml index de60f7ef..386e4590 100644 --- a/alacritty_macos.yml +++ b/alacritty_macos.yml @@ -48,12 +48,19 @@ font: # Should display the render timer render_timer: false +# Use custom cursor colors. If true, display the cursor in the cursor.foreground +# and cursor.background colors, otherwise invert the colors of the cursor. +custom_cursor_colors: false + # Colors (Tomorrow Night Bright) colors: # Default colors primary: background: '0x000000' foreground: '0xeaeaea' + cursor: + background: '0xffffff' + foreground: '0x000000' # Normal colors normal: diff --git a/src/ansi.rs b/src/ansi.rs index 30048048..c9f7e268 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -380,6 +380,10 @@ pub enum NamedColor { Foreground = 256, /// The background color Background, + /// The cursor foreground color + CursorForeground, + /// The cursor background color + CursorBackground, } impl NamedColor { diff --git a/src/config.rs b/src/config.rs index 4ef3481b..1aaf5692 100644 --- a/src/config.rs +++ b/src/config.rs @@ -34,9 +34,10 @@ fn true_bool() -> bool { /// /// 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, and item 257 is the configured background -/// color. -pub struct ColorList([Rgb; 258]); +/// 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 { @@ -88,6 +89,10 @@ impl ColorList { // 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) { @@ -218,7 +223,11 @@ pub struct Config { #[serde(default)] render_timer: bool, - /// Should show render timer + /// Should use custom cursor colors + #[serde(default)] + custom_cursor_colors: bool, + + /// Should draw bold text with brighter colors intead of bold font #[serde(default="true_bool")] draw_bold_text_with_bright_colors: bool, @@ -266,6 +275,7 @@ impl Default for Config { dpi: Default::default(), font: Default::default(), render_timer: Default::default(), + custom_cursor_colors: false, colors: Default::default(), key_bindings: Vec::new(), mouse_bindings: Vec::new(), @@ -668,6 +678,7 @@ pub enum Error { #[derive(Debug, Deserialize)] pub struct Colors { primary: PrimaryColors, + cursor: PrimaryColors, normal: AnsiColors, bright: AnsiColors, } @@ -687,6 +698,10 @@ impl Default for Colors { background: Rgb { r: 0, g: 0, b: 0 }, foreground: Rgb { r: 0xea, g: 0xea, b: 0xea }, }, + cursor: PrimaryColors { + foreground: Rgb { r: 0, g: 0, b: 0 }, + background: Rgb { r: 0xff, g: 0xff, b: 0xff }, + }, normal: AnsiColors { black: Rgb {r: 0x00, g: 0x00, b: 0x00}, red: Rgb {r: 0xd5, g: 0x4e, b: 0x53}, @@ -933,6 +948,11 @@ impl Config { self.font.use_thin_strokes } + /// show cursor as inverted + #[inline] + pub fn custom_cursor_colors(&self) -> bool { + self.custom_cursor_colors + } pub fn path(&self) -> Option<&Path> { self.config_path diff --git a/src/main.rs b/src/main.rs index e51875a6..5126b09d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,7 +95,7 @@ fn run(mut config: Config, options: cli::Options) -> Result<(), Box> { // This object contains all of the state about what's being displayed. It's // wrapped in a clonable mutex since both the I/O loop and display need to // access it. - let terminal = Term::new(display.size().to_owned()); + let terminal = Term::new(&config, display.size().to_owned()); let terminal = Arc::new(FairMutex::new(terminal)); // Create the pty @@ -156,6 +156,7 @@ fn run(mut config: Config, options: cli::Options) -> Result<(), Box> { config = new_config; display.update_config(&config); processor.update_config(&config); + terminal.update_config(&config); terminal.dirty = true; }); diff --git a/src/term/cell.rs b/src/term/cell.rs index 021ce280..e6e9f340 100644 --- a/src/term/cell.rs +++ b/src/term/cell.rs @@ -11,8 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -use std::mem; - use ansi::{NamedColor, Color}; use grid; use index::Column; @@ -98,11 +96,6 @@ impl Cell { // memcpy template to self *self = *template; } - - #[inline] - pub fn swap_fg_and_bg(&mut self) { - mem::swap(&mut self.fg, &mut self.bg); - } } #[cfg(test)] diff --git a/src/term/mod.rs b/src/term/mod.rs index 9d443723..92242071 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -13,6 +13,7 @@ // limitations under the License. // //! 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::ptr; use std::cmp::min; @@ -22,6 +23,7 @@ use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset use grid::{Grid, ClearRegion, ToRange}; use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive}; use selection::{Span, Selection}; +use config::{Config}; pub mod cell; pub use self::cell::Cell; @@ -42,6 +44,7 @@ pub struct RenderableCellsIter<'a> { line: Line, column: Column, selection: Option>, + cursor_original: Option } impl<'a> RenderableCellsIter<'a> { @@ -54,6 +57,7 @@ impl<'a> RenderableCellsIter<'a> { cursor: &'b Point, mode: TermMode, selection: &Selection, + custom_cursor_colors: bool, ) -> RenderableCellsIter<'b> { let selection = selection.span() .map(|span| span.to_range(grid.num_cols())); @@ -65,14 +69,27 @@ impl<'a> RenderableCellsIter<'a> { line: Line(0), column: Column(0), selection: selection, - }.initialize() + cursor_original: None, + }.initialize(custom_cursor_colors) } - fn initialize(self) -> Self { + fn initialize(mut self, custom_cursor_colors: bool) -> Self { if self.cursor_is_visible() { - self.grid[self.cursor].swap_fg_and_bg(); - } + self.cursor_original = Some(IndexedCell { + line: self.cursor.line, + column: self.cursor.col, + inner: self.grid[self.cursor] + }); + if custom_cursor_colors { + let cell = &mut self.grid[self.cursor]; + cell.fg = Color::Named(NamedColor::CursorForeground); + cell.bg = Color::Named(NamedColor::CursorBackground); + } else { + let cell = &mut self.grid[self.cursor]; + mem::swap(&mut cell.fg, &mut cell.bg); + } + } self } @@ -87,7 +104,9 @@ impl<'a> Drop for RenderableCellsIter<'a> { /// Resets temporary render state on the grid fn drop(&mut self) { if self.cursor_is_visible() { - self.grid[self.cursor].swap_fg_and_bg(); + if let Some(ref original) = self.cursor_original { + self.grid[self.cursor] = original.inner; + } } } } @@ -327,6 +346,8 @@ pub struct Term { empty_cell: Cell, pub dirty: bool, + + custom_cursor_colors: bool, } /// Terminal size info @@ -377,7 +398,7 @@ impl Term { self.next_title.take() } - pub fn new(size: SizeInfo) -> Term { + pub fn new(config : &Config, size: SizeInfo) -> Term { let template = Cell::default(); let num_cols = size.cols(); @@ -411,9 +432,14 @@ impl Term { size_info: size, template_cell: template, empty_cell: template, + custom_cursor_colors: config.custom_cursor_colors(), } } + pub fn update_config(&mut self, config: &Config) { + self.custom_cursor_colors = config.custom_cursor_colors() + } + #[inline] pub fn needs_draw(&self) -> bool { self.dirty @@ -564,7 +590,7 @@ impl Term { /// 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 { - RenderableCellsIter::new(&mut self.grid, &self.cursor, self.mode, selection) + RenderableCellsIter::new(&mut self.grid, &self.cursor, self.mode, selection, self.custom_cursor_colors) } /// Resize terminal to new dimensions @@ -1248,7 +1274,7 @@ mod tests { cell_width: 3.0, cell_height: 3.0, }; - let mut term = Term::new(size); + let mut term = Term::new(&Default::default(), size); let cursor = Point::new(Line(0), Column(0)); term.configure_charset(CharsetIndex::G0, StandardCharset::SpecialCharacterAndLineDrawing); @@ -1306,7 +1332,7 @@ mod benches { let mut grid: Grid = json::from_str(&serialized_grid).unwrap(); let size: SizeInfo = json::from_str(&serialized_size).unwrap(); - let mut terminal = Term::new(size); + let mut terminal = Term::new(&Default::default(), size); mem::swap(&mut terminal.grid, &mut grid); b.iter(|| { diff --git a/tests/ref.rs b/tests/ref.rs index c91fdc78..b8be58cf 100644 --- a/tests/ref.rs +++ b/tests/ref.rs @@ -67,7 +67,7 @@ fn ref_test(dir: &Path) { let size: SizeInfo = json::from_str(&serialized_size).unwrap(); let grid: Grid = json::from_str(&serialized_grid).unwrap(); - let mut terminal = Term::new(size); + let mut terminal = Term::new(&Default::default(), size); let mut parser = ansi::Processor::new(); for byte in recording {