From 7724d3499be5bb1a15d4e687f618295add89db83 Mon Sep 17 00:00:00 2001 From: Christopher Bayliss Date: Thu, 16 May 2024 08:20:05 +1000 Subject: [PATCH] avoid cnorm on certain terminals using a terminfo's cnorm doesn't reset the cursor for many terminals, see issue: #10089 --- helix-tui/src/backend/crossterm.rs | 33 +++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/helix-tui/src/backend/crossterm.rs b/helix-tui/src/backend/crossterm.rs index c5c95bff0b838..e02e1001bcaa1 100644 --- a/helix-tui/src/backend/crossterm.rs +++ b/helix-tui/src/backend/crossterm.rs @@ -23,13 +23,39 @@ use std::{ fmt, io::{self, Write}, }; +use termini::TermInfo; fn term_program() -> Option { - std::env::var("TERM_PROGRAM").ok() + // Some terminals don't set $TERM_PROGRAM + match std::env::var("TERM_PROGRAM") { + Err(_) => std::env::var("TERM").ok(), + Ok(term_program) => Some(term_program), + } } fn vte_version() -> Option { std::env::var("VTE_VERSION").ok()?.parse().ok() } +fn reset_cursor_approach(terminfo: TermInfo, fallback: &str) -> String { + let mut reset_str: String = Default::default(); + if let Some(termini::Value::Utf8String(reset_str_se)) = terminfo.extended_cap("Se") { + reset_str.push_str(reset_str_se); + } + + reset_str.push_str( + terminfo + .utf8_string_cap(termini::StringCapability::CursorNormal) + .unwrap_or(fallback), + ); + + match term_program().as_deref() { + // some terminals don't reset the cursor with either cnorm or Se + Some("tmux") => { + reset_str.push_str(fallback); + reset_str + } + _ => reset_str, + } +} /// Describes terminal capabilities like extended underline, truecolor, etc. #[derive(Clone, Debug)] @@ -69,10 +95,7 @@ impl Capabilities { || t.extended_cap("Su").is_some() || vte_version() >= Some(5102) || matches!(term_program().as_deref(), Some("WezTerm")), - reset_cursor_command: t - .utf8_string_cap(termini::StringCapability::CursorNormal) - .unwrap_or("\x1B[0 q") - .to_string(), + reset_cursor_command: reset_cursor_approach(t, "\x1B[0 q"), }, } }