ok/jj
1
0
Fork 0
forked from mirrors/jj

formatter: add support for bold text

This commit is contained in:
Martin von Zweigbergk 2023-01-07 10:03:08 -08:00 committed by Martin von Zweigbergk
parent 3b4ed096d0
commit e93a347f9e
2 changed files with 32 additions and 8 deletions

View file

@ -42,8 +42,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* The `ui.relative-timestamps` option now also affects `jj op log`. * The `ui.relative-timestamps` option now also affects `jj op log`.
* Background colors are now supported. You can set e.g. * Background colors and bold text are now supported. You can set e.g.
`color.error = { bg = "red" }` in your `~/.jjconfig.toml`. `color.error = { bg = "red", bold = true }` in your `~/.jjconfig.toml`.
### Fixed bugs ### Fixed bugs

View file

@ -154,12 +154,14 @@ impl<W: Write> Formatter for PlainTextFormatter<W> {
pub struct Style { pub struct Style {
pub fg_color: Option<Color>, pub fg_color: Option<Color>,
pub bg_color: Option<Color>, pub bg_color: Option<Color>,
pub bold: Option<bool>,
} }
impl Style { impl Style {
fn merge(&mut self, other: &Style) { fn merge(&mut self, other: &Style) {
self.fg_color = other.fg_color.or(self.fg_color); self.fg_color = other.fg_color.or(self.fg_color);
self.bg_color = other.bg_color.or(self.bg_color); self.bg_color = other.bg_color.or(self.bg_color);
self.bold = other.bold.or(self.bold);
} }
} }
@ -238,6 +240,18 @@ impl<W: Write> ColorFormatter<W> {
} else if !is_bright(&new_style.fg_color) && is_bright(&self.current_style.fg_color) { } else if !is_bright(&new_style.fg_color) && is_bright(&self.current_style.fg_color) {
queue!(self.output, SetAttribute(Attribute::Reset))?; queue!(self.output, SetAttribute(Attribute::Reset))?;
} }
if new_style.bold != self.current_style.bold {
if new_style.bold.unwrap_or_default() {
queue!(self.output, SetAttribute(Attribute::Bold))?;
} else {
// NoBold results in double underlining on some terminals, so we use reset
// instead. However, that resets other attributes as well, so we reset
// our record of the current style so we re-apply the other attributes
// below.
queue!(self.output, SetAttribute(Attribute::Reset))?;
self.current_style = Style::default();
}
}
if new_style.fg_color != self.current_style.fg_color { if new_style.fg_color != self.current_style.fg_color {
queue!( queue!(
self.output, self.output,
@ -283,6 +297,7 @@ fn rules_from_config(config: &config::Config) -> HashMap<Vec<String>, Style> {
let style = Style { let style = Style {
fg_color: color_for_name(&color_name), fg_color: color_for_name(&color_name),
bg_color: None, bg_color: None,
bold: None,
}; };
result.insert(labels, style); result.insert(labels, style);
} }
@ -298,6 +313,11 @@ fn rules_from_config(config: &config::Config) -> HashMap<Vec<String>, Style> {
style.bg_color = color_for_name(color_name); style.bg_color = color_for_name(color_name);
} }
} }
if let Some(value) = style_table.get("bold") {
if let config::ValueKind::Boolean(value) = &value.kind {
style.bold = Some(*value);
}
}
result.insert(labels, style); result.insert(labels, style);
} }
_ => {} _ => {}
@ -457,7 +477,8 @@ mod tests {
r#" r#"
colors.red_fg = { fg = "red" } colors.red_fg = { fg = "red" }
colors.blue_bg = { bg = "blue" } colors.blue_bg = { bg = "blue" }
colors.multiple = { fg = "green", bg = "yellow" } colors.bold_font = { bold = true }
colors.multiple = { fg = "green", bg = "yellow", bold = true }
"#, "#,
); );
let mut output: Vec<u8> = vec![]; let mut output: Vec<u8> = vec![];
@ -470,6 +491,10 @@ mod tests {
formatter.write_str(" bg only ").unwrap(); formatter.write_str(" bg only ").unwrap();
formatter.remove_label().unwrap(); formatter.remove_label().unwrap();
formatter.write_str("\n").unwrap(); formatter.write_str("\n").unwrap();
formatter.add_label("bold_font").unwrap();
formatter.write_str(" bold only ").unwrap();
formatter.remove_label().unwrap();
formatter.write_str("\n").unwrap();
formatter.add_label("multiple").unwrap(); formatter.add_label("multiple").unwrap();
formatter.write_str(" single rule ").unwrap(); formatter.write_str(" single rule ").unwrap();
formatter.remove_label().unwrap(); formatter.remove_label().unwrap();
@ -483,7 +508,8 @@ mod tests {
insta::assert_snapshot!(String::from_utf8(output).unwrap(), @r###" insta::assert_snapshot!(String::from_utf8(output).unwrap(), @r###"
 fg only   fg only 
 bg only   bg only 
 single rule   bold only 
 single rule 
 two rules   two rules 
"###); "###);
} }
@ -491,11 +517,10 @@ mod tests {
#[test] #[test]
fn test_color_formatter_bold_reset() { fn test_color_formatter_bold_reset() {
// Test that we don't lose other attributes when we reset the bold attribute. // Test that we don't lose other attributes when we reset the bold attribute.
// TODO: Actually use bold instead of bright when we support that
let config = config_from_string( let config = config_from_string(
r#" r#"
colors.not_bold = { fg = "red", bg = "blue" } colors.not_bold = { fg = "red", bg = "blue" }
colors.bold_font = { fg = "bright red" } colors.bold_font = { bold = true }
"#, "#,
); );
let mut output: Vec<u8> = vec![]; let mut output: Vec<u8> = vec![];
@ -507,8 +532,7 @@ mod tests {
formatter.remove_label().unwrap(); formatter.remove_label().unwrap();
formatter.write_str(" not bold again ").unwrap(); formatter.write_str(" not bold again ").unwrap();
formatter.remove_label().unwrap(); formatter.remove_label().unwrap();
// TODO: This loses the blue background when we reset the bold attribute. insta::assert_snapshot!(String::from_utf8(output).unwrap(), @" not bold  bold  not bold again ");
insta::assert_snapshot!(String::from_utf8(output).unwrap(), @" not bold  bold  not bold again ");
} }
#[test] #[test]