mirror of
https://github.com/openai/codex.git
synced 2026-05-04 05:11:37 +03:00
feat: add /ps (#8279)
See snapshots for view of edge cases This is still named `UnifiedExecSessions` for consistency across the code but should be renamed to `BackgroundTerminals` in a follow-up Example: <img width="945" height="687" alt="Screenshot 2025-12-18 at 20 12 53" src="https://github.com/user-attachments/assets/92f39ff2-243c-4006-b402-e3fa9e93c952" />
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/unified_exec_footer.rs
|
||||
expression: "format!(\"{buf:?}\")"
|
||||
---
|
||||
Buffer {
|
||||
area: Rect { x: 0, y: 0, width: 50, height: 1 },
|
||||
content: [
|
||||
" 123 background terminals running · /ps to view ",
|
||||
],
|
||||
styles: [
|
||||
x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 48, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
]
|
||||
}
|
||||
@@ -1,26 +1,14 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/unified_exec_footer.rs
|
||||
assertion_line: 123
|
||||
expression: "format!(\"{buf:?}\")"
|
||||
---
|
||||
Buffer {
|
||||
area: Rect { x: 0, y: 0, width: 50, height: 3 },
|
||||
area: Rect { x: 0, y: 0, width: 50, height: 1 },
|
||||
content: [
|
||||
" Background terminal running: echo hello · rg ",
|
||||
" "foo" src · 1 more ",
|
||||
" running ",
|
||||
" 1 background terminal running · /ps to view ",
|
||||
],
|
||||
styles: [
|
||||
x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 30, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 31, y: 0, fg: Cyan, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 41, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 44, y: 0, fg: Cyan, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 46, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 31, y: 1, fg: Cyan, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 40, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 49, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 31, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 38, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 45, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/unified_exec_footer.rs
|
||||
assertion_line: 108
|
||||
expression: "format!(\"{buf:?}\")"
|
||||
---
|
||||
Buffer {
|
||||
area: Rect { x: 0, y: 0, width: 50, height: 2 },
|
||||
content: [
|
||||
" Background terminal running: echo hello · rg ",
|
||||
" "foo" src ",
|
||||
],
|
||||
styles: [
|
||||
x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 30, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 31, y: 0, fg: Cyan, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 41, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 44, y: 0, fg: Cyan, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 46, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 31, y: 1, fg: Cyan, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 40, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
]
|
||||
}
|
||||
@@ -4,13 +4,8 @@ use ratatui::style::Stylize;
|
||||
use ratatui::text::Line;
|
||||
use ratatui::widgets::Paragraph;
|
||||
|
||||
use crate::live_wrap::take_prefix_by_width;
|
||||
use crate::render::renderable::Renderable;
|
||||
use crate::text_formatting::truncate_text;
|
||||
use crate::wrapping::RtOptions;
|
||||
use crate::wrapping::word_wrap_lines;
|
||||
|
||||
const MAX_SESSION_LABEL_GRAPHEMES: usize = 48;
|
||||
const MAX_VISIBLE_SESSIONS: usize = 2;
|
||||
|
||||
pub(crate) struct UnifiedExecFooter {
|
||||
sessions: Vec<String>,
|
||||
@@ -40,34 +35,11 @@ impl UnifiedExecFooter {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let label = " Background terminal running:";
|
||||
let mut spans = Vec::new();
|
||||
spans.push(label.dim());
|
||||
spans.push(" ".into());
|
||||
|
||||
let visible = self.sessions.iter().take(MAX_VISIBLE_SESSIONS);
|
||||
let mut visible_count = 0usize;
|
||||
for (idx, command) in visible.enumerate() {
|
||||
if idx > 0 {
|
||||
spans.push(" · ".dim());
|
||||
}
|
||||
let truncated = truncate_text(command, MAX_SESSION_LABEL_GRAPHEMES);
|
||||
spans.push(truncated.cyan());
|
||||
visible_count += 1;
|
||||
}
|
||||
|
||||
let remaining = self.sessions.len().saturating_sub(visible_count);
|
||||
if remaining > 0 {
|
||||
spans.push(" · ".dim());
|
||||
spans.push(format!("{remaining} more running").dim());
|
||||
}
|
||||
|
||||
let indent = " ".repeat(label.len() + 1);
|
||||
let line = Line::from(spans);
|
||||
word_wrap_lines(
|
||||
std::iter::once(line),
|
||||
RtOptions::new(width as usize).subsequent_indent(Line::from(indent).dim()),
|
||||
)
|
||||
let count = self.sessions.len();
|
||||
let plural = if count == 1 { "" } else { "s" };
|
||||
let message = format!(" {count} background terminal{plural} running · /ps to view");
|
||||
let (truncated, _, _) = take_prefix_by_width(&message, width as usize);
|
||||
vec![Line::from(truncated.dim())]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,29 +69,25 @@ mod tests {
|
||||
assert_eq!(footer.desired_height(40), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_two_sessions() {
|
||||
let mut footer = UnifiedExecFooter::new();
|
||||
footer.set_sessions(vec!["echo hello".to_string(), "rg \"foo\" src".to_string()]);
|
||||
let width = 50;
|
||||
let height = footer.desired_height(width);
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, width, height));
|
||||
footer.render(Rect::new(0, 0, width, height), &mut buf);
|
||||
assert_snapshot!("render_two_sessions", format!("{buf:?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_more_sessions() {
|
||||
let mut footer = UnifiedExecFooter::new();
|
||||
footer.set_sessions(vec![
|
||||
"echo hello".to_string(),
|
||||
"rg \"foo\" src".to_string(),
|
||||
"cat README.md".to_string(),
|
||||
]);
|
||||
footer.set_sessions(vec!["rg \"foo\" src".to_string()]);
|
||||
let width = 50;
|
||||
let height = footer.desired_height(width);
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, width, height));
|
||||
footer.render(Rect::new(0, 0, width, height), &mut buf);
|
||||
assert_snapshot!("render_more_sessions", format!("{buf:?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_many_sessions() {
|
||||
let mut footer = UnifiedExecFooter::new();
|
||||
footer.set_sessions((0..123).map(|idx| format!("cmd {idx}")).collect());
|
||||
let width = 50;
|
||||
let height = footer.desired_height(width);
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, width, height));
|
||||
footer.render(Rect::new(0, 0, width, height), &mut buf);
|
||||
assert_snapshot!("render_many_sessions", format!("{buf:?}"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user