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
2 changes: 1 addition & 1 deletion crates/tui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3304,7 +3304,7 @@ async fn run_doctor(config: &Config, workspace: &Path, config_path_override: Opt
}
if crate::settings::detected_legacy_windows_console_host() {
println!(
" {} legacy Windows console host → low_motion + fancy_animations=false + synchronized_output=off (auto)",
" {} legacy Windows console host → low_motion + fancy_animations=false + bracketed_paste=false + synchronized_output=off (auto)",
"•".truecolor(sky_r, sky_g, sky_b)
);
any_quirk = true;
Expand Down
5 changes: 5 additions & 0 deletions crates/tui/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ impl Settings {
if detected_legacy_windows_console_host() {
self.low_motion = true;
self.fancy_animations = false;
self.bracketed_paste = false;
Comment thread
nightt5879 marked this conversation as resolved.
Outdated
if self.synchronized_output.eq_ignore_ascii_case("auto") {
self.synchronized_output = "off".to_string();
}
Expand Down Expand Up @@ -2222,6 +2223,10 @@ mod tests {
settings.apply_env_overrides();
assert!(settings.low_motion);
assert!(!settings.fancy_animations);
assert!(
!settings.bracketed_paste,
"legacy Windows console hosts do not support crossterm bracketed paste (#1102)"
);
assert_eq!(settings.synchronized_output, "off");

// SAFETY: cleanup under the guard.
Expand Down
28 changes: 22 additions & 6 deletions crates/tui/src/tui/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ pub async fn run_tui(config: &Config, options: TuiOptions) -> Result<()> {
execute!(terminal.backend_mut(), DisableMouseCapture)?;
}
if use_bracketed_paste {
execute!(terminal.backend_mut(), DisableBracketedPaste)?;
disable_bracketed_paste_mode(terminal.backend_mut());
}
terminal.show_cursor()?;
drop(terminal);
Expand Down Expand Up @@ -1061,7 +1061,7 @@ impl Drop for TerminalCleanupGuard {
let _ = execute!(stdout, DisableMouseCapture);
}
if self.use_bracketed_paste {
let _ = execute!(stdout, DisableBracketedPaste);
disable_bracketed_paste_mode(&mut stdout);
}
let _ = execute!(stdout, crossterm::cursor::Show);
}
Expand Down Expand Up @@ -9766,7 +9766,7 @@ fn pause_terminal(
execute!(terminal.backend_mut(), DisableMouseCapture)?;
}
if use_bracketed_paste {
execute!(terminal.backend_mut(), DisableBracketedPaste)?;
disable_bracketed_paste_mode(terminal.backend_mut());
}
Ok(())
}
Expand Down Expand Up @@ -9928,7 +9928,7 @@ pub fn emergency_restore_terminal() {
pop_keyboard_enhancement_flags(&mut stdout);
disable_alternate_scroll_mode(&mut stdout);
let _ = execute!(stdout, DisableFocusChange);
let _ = execute!(stdout, DisableBracketedPaste);
disable_bracketed_paste_mode(&mut stdout);
let _ = execute!(stdout, DisableMouseCapture);
let _ = disable_raw_mode();
let _ = execute!(stdout, LeaveAlternateScreen);
Expand Down Expand Up @@ -9991,14 +9991,30 @@ fn recover_terminal_modes<W: Write>(
if use_mouse_capture && let Err(err) = execute!(writer, EnableMouseCapture) {
tracing::debug!(?err, "EnableMouseCapture ignored");
}
if use_bracketed_paste && let Err(err) = execute!(writer, EnableBracketedPaste) {
tracing::debug!(?err, "EnableBracketedPaste ignored");
if use_bracketed_paste {
try_enable_bracketed_paste_mode(writer);
}
if let Err(err) = execute!(writer, EnableFocusChange) {
tracing::debug!(?err, "EnableFocusChange ignored");
}
}

fn try_enable_bracketed_paste_mode<W: Write>(writer: &mut W) -> bool {
match execute!(writer, EnableBracketedPaste) {
Ok(()) => true,
Err(err) => {
tracing::debug!(?err, "EnableBracketedPaste ignored");
false
}
}
}

fn disable_bracketed_paste_mode<W: Write>(writer: &mut W) {
if let Err(err) = execute!(writer, DisableBracketedPaste) {
tracing::debug!(?err, "DisableBracketedPaste ignored");
}
}

fn terminal_event_needs_viewport_recapture(evt: &Event) -> bool {
matches!(evt, Event::FocusGained)
}
Expand Down
24 changes: 24 additions & 0 deletions crates/tui/src/tui/ui/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,30 @@ fn recover_terminal_modes_emits_expected_csi_sequences_with_gating() {
);
}

#[cfg(not(windows))]
#[test]
fn bracketed_paste_mode_helpers_ignore_writer_errors() {
struct FailingWriter;

impl std::io::Write for FailingWriter {
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
Err(std::io::Error::other("terminal mode unsupported"))
}

fn flush(&mut self) -> std::io::Result<()> {
Err(std::io::Error::other("terminal mode unsupported"))
}
}

let mut writer = FailingWriter;

assert!(
!try_enable_bracketed_paste_mode(&mut writer),
"unsupported bracketed paste must be reported without bubbling an error"
);
disable_bracketed_paste_mode(&mut writer);
}

#[cfg(windows)]
#[test]
fn recover_terminal_modes_runs_without_panic_on_windows() {
Expand Down
Loading