feat(terminal): support styled underlines (#2730)

* feat: support styled underlines

* remove deadcode

* Add ansi_underlines config option

* Add missing variables

* Add ansi_underlines on Output and OutputBuffer

* Fix tests

* Add separate styled underline enum

* Remove ansi_underlines from fg and bg

* Remove unneeded variables

* Rename ansi_underlines -> styled_underlines

* Simplify CharacterStyles::new()

* Move styled_underlines config description

* Fix single underline and remove extra field on CharacterStyles

* Read styled-underlines flag from cli opts

* remove extra attribute left from merge conflict

---------

Co-authored-by: Mike Lloyd <mike.lloyd03@pm.me>
Co-authored-by: Mike Lloyd <49411532+mike-lloyd03@users.noreply.github.com>
Co-authored-by: Aram Drevekenin <aram@poor.dev>
This commit is contained in:
Eatgrass 2023-11-05 08:30:35 -06:00 committed by GitHub
parent 3942000e86
commit 7f87d93a43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 155 additions and 18 deletions

View file

@ -83,6 +83,7 @@ fn serialize_chunks_with_newlines(
character_chunks: Vec<CharacterChunk>, character_chunks: Vec<CharacterChunk>,
_sixel_chunks: Option<&Vec<SixelImageChunk>>, // TODO: fix this sometime _sixel_chunks: Option<&Vec<SixelImageChunk>>, // TODO: fix this sometime
link_handler: Option<&mut Rc<RefCell<LinkHandler>>>, link_handler: Option<&mut Rc<RefCell<LinkHandler>>>,
styled_underlines: bool,
) -> Result<String> { ) -> Result<String> {
let err_context = || "failed to serialize input chunks".to_string(); let err_context = || "failed to serialize input chunks".to_string();
@ -90,7 +91,8 @@ fn serialize_chunks_with_newlines(
let link_handler = link_handler.map(|l_h| l_h.borrow()); let link_handler = link_handler.map(|l_h| l_h.borrow());
for character_chunk in character_chunks { for character_chunk in character_chunks {
let chunk_changed_colors = character_chunk.changed_colors(); let chunk_changed_colors = character_chunk.changed_colors();
let mut character_styles = CharacterStyles::new(); let mut character_styles =
CharacterStyles::new().enable_styled_underlines(styled_underlines);
vte_output.push_str("\n\r"); vte_output.push_str("\n\r");
let mut chunk_width = character_chunk.x; let mut chunk_width = character_chunk.x;
for t_character in character_chunk.terminal_characters.iter() { for t_character in character_chunk.terminal_characters.iter() {
@ -120,6 +122,7 @@ fn serialize_chunks(
sixel_chunks: Option<&Vec<SixelImageChunk>>, sixel_chunks: Option<&Vec<SixelImageChunk>>,
link_handler: Option<&mut Rc<RefCell<LinkHandler>>>, link_handler: Option<&mut Rc<RefCell<LinkHandler>>>,
sixel_image_store: Option<&mut SixelImageStore>, sixel_image_store: Option<&mut SixelImageStore>,
styled_underlines: bool,
) -> Result<String> { ) -> Result<String> {
let err_context = || "failed to serialize input chunks".to_string(); let err_context = || "failed to serialize input chunks".to_string();
@ -128,7 +131,8 @@ fn serialize_chunks(
let link_handler = link_handler.map(|l_h| l_h.borrow()); let link_handler = link_handler.map(|l_h| l_h.borrow());
for character_chunk in character_chunks { for character_chunk in character_chunks {
let chunk_changed_colors = character_chunk.changed_colors(); let chunk_changed_colors = character_chunk.changed_colors();
let mut character_styles = CharacterStyles::new(); let mut character_styles =
CharacterStyles::new().enable_styled_underlines(styled_underlines);
vte_goto_instruction(character_chunk.x, character_chunk.y, &mut vte_output) vte_goto_instruction(character_chunk.x, character_chunk.y, &mut vte_output)
.with_context(err_context)?; .with_context(err_context)?;
let mut chunk_width = character_chunk.x; let mut chunk_width = character_chunk.x;
@ -245,16 +249,19 @@ pub struct Output {
sixel_image_store: Rc<RefCell<SixelImageStore>>, sixel_image_store: Rc<RefCell<SixelImageStore>>,
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>, character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
floating_panes_stack: Option<FloatingPanesStack>, floating_panes_stack: Option<FloatingPanesStack>,
styled_underlines: bool,
} }
impl Output { impl Output {
pub fn new( pub fn new(
sixel_image_store: Rc<RefCell<SixelImageStore>>, sixel_image_store: Rc<RefCell<SixelImageStore>>,
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>, character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
styled_underlines: bool,
) -> Self { ) -> Self {
Output { Output {
sixel_image_store, sixel_image_store,
character_cell_size, character_cell_size,
styled_underlines,
..Default::default() ..Default::default()
} }
} }
@ -417,6 +424,7 @@ impl Output {
self.sixel_chunks.get(&client_id), self.sixel_chunks.get(&client_id),
self.link_handler.as_mut(), self.link_handler.as_mut(),
Some(&mut self.sixel_image_store.borrow_mut()), Some(&mut self.sixel_image_store.borrow_mut()),
self.styled_underlines,
) )
.with_context(err_context)?, .with_context(err_context)?,
); // TODO: less allocations? ); // TODO: less allocations?
@ -869,6 +877,7 @@ impl CharacterChunk {
pub struct OutputBuffer { pub struct OutputBuffer {
pub changed_lines: HashSet<usize>, // line index pub changed_lines: HashSet<usize>, // line index
pub should_update_all_lines: bool, pub should_update_all_lines: bool,
styled_underlines: bool,
} }
impl Default for OutputBuffer { impl Default for OutputBuffer {
@ -876,6 +885,7 @@ impl Default for OutputBuffer {
OutputBuffer { OutputBuffer {
changed_lines: HashSet::new(), changed_lines: HashSet::new(),
should_update_all_lines: true, // first time we should do a full render should_update_all_lines: true, // first time we should do a full render
styled_underlines: true,
} }
} }
} }
@ -913,7 +923,7 @@ impl OutputBuffer {
let y = line_index; let y = line_index;
chunks.push(CharacterChunk::new(terminal_characters, x, y)); chunks.push(CharacterChunk::new(terminal_characters, x, y));
} }
serialize_chunks_with_newlines(chunks, None, None) serialize_chunks_with_newlines(chunks, None, None, self.styled_underlines)
} }
pub fn changed_chunks_in_viewport( pub fn changed_chunks_in_viewport(
&self, &self,

View file

@ -21,6 +21,7 @@ pub const EMPTY_TERMINAL_CHARACTER: TerminalCharacter = TerminalCharacter {
pub const RESET_STYLES: CharacterStyles = CharacterStyles { pub const RESET_STYLES: CharacterStyles = CharacterStyles {
foreground: Some(AnsiCode::Reset), foreground: Some(AnsiCode::Reset),
background: Some(AnsiCode::Reset), background: Some(AnsiCode::Reset),
underline_color: Some(AnsiCode::Reset),
strike: Some(AnsiCode::Reset), strike: Some(AnsiCode::Reset),
hidden: Some(AnsiCode::Reset), hidden: Some(AnsiCode::Reset),
reverse: Some(AnsiCode::Reset), reverse: Some(AnsiCode::Reset),
@ -31,6 +32,7 @@ pub const RESET_STYLES: CharacterStyles = CharacterStyles {
dim: Some(AnsiCode::Reset), dim: Some(AnsiCode::Reset),
italic: Some(AnsiCode::Reset), italic: Some(AnsiCode::Reset),
link_anchor: Some(LinkAnchor::End), link_anchor: Some(LinkAnchor::End),
styled_underlines_enabled: false,
}; };
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -40,6 +42,15 @@ pub enum AnsiCode {
NamedColor(NamedColor), NamedColor(NamedColor),
RgbCode((u8, u8, u8)), RgbCode((u8, u8, u8)),
ColorIndex(u8), ColorIndex(u8),
Underline(Option<AnsiStyledUnderline>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AnsiStyledUnderline {
Double,
Undercurl,
Underdotted,
Underdashed,
} }
impl From<PaletteColor> for AnsiCode { impl From<PaletteColor> for AnsiCode {
@ -122,6 +133,7 @@ impl NamedColor {
pub struct CharacterStyles { pub struct CharacterStyles {
pub foreground: Option<AnsiCode>, pub foreground: Option<AnsiCode>,
pub background: Option<AnsiCode>, pub background: Option<AnsiCode>,
pub underline_color: Option<AnsiCode>,
pub strike: Option<AnsiCode>, pub strike: Option<AnsiCode>,
pub hidden: Option<AnsiCode>, pub hidden: Option<AnsiCode>,
pub reverse: Option<AnsiCode>, pub reverse: Option<AnsiCode>,
@ -132,6 +144,7 @@ pub struct CharacterStyles {
pub dim: Option<AnsiCode>, pub dim: Option<AnsiCode>,
pub italic: Option<AnsiCode>, pub italic: Option<AnsiCode>,
pub link_anchor: Option<LinkAnchor>, pub link_anchor: Option<LinkAnchor>,
pub styled_underlines_enabled: bool,
} }
impl CharacterStyles { impl CharacterStyles {
@ -146,6 +159,10 @@ impl CharacterStyles {
self.background = background_code; self.background = background_code;
self self
} }
pub fn underline_color(mut self, underline_color_code: Option<AnsiCode>) -> Self {
self.underline_color = underline_color_code;
self
}
pub fn bold(mut self, bold_code: Option<AnsiCode>) -> Self { pub fn bold(mut self, bold_code: Option<AnsiCode>) -> Self {
self.bold = bold_code; self.bold = bold_code;
self self
@ -186,9 +203,14 @@ impl CharacterStyles {
self.link_anchor = link_anchor; self.link_anchor = link_anchor;
self self
} }
pub fn enable_styled_underlines(mut self, enabled: bool) -> Self {
self.styled_underlines_enabled = enabled;
self
}
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.foreground = None; self.foreground = None;
self.background = None; self.background = None;
self.underline_color = None;
self.strike = None; self.strike = None;
self.hidden = None; self.hidden = None;
self.reverse = None; self.reverse = None;
@ -215,7 +237,8 @@ impl CharacterStyles {
} }
// create diff from all changed styles // create diff from all changed styles
let mut diff = CharacterStyles::new(); let mut diff =
CharacterStyles::new().enable_styled_underlines(self.styled_underlines_enabled);
if self.foreground != new_styles.foreground { if self.foreground != new_styles.foreground {
diff.foreground = new_styles.foreground; diff.foreground = new_styles.foreground;
@ -223,6 +246,9 @@ impl CharacterStyles {
if self.background != new_styles.background { if self.background != new_styles.background {
diff.background = new_styles.background; diff.background = new_styles.background;
} }
if self.underline_color != new_styles.underline_color {
diff.underline_color = new_styles.underline_color;
}
if self.strike != new_styles.strike { if self.strike != new_styles.strike {
diff.strike = new_styles.strike; diff.strike = new_styles.strike;
} }
@ -274,6 +300,7 @@ impl CharacterStyles {
pub fn reset_all(&mut self) { pub fn reset_all(&mut self) {
self.foreground = Some(AnsiCode::Reset); self.foreground = Some(AnsiCode::Reset);
self.background = Some(AnsiCode::Reset); self.background = Some(AnsiCode::Reset);
self.underline_color = Some(AnsiCode::Reset);
self.bold = Some(AnsiCode::Reset); self.bold = Some(AnsiCode::Reset);
self.dim = Some(AnsiCode::Reset); self.dim = Some(AnsiCode::Reset);
self.italic = Some(AnsiCode::Reset); self.italic = Some(AnsiCode::Reset);
@ -291,7 +318,28 @@ impl CharacterStyles {
[1] => *self = self.bold(Some(AnsiCode::On)), [1] => *self = self.bold(Some(AnsiCode::On)),
[2] => *self = self.dim(Some(AnsiCode::On)), [2] => *self = self.dim(Some(AnsiCode::On)),
[3] => *self = self.italic(Some(AnsiCode::On)), [3] => *self = self.italic(Some(AnsiCode::On)),
[4] => *self = self.underline(Some(AnsiCode::On)), [4, 0] => *self = self.underline(Some(AnsiCode::Reset)),
[4, 1] => *self = self.underline(Some(AnsiCode::Underline(None))),
[4, 2] => {
*self =
self.underline(Some(AnsiCode::Underline(Some(AnsiStyledUnderline::Double))))
},
[4, 3] => {
*self = self.underline(Some(AnsiCode::Underline(Some(
AnsiStyledUnderline::Undercurl,
))))
},
[4, 4] => {
*self = self.underline(Some(AnsiCode::Underline(Some(
AnsiStyledUnderline::Underdotted,
))))
},
[4, 5] => {
*self = self.underline(Some(AnsiCode::Underline(Some(
AnsiStyledUnderline::Underdashed,
))))
},
[4] => *self = self.underline(Some(AnsiCode::Underline(None))),
[5] => *self = self.blink_slow(Some(AnsiCode::On)), [5] => *self = self.blink_slow(Some(AnsiCode::On)),
[6] => *self = self.blink_fast(Some(AnsiCode::On)), [6] => *self = self.blink_fast(Some(AnsiCode::On)),
[7] => *self = self.reverse(Some(AnsiCode::On)), [7] => *self = self.reverse(Some(AnsiCode::On)),
@ -357,6 +405,21 @@ impl CharacterStyles {
} }
}, },
[49] => *self = self.background(Some(AnsiCode::Reset)), [49] => *self = self.background(Some(AnsiCode::Reset)),
[58] => {
let mut iter = params.map(|param| param[0]);
if let Some(ansi_code) = parse_sgr_color(&mut iter) {
*self = self.underline_color(Some(ansi_code));
}
},
[58, params @ ..] => {
let rgb_start = if params.len() > 4 { 2 } else { 1 };
let rgb_iter = params[rgb_start..].iter().copied();
let mut iter = std::iter::once(params[0]).chain(rgb_iter);
if let Some(ansi_code) = parse_sgr_color(&mut iter) {
*self = self.underline_color(Some(ansi_code));
}
},
[59] => *self = self.underline_color(Some(AnsiCode::Reset)),
[90] => { [90] => {
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::BrightBlack))) *self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::BrightBlack)))
}, },
@ -409,6 +472,7 @@ impl Display for CharacterStyles {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if self.foreground == Some(AnsiCode::Reset) if self.foreground == Some(AnsiCode::Reset)
&& self.background == Some(AnsiCode::Reset) && self.background == Some(AnsiCode::Reset)
&& self.underline_color == Some(AnsiCode::Reset)
&& self.strike == Some(AnsiCode::Reset) && self.strike == Some(AnsiCode::Reset)
&& self.hidden == Some(AnsiCode::Reset) && self.hidden == Some(AnsiCode::Reset)
&& self.reverse == Some(AnsiCode::Reset) && self.reverse == Some(AnsiCode::Reset)
@ -456,6 +520,22 @@ impl Display for CharacterStyles {
_ => {}, _ => {},
} }
} }
if self.styled_underlines_enabled {
if let Some(ansi_code) = self.underline_color {
match ansi_code {
AnsiCode::RgbCode((r, g, b)) => {
write!(f, "\u{1b}[58;2;{};{};{}m", r, g, b)?;
},
AnsiCode::ColorIndex(color_index) => {
write!(f, "\u{1b}[58;5;{}m", color_index)?;
},
AnsiCode::Reset => {
write!(f, "\u{1b}[59m")?;
},
_ => {},
}
};
}
if let Some(ansi_code) = self.strike { if let Some(ansi_code) = self.strike {
match ansi_code { match ansi_code {
AnsiCode::On => { AnsiCode::On => {
@ -529,15 +609,34 @@ impl Display for CharacterStyles {
// otherwise // otherwise
if let Some(ansi_code) = self.underline { if let Some(ansi_code) = self.underline {
match ansi_code { match ansi_code {
AnsiCode::On => { AnsiCode::Underline(None) => {
write!(f, "\u{1b}[4m")?; write!(f, "\u{1b}[4m")?;
}, },
AnsiCode::Underline(Some(styled)) => {
if self.styled_underlines_enabled {
match styled {
AnsiStyledUnderline::Double => {
write!(f, "\u{1b}[4:2m")?;
},
AnsiStyledUnderline::Undercurl => {
write!(f, "\u{1b}[4:3m")?;
},
AnsiStyledUnderline::Underdotted => {
write!(f, "\u{1b}[4:4m")?;
},
AnsiStyledUnderline::Underdashed => {
write!(f, "\u{1b}[4:5m")?;
},
}
}
},
AnsiCode::Reset => { AnsiCode::Reset => {
write!(f, "\u{1b}[24m")?; write!(f, "\u{1b}[24m")?;
}, },
_ => {}, _ => {},
} }
} }
if let Some(ansi_code) = self.dim { if let Some(ansi_code) = self.dim {
match ansi_code { match ansi_code {
AnsiCode::On => { AnsiCode::On => {

View file

@ -566,6 +566,7 @@ pub(crate) struct Screen {
// its creation time // its creation time
default_layout: Box<Layout>, default_layout: Box<Layout>,
default_shell: Option<PathBuf>, default_shell: Option<PathBuf>,
styled_underlines: bool,
arrow_fonts: bool, arrow_fonts: bool,
} }
@ -586,6 +587,7 @@ impl Screen {
session_serialization: bool, session_serialization: bool,
serialize_pane_viewport: bool, serialize_pane_viewport: bool,
scrollback_lines_to_serialize: Option<usize>, scrollback_lines_to_serialize: Option<usize>,
styled_underlines: bool,
arrow_fonts: bool, arrow_fonts: bool,
) -> Self { ) -> Self {
let session_name = mode_info.session_name.clone().unwrap_or_default(); let session_name = mode_info.session_name.clone().unwrap_or_default();
@ -622,6 +624,7 @@ impl Screen {
session_serialization, session_serialization,
serialize_pane_viewport, serialize_pane_viewport,
scrollback_lines_to_serialize, scrollback_lines_to_serialize,
styled_underlines,
arrow_fonts, arrow_fonts,
resurrectable_sessions, resurrectable_sessions,
} }
@ -1032,6 +1035,7 @@ impl Screen {
let mut output = Output::new( let mut output = Output::new(
self.sixel_image_store.clone(), self.sixel_image_store.clone(),
self.character_cell_size.clone(), self.character_cell_size.clone(),
self.styled_underlines,
); );
let mut tabs_to_close = vec![]; let mut tabs_to_close = vec![];
for (tab_index, tab) in &mut self.tabs { for (tab_index, tab) in &mut self.tabs {
@ -2067,6 +2071,7 @@ pub(crate) fn screen_thread_main(
config_options.copy_clipboard.unwrap_or_default(), config_options.copy_clipboard.unwrap_or_default(),
config_options.copy_on_select.unwrap_or(true), config_options.copy_on_select.unwrap_or(true),
); );
let styled_underlines = config_options.styled_underlines.unwrap_or(true);
let thread_senders = bus.senders.clone(); let thread_senders = bus.senders.clone();
let mut screen = Screen::new( let mut screen = Screen::new(
@ -2091,6 +2096,7 @@ pub(crate) fn screen_thread_main(
session_serialization, session_serialization,
serialize_pane_viewport, serialize_pane_viewport,
scrollback_lines_to_serialize, scrollback_lines_to_serialize,
styled_underlines,
arrow_fonts, arrow_fonts,
); );

View file

@ -2049,7 +2049,7 @@ fn move_floating_pane_with_sixel_image() {
width: 8, width: 8,
height: 21, height: 21,
}))); })));
let mut output = Output::new(sixel_image_store.clone(), character_cell_size); let mut output = Output::new(sixel_image_store.clone(), character_cell_size, true);
tab.toggle_floating_panes(Some(client_id), None).unwrap(); tab.toggle_floating_panes(Some(client_id), None).unwrap();
tab.new_pane(new_pane_id, None, None, None, Some(client_id)) tab.new_pane(new_pane_id, None, None, None, Some(client_id))
@ -2087,7 +2087,7 @@ fn floating_pane_above_sixel_image() {
width: 8, width: 8,
height: 21, height: 21,
}))); })));
let mut output = Output::new(sixel_image_store.clone(), character_cell_size); let mut output = Output::new(sixel_image_store.clone(), character_cell_size, true);
tab.toggle_floating_panes(Some(client_id), None).unwrap(); tab.toggle_floating_panes(Some(client_id), None).unwrap();
tab.new_pane(new_pane_id, None, None, None, Some(client_id)) tab.new_pane(new_pane_id, None, None, None, Some(client_id))

View file

@ -244,6 +244,7 @@ fn create_new_screen(size: Size) -> Screen {
let scrollback_lines_to_serialize = None; let scrollback_lines_to_serialize = None;
let debug = false; let debug = false;
let styled_underlines = true;
let arrow_fonts = true; let arrow_fonts = true;
let screen = Screen::new( let screen = Screen::new(
bus, bus,
@ -260,6 +261,7 @@ fn create_new_screen(size: Size) -> Screen {
session_serialization, session_serialization,
serialize_pane_viewport, serialize_pane_viewport,
scrollback_lines_to_serialize, scrollback_lines_to_serialize,
styled_underlines,
arrow_fonts, arrow_fonts,
); );
screen screen

View file

@ -343,3 +343,9 @@ plugins {
// The folder in which Zellij will look for themes // The folder in which Zellij will look for themes
// //
// theme_dir "/path/to/my/theme_dir" // theme_dir "/path/to/my/theme_dir"
// Enable or disable the rendering of styled and colored underlines (undercurl).
// May need to be disabled for certain unsupported terminals
// Default: true
//
// styled_underlines false

View file

@ -142,6 +142,11 @@ pub struct Options {
#[clap(long, value_parser)] #[clap(long, value_parser)]
#[serde(default)] #[serde(default)]
pub scrollback_lines_to_serialize: Option<usize>, pub scrollback_lines_to_serialize: Option<usize>,
/// Whether to use ANSI styled underlines
#[clap(long, value_parser)]
#[serde(default)]
pub styled_underlines: Option<bool>,
} }
#[derive(ArgEnum, Deserialize, Serialize, Debug, Clone, Copy, PartialEq)] #[derive(ArgEnum, Deserialize, Serialize, Debug, Clone, Copy, PartialEq)]
@ -212,6 +217,7 @@ impl Options {
let scrollback_lines_to_serialize = other let scrollback_lines_to_serialize = other
.scrollback_lines_to_serialize .scrollback_lines_to_serialize
.or(self.scrollback_lines_to_serialize); .or(self.scrollback_lines_to_serialize);
let styled_underlines = other.styled_underlines.or(self.styled_underlines);
Options { Options {
simplified_ui, simplified_ui,
@ -237,6 +243,7 @@ impl Options {
session_serialization, session_serialization,
serialize_pane_viewport, serialize_pane_viewport,
scrollback_lines_to_serialize, scrollback_lines_to_serialize,
styled_underlines,
} }
} }
@ -287,6 +294,7 @@ impl Options {
let scrollback_lines_to_serialize = other let scrollback_lines_to_serialize = other
.scrollback_lines_to_serialize .scrollback_lines_to_serialize
.or_else(|| self.scrollback_lines_to_serialize.clone()); .or_else(|| self.scrollback_lines_to_serialize.clone());
let styled_underlines = other.styled_underlines.or(self.styled_underlines);
Options { Options {
simplified_ui, simplified_ui,
@ -312,6 +320,7 @@ impl Options {
session_serialization, session_serialization,
serialize_pane_viewport, serialize_pane_viewport,
scrollback_lines_to_serialize, scrollback_lines_to_serialize,
styled_underlines,
} }
} }
@ -374,6 +383,7 @@ impl From<CliOptions> for Options {
session_serialization: opts.session_serialization, session_serialization: opts.session_serialization,
serialize_pane_viewport: opts.serialize_pane_viewport, serialize_pane_viewport: opts.serialize_pane_viewport,
scrollback_lines_to_serialize: opts.scrollback_lines_to_serialize, scrollback_lines_to_serialize: opts.scrollback_lines_to_serialize,
styled_underlines: opts.styled_underlines,
..Default::default() ..Default::default()
} }
} }

View file

@ -1438,6 +1438,9 @@ impl Options {
let scrollback_lines_to_serialize = let scrollback_lines_to_serialize =
kdl_property_first_arg_as_i64_or_error!(kdl_options, "scrollback_lines_to_serialize") kdl_property_first_arg_as_i64_or_error!(kdl_options, "scrollback_lines_to_serialize")
.map(|(v, _)| v as usize); .map(|(v, _)| v as usize);
let styled_underlines =
kdl_property_first_arg_as_bool_or_error!(kdl_options, "styled_underlines")
.map(|(v, _)| v);
Ok(Options { Ok(Options {
simplified_ui, simplified_ui,
theme, theme,
@ -1462,6 +1465,7 @@ impl Options {
session_serialization, session_serialization,
serialize_pane_viewport, serialize_pane_viewport,
scrollback_lines_to_serialize, scrollback_lines_to_serialize,
styled_underlines,
}) })
} }
} }

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 686
expression: "format!(\"{:#?}\", options)" expression: "format!(\"{:#?}\", options)"
--- ---
Options { Options {
@ -29,4 +28,5 @@ Options {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
} }

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 714
expression: "format!(\"{:#?}\", options)" expression: "format!(\"{:#?}\", options)"
--- ---
Options { Options {
@ -29,4 +28,5 @@ Options {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
} }

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 673
expression: "format!(\"{:#?}\", options)" expression: "format!(\"{:#?}\", options)"
--- ---
Options { Options {
@ -27,4 +26,5 @@ Options {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
} }

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 671
expression: "format!(\"{:#?}\", config)" expression: "format!(\"{:#?}\", config)"
--- ---
Config { Config {
@ -3592,6 +3591,7 @@ Config {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
}, },
themes: {}, themes: {},
plugins: { plugins: {

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 729
expression: "format!(\"{:#?}\", config)" expression: "format!(\"{:#?}\", config)"
--- ---
Config { Config {
@ -3592,6 +3591,7 @@ Config {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
}, },
themes: {}, themes: {},
plugins: { plugins: {

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 785
expression: "format!(\"{:#?}\", config)" expression: "format!(\"{:#?}\", config)"
--- ---
Config { Config {
@ -85,6 +84,7 @@ Config {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
}, },
themes: {}, themes: {},
plugins: { plugins: {

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 696
expression: "format!(\"{:#?}\", options)" expression: "format!(\"{:#?}\", options)"
--- ---
Options { Options {
@ -29,4 +28,5 @@ Options {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
} }

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 757
expression: "format!(\"{:#?}\", config)" expression: "format!(\"{:#?}\", config)"
--- ---
Config { Config {
@ -3592,6 +3591,7 @@ Config {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
}, },
themes: {}, themes: {},
plugins: { plugins: {

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 771
expression: "format!(\"{:#?}\", config)" expression: "format!(\"{:#?}\", config)"
--- ---
Config { Config {
@ -3592,6 +3591,7 @@ Config {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
}, },
themes: { themes: {
"other-theme-from-config": Theme { "other-theme-from-config": Theme {

View file

@ -1,6 +1,5 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 743
expression: "format!(\"{:#?}\", config)" expression: "format!(\"{:#?}\", config)"
--- ---
Config { Config {
@ -3592,6 +3591,7 @@ Config {
session_serialization: None, session_serialization: None,
serialize_pane_viewport: None, serialize_pane_viewport: None,
scrollback_lines_to_serialize: None, scrollback_lines_to_serialize: None,
styled_underlines: None,
}, },
themes: {}, themes: {},
plugins: { plugins: {