Skip to content
Open
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
11 changes: 6 additions & 5 deletions crates/tui/src/tui/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,11 @@ impl HistoryCell {

/// Render with an explicit per-cell fold override for thinking cells.
///
/// Uses XOR with the `verbose` flag so that pressing Space toggles
/// the collapsed state *relative* to the global setting:
/// - verbose off (default): thinking is collapsed; Space unfolds it
/// - verbose on: thinking is expanded; Space folds it
/// Space toggles the collapsed state *relative* to the expanded
/// baseline, which is on when either the session is verbose or the
/// thinking default is expanded:
/// - baseline off (default): thinking is collapsed; Space unfolds it
/// - baseline on: thinking is expanded; Space folds it
pub fn lines_with_options_folded(
&self,
width: u16,
Expand All @@ -432,7 +433,7 @@ impl HistoryCell {
streaming,
duration_secs,
} => {
let collapsed = folded ^ !options.verbose ^ options.thinking_default_expanded;
let collapsed = folded ^ !(options.verbose || options.thinking_default_expanded);
let (lines, expandable) = thinking::render_thinking_with_preview_limit(
content,
width,
Expand Down
41 changes: 41 additions & 0 deletions crates/tui/src/tui/history/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,47 @@ fn reasoning_folds_in_live_and_the_fold_is_reversible() {
}
}

/// The fold toggle is relative to the expanded baseline (verbose session or
/// expanded default): Space inverts the baseline, never the other flag.
/// In particular verbose plus an expanded default renders expanded — the
/// old triple-XOR collapsed exactly that cell.
#[test]
fn thinking_fold_toggle_is_relative_to_the_expanded_baseline() {
let body = (1..=20)
.map(|i| format!("step {i:02}: baseline check"))
.collect::<Vec<_>>()
.join("\n");
let cell = HistoryCell::Thinking {
content: body,
streaming: false,
duration_secs: Some(1.0),
};
// (folded, verbose, default_expanded, expect_expanded)
for (folded, verbose, default_expanded, expect_expanded) in [
(false, false, false, false),
(false, false, true, true),
(false, true, false, true),
(false, true, true, true),
(true, false, false, true),
(true, false, true, false),
(true, true, false, false),
(true, true, true, false),
] {
let options = TranscriptRenderOptions {
verbose,
thinking_default_expanded: default_expanded,
low_motion: true,
..TranscriptRenderOptions::default()
};
let text = lines_text(&cell.lines_with_options_folded(80, options, folded).0);
let expanded = text.contains("step 20: baseline check");
assert_eq!(
expanded, expect_expanded,
"[folded={folded} verbose={verbose} default_expanded={default_expanded}]"
);
}
}

/// A completed reasoning cell short enough to fit needs no expand affordance,
/// and the live view must still show it — the alternative was a dead card that
/// said reasoning happened and nothing about what it was.
Expand Down
Loading