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,
|
env::env_init,
|
||||||
eprintf, fprintf,
|
eprintf, fprintf,
|
||||||
input::input_terminfo_get_name,
|
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},
|
key::{self, char_to_symbol, Key},
|
||||||
panic::panic_handler,
|
panic::panic_handler,
|
||||||
print_help::print_help,
|
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.
|
// in fish-proper this is done once a command is run.
|
||||||
unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) };
|
unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) };
|
||||||
|
|
||||||
|
terminal_protocol_hacks();
|
||||||
|
|
||||||
if continuous_mode {
|
if continuous_mode {
|
||||||
eprintf!("\n");
|
eprintf!("\n");
|
||||||
eprintf!("To terminate this program type \"exit\" or \"quit\" in this window,\n");
|
eprintf!("To terminate this program type \"exit\" or \"quit\" in this window,\n");
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use libc::STDOUT_FILENO;
|
use libc::STDOUT_FILENO;
|
||||||
|
|
||||||
use crate::common::{
|
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::env::{EnvStack, Environment};
|
||||||
use crate::fd_readable_set::FdReadableSet;
|
use crate::fd_readable_set::FdReadableSet;
|
||||||
|
@ -20,6 +21,7 @@ use crate::wutil::{fish_wcstol, write_to_fd};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
use std::os::fd::RawFd;
|
use std::os::fd::RawFd;
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
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);
|
static TERMINAL_PROTOCOLS: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub(crate) static IS_TMUX: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
static IS_TMUX: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||||
pub(crate) static IN_MIDNIGHT_COMMANDER: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
static IN_MIDNIGHT_COMMANDER: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||||
pub(crate) static IN_ITERM_PRE_CSI_U: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
static IN_ITERM_PRE_CSI_U: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||||
pub(crate) static IN_WEZTERM: 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() {
|
pub fn terminal_protocols_enable_ifn() {
|
||||||
if IN_MIDNIGHT_COMMANDER.load() {
|
if IN_MIDNIGHT_COMMANDER.load() {
|
||||||
|
|
|
@ -74,11 +74,9 @@ use crate::history::{
|
||||||
SearchType,
|
SearchType,
|
||||||
};
|
};
|
||||||
use crate::input::init_input;
|
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::{
|
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::io::IoChain;
|
||||||
use crate::kill::{kill_add, kill_replace, kill_yank, kill_yank_rotate};
|
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,
|
string_prefixes_string_case_insensitive, StringFuzzyMatch,
|
||||||
};
|
};
|
||||||
use crate::wildcard::wildcard_has;
|
use crate::wildcard::wildcard_has;
|
||||||
use crate::wutil::fish_wcstol;
|
|
||||||
use crate::wutil::{fstat, perror, write_to_fd};
|
use crate::wutil::{fstat, perror, write_to_fd};
|
||||||
use crate::{abbrs, event, function, history};
|
use crate::{abbrs, event, function, history};
|
||||||
|
|
||||||
|
@ -3958,55 +3955,7 @@ fn reader_interactive_init(parser: &Parser) {
|
||||||
.vars()
|
.vars()
|
||||||
.set_one(L!("_"), EnvMode::GLOBAL, L!("fish").to_owned());
|
.set_one(L!("_"), EnvMode::GLOBAL, L!("fish").to_owned());
|
||||||
|
|
||||||
interactive_hacks(parser);
|
terminal_protocol_hacks();
|
||||||
}
|
|
||||||
|
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destroy data for interactive use.
|
/// Destroy data for interactive use.
|
||||||
|
|
Loading…
Reference in a new issue