Skip to content

Commit 19fa129

Browse files
authored
Merge branch 'main' into add-github-action-for-nix
2 parents fe64da9 + ddcaf3d commit 19fa129

16 files changed

+462
-190
lines changed

codex-rs/tui/src/bottom_pane/approval_overlay.rs

Lines changed: 35 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use crate::key_hint::KeyBinding;
1616
use crate::render::highlight::highlight_bash_to_lines;
1717
use crate::render::renderable::ColumnRenderable;
1818
use crate::render::renderable::Renderable;
19-
use crate::text_formatting::truncate_text;
2019
use codex_core::protocol::FileChange;
2120
use codex_core::protocol::Op;
2221
use codex_core::protocol::ReviewDecision;
@@ -105,9 +104,9 @@ impl ApprovalOverlay {
105104
),
106105
};
107106

108-
let header = Box::new(ColumnRenderable::new([
109-
Box::new(Line::from(title.bold())),
110-
Box::new(Line::from("")),
107+
let header = Box::new(ColumnRenderable::with([
108+
Line::from(title.bold()).into(),
109+
Line::from("").into(),
111110
header,
112111
]));
113112

@@ -160,11 +159,8 @@ impl ApprovalOverlay {
160159
}
161160

162161
fn handle_exec_decision(&self, id: &str, command: &[String], decision: ReviewDecision) {
163-
if let Some(lines) = build_exec_history_lines(command.to_vec(), decision) {
164-
self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new(
165-
history_cell::new_user_approval_decision(lines),
166-
)));
167-
}
162+
let cell = history_cell::new_approval_decision_cell(command.to_vec(), decision);
163+
self.app_event_tx.send(AppEvent::InsertHistoryCell(cell));
168164
self.app_event_tx.send(AppEvent::CodexOp(Op::ExecApproval {
169165
id: id.to_string(),
170166
decision,
@@ -327,7 +323,7 @@ impl From<ApprovalRequest> for ApprovalRequestState {
327323
header.push(DiffSummary::new(changes, cwd).into());
328324
Self {
329325
variant: ApprovalVariant::ApplyPatch { id },
330-
header: Box::new(ColumnRenderable::new(header)),
326+
header: Box::new(ColumnRenderable::with(header)),
331327
}
332328
}
333329
}
@@ -396,91 +392,11 @@ fn patch_options() -> Vec<ApprovalOption> {
396392
]
397393
}
398394

399-
fn build_exec_history_lines(
400-
command: Vec<String>,
401-
decision: ReviewDecision,
402-
) -> Option<Vec<Line<'static>>> {
403-
use ReviewDecision::*;
404-
405-
let (symbol, summary): (Span<'static>, Vec<Span<'static>>) = match decision {
406-
Approved => {
407-
let snippet = Span::from(exec_snippet(&command)).dim();
408-
(
409-
"✔ ".green(),
410-
vec![
411-
"You ".into(),
412-
"approved".bold(),
413-
" codex to run ".into(),
414-
snippet,
415-
" this time".bold(),
416-
],
417-
)
418-
}
419-
ApprovedForSession => {
420-
let snippet = Span::from(exec_snippet(&command)).dim();
421-
(
422-
"✔ ".green(),
423-
vec![
424-
"You ".into(),
425-
"approved".bold(),
426-
" codex to run ".into(),
427-
snippet,
428-
" every time this session".bold(),
429-
],
430-
)
431-
}
432-
Denied => {
433-
let snippet = Span::from(exec_snippet(&command)).dim();
434-
(
435-
"✗ ".red(),
436-
vec![
437-
"You ".into(),
438-
"did not approve".bold(),
439-
" codex to run ".into(),
440-
snippet,
441-
],
442-
)
443-
}
444-
Abort => {
445-
let snippet = Span::from(exec_snippet(&command)).dim();
446-
(
447-
"✗ ".red(),
448-
vec![
449-
"You ".into(),
450-
"canceled".bold(),
451-
" the request to run ".into(),
452-
snippet,
453-
],
454-
)
455-
}
456-
};
457-
458-
let mut lines = Vec::new();
459-
let mut spans = Vec::new();
460-
spans.push(symbol);
461-
spans.extend(summary);
462-
lines.push(Line::from(spans));
463-
Some(lines)
464-
}
465-
466-
fn truncate_exec_snippet(full_cmd: &str) -> String {
467-
let mut snippet = match full_cmd.split_once('\n') {
468-
Some((first, _)) => format!("{first} ..."),
469-
None => full_cmd.to_string(),
470-
};
471-
snippet = truncate_text(&snippet, 80);
472-
snippet
473-
}
474-
475-
fn exec_snippet(command: &[String]) -> String {
476-
let full_cmd = strip_bash_lc_and_escape(command);
477-
truncate_exec_snippet(&full_cmd)
478-
}
479-
480395
#[cfg(test)]
481396
mod tests {
482397
use super::*;
483398
use crate::app_event::AppEvent;
399+
use pretty_assertions::assert_eq;
484400
use tokio::sync::mpsc::unbounded_channel;
485401

486402
fn make_exec_request() -> ApprovalRequest {
@@ -550,6 +466,34 @@ mod tests {
550466
);
551467
}
552468

469+
#[test]
470+
fn exec_history_cell_wraps_with_two_space_indent() {
471+
let command = vec![
472+
"/bin/zsh".into(),
473+
"-lc".into(),
474+
"git add tui/src/render/mod.rs tui/src/render/renderable.rs".into(),
475+
];
476+
let cell = history_cell::new_approval_decision_cell(command, ReviewDecision::Approved);
477+
let lines = cell.display_lines(28);
478+
let rendered: Vec<String> = lines
479+
.iter()
480+
.map(|line| {
481+
line.spans
482+
.iter()
483+
.map(|span| span.content.as_ref())
484+
.collect::<String>()
485+
})
486+
.collect();
487+
let expected = vec![
488+
"✔ You approved codex to".to_string(),
489+
" run /bin/zsh -lc 'git add".to_string(),
490+
" tui/src/render/mod.rs tui/".to_string(),
491+
" src/render/renderable.rs'".to_string(),
492+
" this time".to_string(),
493+
];
494+
assert_eq!(rendered, expected);
495+
}
496+
553497
#[test]
554498
fn enter_sets_last_selected_index_without_dismissing() {
555499
let (tx_raw, mut rx) = unbounded_channel::<AppEvent>();

codex-rs/tui/src/bottom_pane/list_selection_view.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl ListSelectionView {
8787
if params.title.is_some() || params.subtitle.is_some() {
8888
let title = params.title.map(|title| Line::from(title.bold()));
8989
let subtitle = params.subtitle.map(|subtitle| Line::from(subtitle.dim()));
90-
header = Box::new(ColumnRenderable::new([
90+
header = Box::new(ColumnRenderable::with([
9191
header,
9292
Box::new(title),
9393
Box::new(subtitle),

codex-rs/tui/src/bottom_pane/textarea.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -799,16 +799,22 @@ impl TextArea {
799799
}
800800

801801
pub(crate) fn beginning_of_previous_word(&self) -> usize {
802-
if let Some(first_non_ws) = self.text[..self.cursor_pos].rfind(|c: char| !c.is_whitespace())
803-
{
804-
let candidate = self.text[..first_non_ws]
805-
.rfind(|c: char| c.is_whitespace())
806-
.map(|i| i + 1)
807-
.unwrap_or(0);
808-
self.adjust_pos_out_of_elements(candidate, true)
809-
} else {
810-
0
811-
}
802+
let prefix = &self.text[..self.cursor_pos];
803+
let Some((first_non_ws_idx, _)) = prefix
804+
.char_indices()
805+
.rev()
806+
.find(|&(_, ch)| !ch.is_whitespace())
807+
else {
808+
return 0;
809+
};
810+
let before = &prefix[..first_non_ws_idx];
811+
let candidate = before
812+
.char_indices()
813+
.rev()
814+
.find(|&(_, ch)| ch.is_whitespace())
815+
.map(|(idx, ch)| idx + ch.len_utf8())
816+
.unwrap_or(0);
817+
self.adjust_pos_out_of_elements(candidate, true)
812818
}
813819

814820
pub(crate) fn end_of_next_word(&self) -> usize {
@@ -1262,6 +1268,15 @@ mod tests {
12621268
assert_eq!(t.cursor(), 6);
12631269
}
12641270

1271+
#[test]
1272+
fn delete_backward_word_handles_narrow_no_break_space() {
1273+
let mut t = ta_with("32\u{202F}AM");
1274+
t.set_cursor(t.text().len());
1275+
t.input(KeyEvent::new(KeyCode::Backspace, KeyModifiers::ALT));
1276+
pretty_assertions::assert_eq!(t.text(), "32\u{202F}");
1277+
pretty_assertions::assert_eq!(t.cursor(), t.text().len());
1278+
}
1279+
12651280
#[test]
12661281
fn delete_forward_word_with_without_alt_modifier() {
12671282
let mut t = ta_with("hello world");

codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_exec_and_status_layout_vt100_snapshot.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ expression: term.backend().vt100().screen().contents()
1313

1414

1515
Summarize recent commits
16+
1617
100% context left
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
22
source: tui/src/chatwidget/tests.rs
3+
assertion_line: 495
34
expression: lines_to_single_string(&aborted_long)
45
---
5-
You canceled the request to run echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...
6+
You canceled the request to run echo
7+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...

codex-rs/tui/src/diff_render.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl From<DiffSummary> for Box<dyn Renderable> {
7272
)));
7373
}
7474

75-
Box::new(ColumnRenderable::new(rows))
75+
Box::new(ColumnRenderable::with(rows))
7676
}
7777
}
7878

0 commit comments

Comments
 (0)