From d387ebe1d7fe9f9fe9d840039aba68efffe5a233 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Wed, 19 Sep 2018 19:18:51 +0000 Subject: [PATCH] Add hidden escape sequence This adds support for the `hidden` escape sequence `\e[8m`, which will render the text as invisible. This has also raised a few questions about the rendering of foreground and background colors and their interaction with the different escape sequences. Previously, Alacritty has oriented itself after URxvt, which has some strange and unexpected behavior. The new implementation of color inversion is modeled after XTerm, which has a consistent pattern of always inverting the foreground and background colors. This should hopefully lead to less confusion for the user and a more consistent behavior. A full matrix showcasing the new way Alacritty inverses text can be found here: https://i.imgur.com/d1XavG7.png This fixes #1454 and fixes #1455. --- CHANGELOG.md | 2 ++ scripts/fg-bg.sh | 63 ++++++++++++++++++++++++++++++++++++--------- src/renderer/mod.rs | 7 ++++- src/term/cell.rs | 19 +++++++------- src/term/mod.rs | 30 +++++++-------------- 5 files changed, 79 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa3af77b..5c78cc7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Implement the `hidden` escape sequence (`echo -e "\e[8mTEST"`) - Add support for macOS systemwide dark mode - Set the environment variable `COLORTERM="truecolor"` to advertise 24-bit color support ### Changed +- Inverse/Selection color is now modelled after XTerm/VTE instead of URxvt to improve consistency - First click on unfocused Alacritty windows is no longer ignored on platforms other than macOS ## Version 0.2.0 diff --git a/scripts/fg-bg.sh b/scripts/fg-bg.sh index f1ad4d0c..b6e0eaea 100755 --- a/scripts/fg-bg.sh +++ b/scripts/fg-bg.sh @@ -1,14 +1,53 @@ #!/bin/bash -printf "Fg=Black, Bg=Background \e[30;49mTEST\e[m\n" -printf "Fg=Black, Bg=Black \e[30;40mTEST\e[m\n" -printf "Fg=Foreground,Bg=Background \e[39;49mTEST\e[m\n" -printf "Fg=Foreground,Bg=Black \e[39;40mTEST\e[m\n" -printf "Fg=Foreground,Bg=White \e[39;47mTEST\e[m\n" -printf "Fg=White, Bg=Foreground \e[37;39mTEST\e[m\n" -printf "Fg=Black, Bg=Background, Inverse \e[7;30;49mTEST\e[m\n" -printf "Fg=Black, Bg=Black, Inverse \e[7;30;40mTEST\e[m\n" -printf "Fg=Foreground,Bg=Background, Inverse \e[7;39;49mTEST\e[m\n" -printf "Fg=Foreground,Bg=Black, Inverse \e[7;39;40mTEST\e[m\n" -printf "Fg=Foreground,Bg=White, Inverse \e[7;39;47mTEST\e[m\n" -printf "Fg=White, Bg=Foreground, Inverse \e[7;37;39mTEST\e[m\n" +printf "Fg=Black Bg=Black \e[30;40mTEST\e[m\n" +printf "Fg=Black Bg=White \e[30;107mTEST\e[m\n" +printf "Fg=Black Bg=Red \e[30;41mTEST\e[m\n" +printf "Fg=Black Bg=BG \e[30;49mTEST\e[m\n" +printf "Fg=White Bg=Black \e[97;40mTEST\e[m\n" +printf "Fg=White Bg=White \e[97;107mTEST\e[m\n" +printf "Fg=White Bg=Red \e[97;41mTEST\e[m\n" +printf "Fg=White Bg=BG \e[97;49mTEST\e[m\n" +printf "Fg=Red Bg=Black \e[31;40mTEST\e[m\n" +printf "Fg=Red Bg=White \e[31;107mTEST\e[m\n" +printf "Fg=Red Bg=Red \e[31;41mTEST\e[m\n" +printf "Fg=Red Bg=BG \e[31;49mTEST\e[m\n" +printf "\n" +printf "Fg=Black Bg=Black Inverse \e[7;30;40mTEST\e[m\n" +printf "Fg=Black Bg=White Inverse \e[7;30;107mTEST\e[m\n" +printf "Fg=Black Bg=Red Inverse \e[7;30;41mTEST\e[m\n" +printf "Fg=Black Bg=BG Inverse \e[7;30;49mTEST\e[m\n" +printf "Fg=White Bg=Black Inverse \e[7;97;40mTEST\e[m\n" +printf "Fg=White Bg=White Inverse \e[7;97;107mTEST\e[m\n" +printf "Fg=White Bg=Red Inverse \e[7;97;41mTEST\e[m\n" +printf "Fg=White Bg=BG Inverse \e[7;97;49mTEST\e[m\n" +printf "Fg=Red Bg=Black Inverse \e[7;31;40mTEST\e[m\n" +printf "Fg=Red Bg=White Inverse \e[7;31;107mTEST\e[m\n" +printf "Fg=Red Bg=Red Inverse \e[7;31;41mTEST\e[m\n" +printf "Fg=Red Bg=BG Inverse \e[7;31;49mTEST\e[m\n" +printf "\n" +printf "Fg=Black Bg=Black Hidden \e[8;30;40mTEST\e[m\n" +printf "Fg=Black Bg=White Hidden \e[8;30;107mTEST\e[m\n" +printf "Fg=Black Bg=Red Hidden \e[8;30;41mTEST\e[m\n" +printf "Fg=Black Bg=BG Hidden \e[8;30;49mTEST\e[m\n" +printf "Fg=White Bg=Black Hidden \e[8;97;40mTEST\e[m\n" +printf "Fg=White Bg=White Hidden \e[8;97;107mTEST\e[m\n" +printf "Fg=White Bg=Red Hidden \e[8;97;41mTEST\e[m\n" +printf "Fg=White Bg=BG Hidden \e[8;97;49mTEST\e[m\n" +printf "Fg=Red Bg=Black Hidden \e[8;31;40mTEST\e[m\n" +printf "Fg=Red Bg=White Hidden \e[8;31;107mTEST\e[m\n" +printf "Fg=Red Bg=Red Hidden \e[8;31;41mTEST\e[m\n" +printf "Fg=Red Bg=BG Hidden \e[8;31;49mTEST\e[m\n" +printf "\n" +printf "Fg=Black Bg=Black Hid+Inv \e[7;8;30;40mTEST\e[m\n" +printf "Fg=Black Bg=White Hid+Inv \e[7;8;30;107mTEST\e[m\n" +printf "Fg=Black Bg=Red Hid+Inv \e[7;8;30;41mTEST\e[m\n" +printf "Fg=Black Bg=BG Hid+Inv \e[7;8;30;49mTEST\e[m\n" +printf "Fg=White Bg=Black Hid+Inv \e[7;8;97;40mTEST\e[m\n" +printf "Fg=White Bg=White Hid+Inv \e[7;8;97;107mTEST\e[m\n" +printf "Fg=White Bg=Red Hid+Inv \e[7;8;97;41mTEST\e[m\n" +printf "Fg=White Bg=BG Hid+Inv \e[7;8;97;49mTEST\e[m\n" +printf "Fg=Red Bg=Black Hid+Inv \e[7;8;31;40mTEST\e[m\n" +printf "Fg=Red Bg=White Hid+Inv \e[7;8;31;107mTEST\e[m\n" +printf "Fg=Red Bg=Red Hid+Inv \e[7;8;31;41mTEST\e[m\n" +printf "Fg=Red Bg=BG Hid+Inv \e[7;8;31;49mTEST\e[m\n" diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 68335e1c..b461db0c 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -835,12 +835,17 @@ impl<'a> RenderApi<'a> { glyph_cache.font_key }; - let glyph_key = GlyphKey { + let mut glyph_key = GlyphKey { font_key, size: glyph_cache.font_size, c: cell.c }; + // Don't render text of HIDDEN cells + if cell.flags.contains(cell::Flags::HIDDEN) { + glyph_key.c = ' '; + } + // Add cell to batch { let glyph = glyph_cache.get(glyph_key, self); diff --git a/src/term/cell.rs b/src/term/cell.rs index a04eb8e1..ef8509dc 100644 --- a/src/term/cell.rs +++ b/src/term/cell.rs @@ -18,15 +18,16 @@ use index::Column; bitflags! { #[derive(Serialize, Deserialize)] pub struct Flags: u32 { - const INVERSE = 0b0000_0001; - const BOLD = 0b0000_0010; - const ITALIC = 0b0000_0100; - const UNDERLINE = 0b0000_1000; - const WRAPLINE = 0b0001_0000; - const WIDE_CHAR = 0b0010_0000; - const WIDE_CHAR_SPACER = 0b0100_0000; - const DIM = 0b1000_0000; - const DIM_BOLD = 0b1000_0010; + const INVERSE = 0b0_0000_0001; + const BOLD = 0b0_0000_0010; + const ITALIC = 0b0_0000_0100; + const UNDERLINE = 0b0_0000_1000; + const WRAPLINE = 0b0_0001_0000; + const WIDE_CHAR = 0b0_0010_0000; + const WIDE_CHAR_SPACER = 0b0_0100_0000; + const DIM = 0b0_1000_0000; + const DIM_BOLD = 0b0_1000_0010; + const HIDDEN = 0b1_0000_0000; } } diff --git a/src/term/mod.rs b/src/term/mod.rs index f4ebf1c9..c2759802 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -14,9 +14,8 @@ // //! Exports the `Term` type which is a high-level API for the Grid use std::ops::{Range, Index, IndexMut}; -use std::ptr; +use std::{ptr, io, mem}; use std::cmp::{min, max}; -use std::io; use std::time::{Duration, Instant}; use arraydeque::ArrayDeque; @@ -424,26 +423,15 @@ impl<'a> Iterator for RenderableCellsIter<'a> { }; // Apply inversion and lookup RGB values - let mut bg_alpha = 1.0; - let fg_rgb; - let bg_rgb; + let mut fg_rgb = self.compute_fg_rgb(cell.fg, &cell); + let mut bg_rgb = self.compute_bg_rgb(cell.bg); - let invert = selected ^ cell.inverse(); - - if invert { - if cell.fg == cell.bg { - bg_rgb = self.colors[NamedColor::Foreground]; - fg_rgb = self.colors[NamedColor::Background]; - bg_alpha = 1.0 - } else { - bg_rgb = self.compute_fg_rgb(cell.fg, &cell); - fg_rgb = self.compute_bg_rgb(cell.bg); - } + let bg_alpha = if selected ^ cell.inverse() { + mem::swap(&mut fg_rgb, &mut bg_rgb); + self.compute_bg_alpha(cell.fg) } else { - fg_rgb = self.compute_fg_rgb(cell.fg, &cell); - bg_rgb = self.compute_bg_rgb(cell.bg); - bg_alpha = self.compute_bg_alpha(cell.bg); - } + self.compute_bg_alpha(cell.bg) + }; return Some(RenderableCell { line: cell.line, @@ -1877,6 +1865,8 @@ impl ansi::Handler for Term { Attr::CancelItalic => self.cursor.template.flags.remove(cell::Flags::ITALIC), Attr::Underscore => self.cursor.template.flags.insert(cell::Flags::UNDERLINE), Attr::CancelUnderline => self.cursor.template.flags.remove(cell::Flags::UNDERLINE), + Attr::Hidden => self.cursor.template.flags.insert(cell::Flags::HIDDEN), + Attr::CancelHidden => self.cursor.template.flags.remove(cell::Flags::HIDDEN), _ => { debug!("Term got unhandled attr: {:?}", attr); }