mirror of
https://github.com/openai/codex.git
synced 2026-10-21 05:22:21 +00:00
Show multiline command previews in /ps (#48101)
## Why `/ps` previously showed only the first line of each background command, hiding useful details when a command began with an opening parenthesis. ## What changed Render LF and CRLF line breaks as `↵` in command previews. Include subsequent lines within the existing 80-grapheme limit, and show the truncation marker only when the command exceeds that limit. ## Testing Update snapshot coverage for multiline commands, including parenthesized commands and CRLF line endings, and add a snapshot for a multiline command exceeding the preview limit. GitOrigin-RevId: 92544e5636821fc94bc1ca4af389c3c646127c0e
This commit is contained in:
@@ -159,17 +159,17 @@ impl HistoryCell for UnifiedExecProcessesCell {
|
||||
}
|
||||
let command = &process.command_display;
|
||||
let (snippet, snippet_truncated) = {
|
||||
let (first_line, has_more_lines) = match command.split_once('\n') {
|
||||
Some((first, _)) => (first, true),
|
||||
None => (command.as_str(), false),
|
||||
};
|
||||
let max_graphemes = 80;
|
||||
let mut graphemes = first_line.grapheme_indices(true);
|
||||
if let Some((byte_index, _)) = graphemes.nth(max_graphemes) {
|
||||
(first_line[..byte_index].to_string(), true)
|
||||
} else {
|
||||
(first_line.to_string(), has_more_lines)
|
||||
}
|
||||
let mut graphemes = command.graphemes(true);
|
||||
let snippet: String = graphemes
|
||||
.by_ref()
|
||||
.take(max_graphemes)
|
||||
.map(|grapheme| match grapheme {
|
||||
"\n" | "\r\n" => "↵",
|
||||
_ => grapheme,
|
||||
})
|
||||
.collect();
|
||||
(snippet, graphemes.next().is_some())
|
||||
};
|
||||
if wrap_width <= prefix_width {
|
||||
out.push(Line::from(prefix.dim()));
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
---
|
||||
source: tui/src/history_cell/tests.rs
|
||||
expression: rendered
|
||||
---
|
||||
/ps
|
||||
|
||||
Background terminals
|
||||
|
||||
• (↵ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [...]
|
||||
+4
-2
@@ -1,13 +1,15 @@
|
||||
---
|
||||
source: tui/src/history_cell.rs
|
||||
source: tui/src/history_cell/tests.rs
|
||||
expression: rendered
|
||||
---
|
||||
/ps
|
||||
|
||||
Background terminals
|
||||
|
||||
• echo hello [...]
|
||||
• echo hello↵and then some extra text
|
||||
↳ hello
|
||||
done
|
||||
• (↵ sleep 120↵)
|
||||
• sleep 1↵sleep 120
|
||||
• rg "foo" src
|
||||
↳ src/main.rs:12:foo
|
||||
|
||||
@@ -878,6 +878,14 @@ fn ps_output_multiline_snapshot() {
|
||||
command_display: "echo hello\nand then some extra text".to_string(),
|
||||
recent_chunks: vec!["hello".to_string(), "done".to_string()],
|
||||
},
|
||||
UnifiedExecProcessDetails {
|
||||
command_display: "(\n sleep 120\n)".to_string(),
|
||||
recent_chunks: Vec::new(),
|
||||
},
|
||||
UnifiedExecProcessDetails {
|
||||
command_display: "sleep 1\r\nsleep 120".to_string(),
|
||||
recent_chunks: Vec::new(),
|
||||
},
|
||||
UnifiedExecProcessDetails {
|
||||
command_display: "rg \"foo\" src".to_string(),
|
||||
recent_chunks: vec!["src/main.rs:12:foo".to_string()],
|
||||
@@ -887,6 +895,16 @@ fn ps_output_multiline_snapshot() {
|
||||
insta::assert_snapshot!(rendered);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ps_output_multiline_long_command_snapshot() {
|
||||
let cell = new_unified_exec_processes_output(vec![UnifiedExecProcessDetails {
|
||||
command_display: format!("(\n {}\n)", "x".repeat(100)),
|
||||
recent_chunks: Vec::new(),
|
||||
}]);
|
||||
let rendered = render_lines(&cell.display_lines(/*width*/ 100)).join("\n");
|
||||
insta::assert_snapshot!(rendered);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cyber_policy_error_event_snapshot() {
|
||||
let cell = new_cyber_policy_error_event(crate::daybreak::Notice::Apply);
|
||||
|
||||
Reference in New Issue
Block a user