Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
11f3f7e
lighter rendering of user/agent messages
nornagon-openai Aug 26, 2025
9c659d6
wip
nornagon-openai Aug 27, 2025
8170786
wip
nornagon-openai Aug 27, 2025
1e56853
wip
nornagon-openai Aug 27, 2025
54dee3a
simplify
nornagon-openai Aug 27, 2025
792fb82
fix tests
nornagon-openai Aug 27, 2025
5159b46
agent message >
nornagon-openai Aug 27, 2025
f51eda8
warning emoji
nornagon-openai Aug 27, 2025
b2d79b9
single-line command runs
nornagon-openai Aug 27, 2025
bb45161
command wrapping
nornagon-openai Aug 27, 2025
93d9da0
diff wip
nornagon-openai Aug 28, 2025
e6ba0af
diffs
nornagon-openai Aug 28, 2025
ca93201
fix wrapping
nornagon-openai Aug 28, 2025
a25a6be
cleanup
nornagon-openai Aug 28, 2025
2567354
wip
nornagon-openai Aug 29, 2025
99dd4f2
fix spacing in textarea
nornagon-openai Aug 29, 2025
8a86495
tui: show spinner instead of bullet in Exploring header
nornagon-openai Aug 29, 2025
7ecac28
test
nornagon-openai Aug 29, 2025
e7548e2
revert status changes
nornagon-openai Aug 29, 2025
1bc20d1
placeholder
nornagon-openai Aug 29, 2025
990e997
update plan, approval spacing
nornagon-openai Aug 29, 2025
3339c3b
Merge remote-tracking branch 'origin/main' into nornagon/message-styling
nornagon-openai Aug 29, 2025
599e5d0
fix testst
nornagon-openai Aug 29, 2025
64d548b
tui: ChatComposer rect fixes and hint line; split patch history snaps…
nornagon-openai Aug 29, 2025
49d8633
remove empty test
nornagon-openai Aug 29, 2025
3a10412
test
nornagon-openai Aug 29, 2025
0f18de3
simpler test
nornagon-openai Aug 29, 2025
230bd1a
more simpler
nornagon-openai Aug 29, 2025
b8adb5a
test
nornagon-openai Aug 29, 2025
b6d38e9
tui: parse bash commands and dim some syntax
nornagon-openai Aug 29, 2025
cdfd879
fix headers
nornagon-openai Aug 29, 2025
7afe05a
better wrapping
nornagon-openai Aug 29, 2025
c312e26
diff simplify
nornagon-openai Aug 29, 2025
5bc0d64
simplify
nornagon-openai Aug 29, 2025
3da7f52
better path display
nornagon-openai Aug 29, 2025
a8d37e0
simplify diff
nornagon-openai Aug 29, 2025
d7ed1fd
better wrap in userhistorycell
nornagon-openai Aug 29, 2025
582d7fd
simplify
nornagon-openai Aug 29, 2025
27ef3c5
revert changes in tui.rs
nornagon-openai Aug 29, 2025
c21e10a
show single file for change approved
nornagon-openai Aug 29, 2025
0d96cb8
reparse commands for ideal response
nornagon-openai Aug 29, 2025
521a71b
dim output text
nornagon-openai Aug 29, 2025
861f7b5
convert binary size test to snapshot
nornagon-openai Aug 29, 2025
70b83f4
dim output text
nornagon-openai Aug 29, 2025
1aa8cec
don't try to detect image paths for normal typing
nornagon-openai Aug 30, 2025
93934a1
defensively, assume 1-char strings are not image paths
nornagon-openai Aug 30, 2025
1dbfa1f
Merge branch 'nornagon/lag' into nornagon/message-styling
nornagon-openai Aug 30, 2025
bf72447
update plan cell
nornagon-openai Sep 1, 2025
e8fc8c2
simplify
nornagon-openai Sep 1, 2025
1677132
wip
nornagon-openai Sep 1, 2025
47c9068
Merge branch 'nornagon/message-styling' into nornagon/parse-bash
nornagon-openai Sep 2, 2025
34bdfdd
Merge remote-tracking branch 'origin/main' into nornagon/parse-bash
nornagon-openai Sep 2, 2025
e700c44
Merge remote-tracking branch 'origin/main' into nornagon/parse-bash
nornagon-openai Sep 2, 2025
62c8ee3
fix
nornagon-openai Sep 2, 2025
19fd5e6
standardize on allowing hyphenation and breaking words
nornagon-openai Sep 2, 2025
59a4c63
restore no-hyphenation for bash
nornagon-openai Sep 2, 2025
92144d9
wip
nornagon-openai Sep 2, 2025
3750b6a
wip
nornagon-openai Sep 3, 2025
e2688ff
wip
nornagon-openai Sep 3, 2025
fbefb73
Merge remote-tracking branch 'origin/main' into nornagon/parse-bash
nornagon-openai Sep 3, 2025
f85f54e
wip
nornagon-openai Sep 3, 2025
6ca03b6
reorg
nornagon-openai Sep 4, 2025
d508cff
wip
nornagon-openai Sep 4, 2025
78d911f
move prefix_lines helper
nornagon-openai Sep 4, 2025
01e311b
gitignore
nornagon-openai Sep 4, 2025
54630ca
order
nornagon-openai Sep 4, 2025
79c66d9
consolidate wrapping helpers
nornagon-openai Sep 4, 2025
7508ec2
agents.md
nornagon-openai Sep 4, 2025
d9fd052
lint
nornagon-openai Sep 4, 2025
9f52dd2
better test
nornagon-openai Sep 4, 2025
c11f63a
simplify
nornagon-openai Sep 4, 2025
9e28bb4
tests
nornagon-openai Sep 4, 2025
8d2eeb1
Merge branch 'main' into nornagon/parse-bash
nornagon-openai Sep 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip
  • Loading branch information
nornagon-openai committed Sep 2, 2025
commit 92144d989c2dcff39b01b903aad71c05339e603d
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ This repo uses snapshot tests (via `insta`), especially in `codex-rs/tui`, to va

If you don’t have the tool:
- `cargo install cargo-insta`

### TUI Command Highlighting
- Always parse and syntax-highlight the entire command or script before any wrapping; never re‑highlight per wrapped chunk.
- Perform wrapping in a style‑preserving way and add visual prefixes/indents after wrapping so line breaks account for the intended gutter.
88 changes: 42 additions & 46 deletions codex-rs/tui/src/history_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ impl HistoryCell for AgentMessageCell {
let mut is_first_visual = true;
let wrap_width = width.saturating_sub(2) as usize; // account for prefix
for line in &self.lines {
let wrapped =
crate::insert_history::word_wrap_lines(std::slice::from_ref(line), wrap_width);
let wrapped = crate::insert_history::word_wrap_line(line, wrap_width);
for (i, piece) in wrapped.into_iter().enumerate() {
let mut spans = Vec::with_capacity(piece.spans.len() + 1);
spans.push(if is_first_visual && i == 0 && self.is_first_line {
Expand Down Expand Up @@ -372,8 +371,8 @@ impl ExecCell {
};
for (title, line) in call_lines {
let prefix_len = 4 + title.len() + 1; // " └ " + title + " "
let wrapped = crate::insert_history::word_wrap_lines(
&[Line::from(line)],
let wrapped = crate::insert_history::word_wrap_line(
&Line::from(line),
(width as usize).saturating_sub(prefix_len),
);
let mut first_sub = true;
Expand Down Expand Up @@ -403,7 +402,6 @@ impl ExecCell {

fn command_display_lines(&self, width: u16) -> Vec<Line<'static>> {
use textwrap::Options as TwOptions;
use textwrap::WordSplitter;

let mut lines: Vec<Line<'static>> = Vec::new();
let [call] = &self.calls.as_slice() else {
Expand Down Expand Up @@ -438,22 +436,23 @@ impl ExecCell {
branch_consumed = true;
lines.push(Line::from(vec![bullet, " ".into(), title.bold()]));

// Wrap the command line.
for (i, line) in cmd_display.lines().enumerate() {
let wrapped = textwrap::wrap(
line,
TwOptions::new(width as usize)
.initial_indent(" ")
.subsequent_indent(" ")
.word_splitter(WordSplitter::NoHyphenation),
// Highlight once, then wrap each line using a fixed 4-space
// indent for all wrapped pieces. This drops the extra continuation
// indent for simplicity while preserving styles.
let full_hl = highlight_bash_to_lines(&cmd_display);
for (i, hl_line) in full_hl.iter().enumerate() {
let wrapped = crate::insert_history::word_wrap_line(
hl_line,
(width as usize).saturating_sub(4),
);
lines.extend(wrapped.into_iter().enumerate().map(|(j, l)| {
if i == 0 && j == 0 {
Line::from(vec![" └ ".dim(), l[4..].to_string().into()])
} else {
Line::from(l.to_string())
}
}));
let initial_prefix = if i == 0 {
" └ ".dim()
} else {
" ".into()
};
let subsequent_prefix: Span<'static> = " ".into();
let prefixed = prefix_lines(wrapped, initial_prefix, subsequent_prefix);
lines.extend(prefixed);
}
}
if let Some(output) = call.output.as_ref()
Expand Down Expand Up @@ -566,6 +565,27 @@ fn line_visual_width(line: &Line<'_>) -> usize {
.sum()
}

fn prefix_lines(
lines: Vec<Line<'static>>,
initial_prefix: Span<'static>,
subsequent_prefix: Span<'static>,
) -> Vec<Line<'static>> {
lines
.into_iter()
.enumerate()
.map(|(i, mut l)| {
let mut spans = Vec::with_capacity(l.spans.len() + 1);
spans.push(if i == 0 {
initial_prefix.clone()
} else {
subsequent_prefix.clone()
});
spans.extend(l.spans.into_iter());
Line::from(spans)
})
.collect()
}

#[cfg(test)]
mod syntax_tests {
use super::*;
Expand Down Expand Up @@ -1371,33 +1391,9 @@ impl HistoryCell for PlanUpdateCell {
.into_iter()
.map(|s| s.to_string().set_style(step_style).into())
.collect();
prefix_lines(step_text, &box_str.into(), &" ".into())
prefix_lines(step_text, box_str.into(), " ".into())
};

fn prefix_lines(
lines: Vec<Line<'static>>,
initial_prefix: &Span<'static>,
subsequent_prefix: &Span<'static>,
) -> Vec<Line<'static>> {
lines
.into_iter()
.enumerate()
.map(|(i, l)| {
Line::from(
[
vec![if i == 0 {
initial_prefix.clone()
} else {
subsequent_prefix.clone()
}],
l.spans,
]
.concat(),
)
})
.collect()
}

let mut lines: Vec<Line<'static>> = vec![];
lines.push(vec!["• ".into(), "Updated Plan".bold()].into());

Expand All @@ -1418,7 +1414,7 @@ impl HistoryCell for PlanUpdateCell {
indented_lines.extend(render_step(status, step));
}
}
lines.extend(prefix_lines(indented_lines, &" └ ".into(), &" ".into()));
lines.extend(prefix_lines(indented_lines, " └ ".into(), " ".into()));

lines
}
Expand Down