mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
feat(tui/exec): make gutter ❯ turn black on Ran; only show leading └ for first combined command; tint completed command lines for clarity
This commit is contained in:
@@ -6755,8 +6755,9 @@ impl WidgetRef for &ChatWidget<'_> {
|
|||||||
// Executed arrow – color reflects exec state
|
// Executed arrow – color reflects exec state
|
||||||
if let Some(exec) = item.as_any().downcast_ref::<crate::history_cell::ExecCell>() {
|
if let Some(exec) = item.as_any().downcast_ref::<crate::history_cell::ExecCell>() {
|
||||||
match &exec.output {
|
match &exec.output {
|
||||||
None => crate::colors::info(), // Running...
|
None => crate::colors::info(), // Running...
|
||||||
Some(o) if o.exit_code == 0 => crate::colors::text_bright(), // Ran
|
// On successful completion, turn the gutter arrow solid black
|
||||||
|
Some(o) if o.exit_code == 0 => ratatui::style::Color::Black, // Ran
|
||||||
Some(_) => crate::colors::error(),
|
Some(_) => crate::colors::error(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1431,22 +1431,30 @@ impl HistoryCell for MergedExecCell {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut added_corner = false;
|
||||||
for (pre_raw, out_raw) in &self.segments {
|
for (pre_raw, out_raw) in &self.segments {
|
||||||
// Build preamble like the renderer: trim, drop first header line, ensure prefix
|
// Build preamble like the renderer: trim, drop first header line, ensure prefix
|
||||||
let mut pre = trim_empty_lines(pre_raw.clone());
|
let mut pre = trim_empty_lines(pre_raw.clone());
|
||||||
if !pre.is_empty() {
|
if !pre.is_empty() {
|
||||||
pre.remove(0);
|
pre.remove(0);
|
||||||
}
|
}
|
||||||
if let Some(first) = pre.first_mut() {
|
if !added_corner {
|
||||||
let flat: String = first.spans.iter().map(|s| s.content.as_ref()).collect();
|
if let Some(first) = pre.first_mut() {
|
||||||
let already =
|
let flat: String =
|
||||||
flat.trim_start().starts_with("└ ") || flat.trim_start().starts_with(" └ ");
|
first.spans.iter().map(|s| s.content.as_ref()).collect();
|
||||||
if !already {
|
let already = flat.trim_start().starts_with("└ ")
|
||||||
first.spans.insert(
|
|| flat.trim_start().starts_with(" └ ");
|
||||||
0,
|
if !already {
|
||||||
Span::styled("└ ", Style::default().fg(crate::colors::text_dim())),
|
first.spans.insert(
|
||||||
);
|
0,
|
||||||
|
Span::styled(
|
||||||
|
"└ ",
|
||||||
|
Style::default().fg(crate::colors::text_dim()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
added_corner = true;
|
||||||
}
|
}
|
||||||
let out = trim_empty_lines(out_raw.clone());
|
let out = trim_empty_lines(out_raw.clone());
|
||||||
let pre_rows: u16 = Paragraph::new(Text::from(pre))
|
let pre_rows: u16 = Paragraph::new(Text::from(pre))
|
||||||
@@ -1533,8 +1541,12 @@ impl HistoryCell for MergedExecCell {
|
|||||||
skip_rows = skip_rows.saturating_sub(1);
|
skip_rows = skip_rows.saturating_sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: ensure the first visible line of `lines` begins with a dim "└ "
|
// Helper: ensure only the very first preamble line across all segments gets the corner
|
||||||
let ensure_prefix = |lines: &mut Vec<Line<'static>>| {
|
let mut added_corner: bool = false;
|
||||||
|
let mut ensure_prefix = |lines: &mut Vec<Line<'static>>| {
|
||||||
|
if added_corner {
|
||||||
|
return; // do not add on subsequent segments
|
||||||
|
}
|
||||||
if let Some(first) = lines.first_mut() {
|
if let Some(first) = lines.first_mut() {
|
||||||
let flat: String = first.spans.iter().map(|s| s.content.as_ref()).collect();
|
let flat: String = first.spans.iter().map(|s| s.content.as_ref()).collect();
|
||||||
let already =
|
let already =
|
||||||
@@ -1545,6 +1557,7 @@ impl HistoryCell for MergedExecCell {
|
|||||||
Span::styled("└ ", Style::default().fg(crate::colors::text_dim())),
|
Span::styled("└ ", Style::default().fg(crate::colors::text_dim())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
added_corner = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1678,7 +1691,7 @@ impl HistoryCell for MergedExecCell {
|
|||||||
if !pre.is_empty() {
|
if !pre.is_empty() {
|
||||||
pre.remove(0);
|
pre.remove(0);
|
||||||
}
|
}
|
||||||
// Normalize command prefix for generic execs
|
// Normalize command prefix for generic execs (only on the first segment)
|
||||||
ensure_prefix(&mut pre);
|
ensure_prefix(&mut pre);
|
||||||
|
|
||||||
let out = trim_empty_lines(out_raw.clone());
|
let out = trim_empty_lines(out_raw.clone());
|
||||||
@@ -4743,11 +4756,23 @@ fn new_parsed_command(
|
|||||||
let mut hl =
|
let mut hl =
|
||||||
crate::syntax_highlight::highlight_code_block(line_text, Some("bash"));
|
crate::syntax_highlight::highlight_code_block(line_text, Some("bash"));
|
||||||
if let Some(mut first) = hl.pop() {
|
if let Some(mut first) = hl.pop() {
|
||||||
spans.extend(first.spans.drain(..));
|
// If the exec has completed ("Ran"), render command in a unified
|
||||||
|
// completed color to make the state change clear; otherwise keep
|
||||||
|
// full syntax highlighting while running.
|
||||||
|
if output.is_some() {
|
||||||
|
for s in first.spans.drain(..) {
|
||||||
|
spans.push(Span::styled(
|
||||||
|
s.content.to_string(),
|
||||||
|
Style::default().fg(crate::colors::text_bright()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spans.extend(first.spans.drain(..));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
line_text.to_string(),
|
line_text.to_string(),
|
||||||
Style::default().fg(crate::colors::text()),
|
Style::default().fg(if output.is_some() { crate::colors::text_bright() } else { crate::colors::text() }),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user