fix insert_history modifier handling (#1774)

This fixes a bug in insert_history_lines where writing
`Line::From(vec!["A".bold(), "B".into()])` would write "B" as bold,
because "B" didn't explicitly subtract bold.
This commit is contained in:
Jeremy Rose
2025-08-01 10:37:43 -07:00
committed by GitHub
parent f918198bbb
commit 8360c6a3ec
2 changed files with 52 additions and 25 deletions

View File

@@ -545,24 +545,17 @@ impl HistoryCell {
} else {
for (idx, PlanItemArg { step, status }) in plan.into_iter().enumerate() {
let num = idx + 1;
let (icon, style): (&str, Style) = match status {
StepStatus::Completed => ("", Style::default().fg(Color::Green)),
StepStatus::InProgress => (
"",
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
),
StepStatus::Pending => ("", Style::default().fg(Color::Gray)),
let icon_span: Span = match status {
StepStatus::Completed => Span::from("").fg(Color::Green),
StepStatus::InProgress => Span::from("").fg(Color::Yellow).bold(),
StepStatus::Pending => Span::from("").fg(Color::Gray),
};
let prefix = vec![
Span::raw(format!("{num:>2}. [")),
Span::styled(icon.to_string(), style),
Span::raw("] "),
];
let mut spans = prefix;
spans.push(Span::raw(step));
lines.push(Line::from(spans));
lines.push(Line::from(vec![
format!("{num:>2}. [").into(),
icon_span,
"] ".into(),
step.into(),
]));
}
}

View File

@@ -216,18 +216,18 @@ where
{
let mut fg = Color::Reset;
let mut bg = Color::Reset;
let mut modifier = Modifier::empty();
let mut last_modifier = Modifier::empty();
for span in content {
let mut next_modifier = modifier;
next_modifier.insert(span.style.add_modifier);
next_modifier.remove(span.style.sub_modifier);
if next_modifier != modifier {
let mut modifier = Modifier::empty();
modifier.insert(span.style.add_modifier);
modifier.remove(span.style.sub_modifier);
if modifier != last_modifier {
let diff = ModifierDiff {
from: modifier,
to: next_modifier,
from: last_modifier,
to: modifier,
};
diff.queue(&mut writer)?;
modifier = next_modifier;
last_modifier = modifier;
}
let next_fg = span.style.fg.unwrap_or(Color::Reset);
let next_bg = span.style.bg.unwrap_or(Color::Reset);
@@ -250,3 +250,37 @@ where
SetAttribute(crossterm::style::Attribute::Reset),
)
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
#[test]
fn writes_bold_then_regular_spans() {
use ratatui::style::Stylize;
let spans = ["A".bold(), "B".into()];
let mut actual: Vec<u8> = Vec::new();
write_spans(&mut actual, spans.iter()).unwrap();
let mut expected: Vec<u8> = Vec::new();
queue!(
expected,
SetAttribute(crossterm::style::Attribute::Bold),
Print("A"),
SetAttribute(crossterm::style::Attribute::NormalIntensity),
Print("B"),
SetForegroundColor(CColor::Reset),
SetBackgroundColor(CColor::Reset),
SetAttribute(crossterm::style::Attribute::Reset),
)
.unwrap();
assert_eq!(
String::from_utf8(actual).unwrap(),
String::from_utf8(expected).unwrap()
);
}
}