mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 21:03:12 +00:00
Apply terminal protocol workarounds also in fish_key_reader
We don't care to check the latest value of these variables; these should only be read on startup and are not meant to be overridden by the user ever. Hence we don't need a parser.
This commit is contained in:
parent
fe3e3b3b50
commit
0d9dfb307b
3 changed files with 55 additions and 60 deletions
|
@ -19,7 +19,10 @@ use fish::{
|
|||
env::env_init,
|
||||
eprintf, fprintf,
|
||||
input::input_terminfo_get_name,
|
||||
input_common::{terminal_protocols_enable_ifn, CharEvent, InputEventQueue, InputEventQueuer},
|
||||
input_common::{
|
||||
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, InputEventQueue,
|
||||
InputEventQueuer,
|
||||
},
|
||||
key::{self, char_to_symbol, Key},
|
||||
panic::panic_handler,
|
||||
print_help::print_help,
|
||||
|
@ -136,6 +139,8 @@ fn setup_and_process_keys(continuous_mode: bool, verbose: bool) -> i32 {
|
|||
// in fish-proper this is done once a command is run.
|
||||
unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) };
|
||||
|
||||
terminal_protocol_hacks();
|
||||
|
||||
if continuous_mode {
|
||||
eprintf!("\n");
|
||||
eprintf!("To terminate this program type \"exit\" or \"quit\" in this window,\n");
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use libc::STDOUT_FILENO;
|
||||
|
||||
use crate::common::{
|
||||
fish_reserved_codepoint, is_windows_subsystem_for_linux, read_blocked, shell_modes, WSL,
|
||||
fish_reserved_codepoint, is_windows_subsystem_for_linux, read_blocked, shell_modes,
|
||||
str2wcstring, WSL,
|
||||
};
|
||||
use crate::env::{EnvStack, Environment};
|
||||
use crate::fd_readable_set::FdReadableSet;
|
||||
|
@ -20,6 +21,7 @@ use crate::wutil::{fish_wcstol, write_to_fd};
|
|||
use std::collections::VecDeque;
|
||||
use std::ops::ControlFlow;
|
||||
use std::os::fd::RawFd;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
|
||||
|
@ -427,10 +429,49 @@ pub fn update_wait_on_sequence_key_ms(vars: &EnvStack) {
|
|||
|
||||
static TERMINAL_PROTOCOLS: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub(crate) static IS_TMUX: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
pub(crate) static IN_MIDNIGHT_COMMANDER: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
pub(crate) static IN_ITERM_PRE_CSI_U: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
pub(crate) static IN_WEZTERM: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
static IS_TMUX: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
static IN_MIDNIGHT_COMMANDER: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
static IN_ITERM_PRE_CSI_U: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
static IN_WEZTERM: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
|
||||
pub fn terminal_protocol_hacks() {
|
||||
use std::env::var_os;
|
||||
IS_TMUX.store(var_os("TMUX").is_some());
|
||||
IN_MIDNIGHT_COMMANDER.store(var_os("MC_TMPDIR").is_some());
|
||||
IN_WEZTERM.store(
|
||||
var_os("TERM_PROGRAM")
|
||||
.is_some_and(|term_program| term_program.as_os_str().as_bytes() == b"WezTerm"),
|
||||
);
|
||||
IN_ITERM_PRE_CSI_U.store(
|
||||
var_os("LC_TERMINAL").is_some_and(|term| term.as_os_str().as_bytes() == b"iTerm2")
|
||||
&& var_os("LC_TERMINAL_VERSION").is_some_and(|version| {
|
||||
let Some(version) = parse_version(&str2wcstring(version.as_os_str().as_bytes()))
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
version < (3, 5, 6)
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
fn parse_version(version: &wstr) -> Option<(i64, i64, i64)> {
|
||||
let mut numbers = version.split('.');
|
||||
let major = fish_wcstol(numbers.next()?).ok()?;
|
||||
let minor = fish_wcstol(numbers.next()?).ok()?;
|
||||
let patch = numbers.next()?;
|
||||
let patch = &patch[..patch
|
||||
.chars()
|
||||
.position(|c| !c.is_ascii_digit())
|
||||
.unwrap_or(patch.len())];
|
||||
let patch = fish_wcstol(patch).ok()?;
|
||||
Some((major, minor, patch))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_version() {
|
||||
assert_eq!(parse_version(L!("3.5.2")), Some((3, 5, 2)));
|
||||
assert_eq!(parse_version(L!("3.5.3beta")), Some((3, 5, 3)));
|
||||
}
|
||||
|
||||
pub fn terminal_protocols_enable_ifn() {
|
||||
if IN_MIDNIGHT_COMMANDER.load() {
|
||||
|
|
|
@ -74,11 +74,9 @@ use crate::history::{
|
|||
SearchType,
|
||||
};
|
||||
use crate::input::init_input;
|
||||
use crate::input_common::IN_ITERM_PRE_CSI_U;
|
||||
use crate::input_common::IN_MIDNIGHT_COMMANDER;
|
||||
use crate::input_common::IN_WEZTERM;
|
||||
use crate::input_common::{
|
||||
terminal_protocols_enable_ifn, CharEvent, CharInputStyle, InputData, ReadlineCmd, IS_TMUX,
|
||||
terminal_protocol_hacks, terminal_protocols_enable_ifn, CharEvent, CharInputStyle, InputData,
|
||||
ReadlineCmd,
|
||||
};
|
||||
use crate::io::IoChain;
|
||||
use crate::kill::{kill_add, kill_replace, kill_yank, kill_yank_rotate};
|
||||
|
@ -126,7 +124,6 @@ use crate::wcstringutil::{
|
|||
string_prefixes_string_case_insensitive, StringFuzzyMatch,
|
||||
};
|
||||
use crate::wildcard::wildcard_has;
|
||||
use crate::wutil::fish_wcstol;
|
||||
use crate::wutil::{fstat, perror, write_to_fd};
|
||||
use crate::{abbrs, event, function, history};
|
||||
|
||||
|
@ -3958,55 +3955,7 @@ fn reader_interactive_init(parser: &Parser) {
|
|||
.vars()
|
||||
.set_one(L!("_"), EnvMode::GLOBAL, L!("fish").to_owned());
|
||||
|
||||
interactive_hacks(parser);
|
||||
}
|
||||
|
||||
fn interactive_hacks(parser: &Parser) {
|
||||
IS_TMUX.store(parser.vars().get_unless_empty(L!("TMUX")).is_some());
|
||||
IN_MIDNIGHT_COMMANDER.store(parser.vars().get_unless_empty(L!("MC_TMPDIR")).is_some());
|
||||
IN_WEZTERM.store(
|
||||
parser
|
||||
.vars()
|
||||
.get_unless_empty(L!("TERM_PROGRAM"))
|
||||
.is_some_and(|term_program| term_program.as_list() == [L!("WezTerm")]),
|
||||
);
|
||||
IN_ITERM_PRE_CSI_U.store(
|
||||
parser
|
||||
.vars()
|
||||
.get(L!("LC_TERMINAL"))
|
||||
.is_some_and(|term| term.as_list() == [L!("iTerm2")])
|
||||
&& parser
|
||||
.vars()
|
||||
.get(L!("LC_TERMINAL_VERSION"))
|
||||
.is_some_and(|version| {
|
||||
if version.as_list().is_empty() {
|
||||
return false;
|
||||
}
|
||||
let Some(version) = parse_version(&version.as_list()[0]) else {
|
||||
return false;
|
||||
};
|
||||
version < (3, 5, 6)
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
fn parse_version(version: &wstr) -> Option<(i64, i64, i64)> {
|
||||
let mut numbers = version.split('.');
|
||||
let major = fish_wcstol(numbers.next()?).ok()?;
|
||||
let minor = fish_wcstol(numbers.next()?).ok()?;
|
||||
let patch = numbers.next()?;
|
||||
let patch = &patch[..patch
|
||||
.chars()
|
||||
.position(|c| !c.is_ascii_digit())
|
||||
.unwrap_or(patch.len())];
|
||||
let patch = fish_wcstol(patch).ok()?;
|
||||
Some((major, minor, patch))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_version() {
|
||||
assert_eq!(parse_version(L!("3.5.2")), Some((3, 5, 2)));
|
||||
assert_eq!(parse_version(L!("3.5.3beta")), Some((3, 5, 3)));
|
||||
terminal_protocol_hacks();
|
||||
}
|
||||
|
||||
/// Destroy data for interactive use.
|
||||
|
|
Loading…
Reference in a new issue