Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 9 additions & 2 deletions src/tui/src/ui/harness_pane/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ impl LocalSessions {
/// the notch is forwarded and *its* scrollback moves — which is the one
/// the operator means, because it holds the whole conversation rather than
/// the last screenful the emulator happened to retain;
/// - the harness enables alternate scrolling without mouse reporting (Codex),
/// - Codex does not negotiate mouse reports in current releases. Its TUI
/// consumes cursor keys to move through the transcript, so a notch becomes
/// cursor-key input even when it does not advertise alternate scrolling;
/// - another harness enables alternate scrolling without mouse reporting,
/// so the notch becomes cursor-key input as xterm's alternate-scroll mode
/// specifies;
/// - otherwise our emulator's own retained lines move instead. Not as good,
Expand All @@ -118,7 +121,11 @@ impl LocalSessions {
return;
}
}
if self.sessions.alternate_scroll(session_id) == Some(true) {
let codex = self
.sessions
.row(session_id)
.is_some_and(|row| row.provider == medulla::protocol::HarnessProvider::Codex);
if codex || self.sessions.alternate_scroll(session_id) == Some(true) {
Comment thread
senamakel marked this conversation as resolved.
Outdated
let arrow = if up { b"\x1b[A" } else { b"\x1b[B" };
let mut bytes = Vec::with_capacity(arrow.len() * rows);
for _ in 0..rows {
Expand Down
40 changes: 38 additions & 2 deletions src/tui/src/ui/harness_pane/tests/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ use super::super::LocalSessions;
/// `--session-id`, which `/bin/sh` would reject as an unknown option. Codex
/// takes no preset id, so its argv is empty and the script is the whole command.
pub(super) fn sh(script: &str) -> LaunchSpec {
sh_for(HarnessProvider::Codex, script)
}

/// A shell PTY carrying `provider` metadata for provider-specific input tests.
fn sh_for(provider: HarnessProvider, script: &str) -> LaunchSpec {
let mut env = HashMap::new();
if let Ok(path) = std::env::var("PATH") {
env.insert("PATH".to_string(), path);
}
env.insert("TERM".to_string(), "xterm-256color".to_string());
LaunchSpec {
provider: HarnessProvider::Codex,
provider,
preset: None,
bin: "/bin/sh".to_string(),
cwd: "/".to_string(),
Expand Down Expand Up @@ -291,6 +296,36 @@ fn alternate_scroll_without_mouse_reporting_gets_arrow_scroll_events() {
sessions.close(&id);
}

#[test]
fn codex_without_mouse_or_alternate_scroll_gets_arrow_scroll_events() {
let sessions = PtyManager::new();
let harnesses = harnesses(sessions.clone());
// Current Codex releases enable bracketed paste and enhanced keyboard input,
// but no longer advertise DECSET 1007. The provider still expects wheel
// scrolling to reach its transcript as cursor keys.
let id = sessions
.open(sh(
"printf '\\033[?2004hready'; sleep 0.3; cat -v; sleep 30",
))
.unwrap();

wait_for("the Codex stand-in to become ready", || {
text(&harnesses, &id).contains("ready")
});
assert_eq!(sessions.alternate_scroll(&id), Some(false));
assert!(matches!(
sessions.mouse_protocol(&id),
Some((vt100::MouseProtocolMode::None, _))
));

harnesses.scroll(&id, 3, 4, true, 3);

wait_for("Codex to receive translated wheel input", || {
text(&harnesses, &id).contains("^[[A^[[A^[[A")
});
sessions.close(&id);
}

#[test]
fn alternate_screen_without_alternate_scroll_does_not_receive_arrows() {
let sessions = PtyManager::new();
Expand Down Expand Up @@ -321,7 +356,8 @@ fn a_child_that_never_asked_for_the_mouse_gets_our_scrollback_instead() {
let harnesses = harnesses(sessions.clone());
// Enough lines to push history off a 30-row screen, and no mouse reporting.
let id = sessions
.open(sh(
.open(sh_for(
HarnessProvider::Claude,
"i=1; while [ $i -le 200 ]; do echo line-$i; i=$((i+1)); done; sleep 30",
))
.unwrap();
Expand Down
Loading