Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 3 additions & 4 deletions codex-rs/tui/src/history_cell/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::markdown_render_cache::MarkdownRenderCache;
use super::*;
use crate::style::accent_color_on;
use crate::style::history_prompt_style;
use crate::terminal_hyperlinks::annotate_web_urls_in_line;
use crate::terminal_hyperlinks::annotate_web_urls;
use crate::terminal_hyperlinks::lines_with_sources_eq;
use crate::terminal_hyperlinks::remap_source_wrapped_line;
use crate::wrapping::url_preserving_wrap_options;
Expand Down Expand Up @@ -289,18 +289,17 @@ fn wrap_user_message(
build_user_message_lines_with_elements(message, text_elements, style, element_style)
};
let mut wrapped = crate::terminal_hyperlinks::adaptive_wrap_hyperlink_lines(
&plain_hyperlink_lines(logical_lines),
&annotate_web_urls(logical_lines),
wrap_options,
)
.into_iter()
.flat_map(|mut line| {
.flat_map(|line| {
if line.width() <= usize::from(wrap_width) {
return vec![line];
}

// Terminal autowrap loses the message gutter and background. Explicitly split
// oversized URL tokens while retaining their complete OSC-8 destination.
line.hyperlinks = annotate_web_urls_in_line(line.line.clone()).hyperlinks;
let forced_lines = word_wrap_line_with_source(
&line.line,
url_preserving_wrap_options(RtOptions::new(usize::from(wrap_width)))
Expand Down
49 changes: 49 additions & 0 deletions codex-rs/tui/src/history_cell/messages_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,55 @@ use crate::history_cell::markdown_render_cache::MarkdownRenderCacheKey;
use assert_matches::assert_matches;
use pretty_assertions::assert_eq;

#[test]
fn user_prompt_urls_keep_destinations_across_widths() {
let url = "https://example.test/terminal-link-wrapping/solid-octants";
let placeholder = "[Image #1]";
let message = format!(
"from this site, write out the ascii for solid octants 18 columns {url}\n{placeholder} See (https://example.test/a)."
);
let image_start = message.find(placeholder).unwrap();
let cell = new_user_prompt(
message,
vec![TextElement::new(
(image_start..image_start + placeholder.len()).into(),
Some(placeholder.to_string()),
)],
Vec::new(),
Vec::new(),
);
let mut snapshots = Vec::new();
for width in [120, 60, 24] {
let lines = cell.display_hyperlink_lines(width);
assert_eq!(cell.transcript_hyperlink_lines(width), lines);
assert!(lines.iter().all(|line| line.width() <= usize::from(width)));
for destination in [url, "https://example.test/a"] {
let linked_text = lines
.iter()
.flat_map(|line| {
line.hyperlinks
.iter()
.filter(|link| link.destination == destination)
.flat_map(|link| {
line.line
.to_string()
.chars()
.skip(link.columns.start)
.take(link.columns.len())
.collect::<Vec<_>>()
})
})
.collect::<String>();
assert_eq!(linked_text, destination, "width {width}");
}
snapshots.push(format!(
"width {width}\n{}",
ratatui::text::Text::from(visible_lines(lines))
));
}
insta::assert_snapshot!(snapshots.join("\n\n"));
}

#[test]
fn local_image_only_user_message_remains_visible() {
let cell = new_user_prompt(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
source: tui/src/history_cell/messages_tests.rs
expression: "snapshots.join(\"\\n\\n\")"
---
width 120

› from this site, write out the ascii for solid octants 18 columns
https://example.test/terminal-link-wrapping/solid-octants
[Image #1] See (https://example.test/a).


width 60

› from this site, write out the ascii for solid octants 18
columns
https://example.test/terminal-link-wrapping/solid-octants
[Image #1] See (https://example.test/a).


width 24

› from this site, write
out the ascii for
solid octants 18
columns
https://example.test/
terminal-link-wrappin
g/solid-octants
[Image #1] See
(https://example.test
/a).
Loading