mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-08 02:31:18 -03:00
Use XTVERSION for terminal-specific workarounds
As mentioned in earlier commit
("Query terminal before reading config").
Closes #11812
This commit is contained in:
@@ -1693,6 +1693,10 @@ Fish also provides additional information through the values of certain environm
|
|||||||
|
|
||||||
the process ID (PID) of the shell.
|
the process ID (PID) of the shell.
|
||||||
|
|
||||||
|
.. envvar:: fish_terminal
|
||||||
|
|
||||||
|
the name and version of the terminal fish is running inside (for example as reported via :ref:`XTVERSION <term-compat-xtversion>`).
|
||||||
|
|
||||||
.. envvar:: history
|
.. envvar:: history
|
||||||
|
|
||||||
a list containing the last commands that were entered.
|
a list containing the last commands that were entered.
|
||||||
|
|||||||
@@ -224,9 +224,12 @@ Optional Commands
|
|||||||
- Ss
|
- Ss
|
||||||
- Set cursor style (DECSCUSR); Ps is 2, 4 or 6 for block, underscore or line shape.
|
- Set cursor style (DECSCUSR); Ps is 2, 4 or 6 for block, underscore or line shape.
|
||||||
- VT520
|
- VT520
|
||||||
* - ``\e[ Ps q``
|
* - .. _term-compat-xtversion:
|
||||||
|
|
||||||
|
``\e[ Ps q``
|
||||||
- n/a
|
- n/a
|
||||||
- Request terminal name and version (XTVERSION).
|
- Request terminal name and version (XTVERSION).
|
||||||
|
This is only used for temporary workarounds for incompatible terminals.
|
||||||
- XTerm
|
- XTerm
|
||||||
* - ``\e[?25h``
|
* - ``\e[?25h``
|
||||||
- cvvis
|
- cvvis
|
||||||
|
|||||||
@@ -145,16 +145,14 @@ end" >$__fish_config_dir/config.fish
|
|||||||
if not set -q fish_handle_reflow
|
if not set -q fish_handle_reflow
|
||||||
# VTE reflows the text itself, so us doing it inevitably races against it.
|
# VTE reflows the text itself, so us doing it inevitably races against it.
|
||||||
# Guidance from the VTE developers is to let them repaint.
|
# Guidance from the VTE developers is to let them repaint.
|
||||||
if set -q VTE_VERSION
|
# Konsole reflows since version 21.04. Konsole added XTVERSION
|
||||||
# Same for these terminals
|
# in v22.03.80~7.
|
||||||
|
if string match -rq -- "$fish_terminal" '^(?:VTE\b|Konsole |WezTerm )'
|
||||||
|
or begin
|
||||||
|
set -q KONSOLE_VERSION
|
||||||
|
and test "$KONSOLE_VERSION" -ge 210400 2>/dev/null
|
||||||
|
end
|
||||||
or string match -q -- 'alacritty*' $TERM
|
or string match -q -- 'alacritty*' $TERM
|
||||||
or test "$TERM_PROGRAM" = WezTerm
|
|
||||||
set -g fish_handle_reflow 0
|
|
||||||
else if set -q KONSOLE_VERSION
|
|
||||||
and test "$KONSOLE_VERSION" -ge 210400 2>/dev/null
|
|
||||||
# Konsole since version 21.04(.00)
|
|
||||||
# Note that this is optional, but since we have no way of detecting it
|
|
||||||
# we go with the default, which is true.
|
|
||||||
set -g fish_handle_reflow 0
|
set -g fish_handle_reflow 0
|
||||||
else
|
else
|
||||||
set -g fish_handle_reflow 1
|
set -g fish_handle_reflow 1
|
||||||
@@ -171,6 +169,10 @@ end" >$__fish_config_dir/config.fish
|
|||||||
if not functions --query __fish_update_cwd_osc
|
if not functions --query __fish_update_cwd_osc
|
||||||
function __fish_update_cwd_osc --on-variable PWD --description 'Notify terminals when $PWD changes'
|
function __fish_update_cwd_osc --on-variable PWD --description 'Notify terminals when $PWD changes'
|
||||||
set -l host $hostname
|
set -l host $hostname
|
||||||
|
# if set -l konsole_version (string match -r -- '^Konsole (\d+)\..*' "$fish_terminal")[2]
|
||||||
|
# # To-do: use a Konsole version where KF6_DEP_VERSION is >= 6.12
|
||||||
|
# and $konsole_version -lt ???
|
||||||
|
# end
|
||||||
if set -q KONSOLE_VERSION
|
if set -q KONSOLE_VERSION
|
||||||
set host ''
|
set host ''
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
environment::{env_init, EnvStack, Environment},
|
environment::{env_init, EnvStack, Environment},
|
||||||
EnvMode, Statuses,
|
EnvMode, Statuses,
|
||||||
},
|
},
|
||||||
|
env_dispatch::guess_emoji_width,
|
||||||
eprintf,
|
eprintf,
|
||||||
event::{self, Event},
|
event::{self, Event},
|
||||||
flog::{self, activate_flog_categories_by_pattern, set_flog_file_fd, FLOG, FLOGF},
|
flog::{self, activate_flog_categories_by_pattern, set_flog_file_fd, FLOG, FLOGF},
|
||||||
@@ -62,6 +63,7 @@
|
|||||||
signal::{signal_clear_cancel, signal_unblock_all},
|
signal::{signal_clear_cancel, signal_unblock_all},
|
||||||
threads::{self},
|
threads::{self},
|
||||||
topic_monitor,
|
topic_monitor,
|
||||||
|
tty_handoff::xtversion,
|
||||||
wchar::prelude::*,
|
wchar::prelude::*,
|
||||||
wutil::waccess,
|
wutil::waccess,
|
||||||
};
|
};
|
||||||
@@ -553,6 +555,12 @@ enum CommandSource {
|
|||||||
.pending_input
|
.pending_input
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.extend(std::mem::take(&mut input_data.queue));
|
.extend(std::mem::take(&mut input_data.queue));
|
||||||
|
parser.vars().set_one(
|
||||||
|
L!("fish_terminal"),
|
||||||
|
EnvMode::GLOBAL,
|
||||||
|
xtversion().unwrap().to_owned(),
|
||||||
|
);
|
||||||
|
guess_emoji_width(parser.vars());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !opts.no_exec && !opts.no_config {
|
if !opts.no_exec && !opts.no_config {
|
||||||
|
|||||||
1
src/env/var.rs
vendored
1
src/env/var.rs
vendored
@@ -249,6 +249,7 @@ pub struct ElectricVar {
|
|||||||
ElectricVar{name: L!("fish_kill_signal"), flags:electric::READONLY | electric::COMPUTED},
|
ElectricVar{name: L!("fish_kill_signal"), flags:electric::READONLY | electric::COMPUTED},
|
||||||
ElectricVar{name: L!("fish_killring"), flags:electric::READONLY | electric::COMPUTED},
|
ElectricVar{name: L!("fish_killring"), flags:electric::READONLY | electric::COMPUTED},
|
||||||
ElectricVar{name: L!("fish_pid"), flags:electric::READONLY},
|
ElectricVar{name: L!("fish_pid"), flags:electric::READONLY},
|
||||||
|
ElectricVar{name: L!("fish_terminal"), flags:electric::READONLY},
|
||||||
ElectricVar{name: L!("history"), flags:electric::READONLY | electric::COMPUTED},
|
ElectricVar{name: L!("history"), flags:electric::READONLY | electric::COMPUTED},
|
||||||
ElectricVar{name: L!("hostname"), flags:electric::READONLY},
|
ElectricVar{name: L!("hostname"), flags:electric::READONLY},
|
||||||
ElectricVar{name: L!("pipestatus"), flags:electric::READONLY | electric::COMPUTED},
|
ElectricVar{name: L!("pipestatus"), flags:electric::READONLY | electric::COMPUTED},
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
};
|
};
|
||||||
use crate::terminal::use_terminfo;
|
use crate::terminal::use_terminfo;
|
||||||
use crate::terminal::ColorSupport;
|
use crate::terminal::ColorSupport;
|
||||||
|
use crate::tty_handoff::xtversion;
|
||||||
use crate::wchar::prelude::*;
|
use crate::wchar::prelude::*;
|
||||||
use crate::wutil::fish_wcstoi;
|
use crate::wutil::fish_wcstoi;
|
||||||
use crate::{function, terminal};
|
use crate::{function, terminal};
|
||||||
@@ -153,7 +154,7 @@ fn handle_timezone(var_name: &wstr, vars: &EnvStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the value of [`FISH_EMOJI_WIDTH`](crate::fallback::FISH_EMOJI_WIDTH).
|
/// Update the value of [`FISH_EMOJI_WIDTH`](crate::fallback::FISH_EMOJI_WIDTH).
|
||||||
fn guess_emoji_width(vars: &EnvStack) {
|
pub fn guess_emoji_width(vars: &EnvStack) {
|
||||||
use crate::fallback::FISH_EMOJI_WIDTH;
|
use crate::fallback::FISH_EMOJI_WIDTH;
|
||||||
|
|
||||||
if let Some(width_str) = vars.get(L!("fish_emoji_width")) {
|
if let Some(width_str) = vars.get(L!("fish_emoji_width")) {
|
||||||
@@ -168,7 +169,7 @@ fn guess_emoji_width(vars: &EnvStack) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let term = vars
|
let term_program = vars
|
||||||
.get(L!("TERM_PROGRAM"))
|
.get(L!("TERM_PROGRAM"))
|
||||||
.map(|v| v.as_string())
|
.map(|v| v.as_string())
|
||||||
.unwrap_or_else(WString::new);
|
.unwrap_or_else(WString::new);
|
||||||
@@ -189,14 +190,14 @@ fn guess_emoji_width(vars: &EnvStack) {
|
|||||||
})
|
})
|
||||||
.unwrap_or(0.0);
|
.unwrap_or(0.0);
|
||||||
|
|
||||||
if term == "Apple_Terminal" && version as i32 >= 400 {
|
if xtversion().unwrap().starts_with(L!("iTerm2 ")) {
|
||||||
// Apple Terminal on High Sierra
|
|
||||||
FISH_EMOJI_WIDTH.store(2, Ordering::Relaxed);
|
|
||||||
FLOG!(term_support, "default emoji width: 2 for", term);
|
|
||||||
} else if term == "iTerm.app" {
|
|
||||||
// iTerm2 now defaults to Unicode 9 sizes for anything after macOS 10.12
|
// iTerm2 now defaults to Unicode 9 sizes for anything after macOS 10.12
|
||||||
FISH_EMOJI_WIDTH.store(2, Ordering::Relaxed);
|
FISH_EMOJI_WIDTH.store(2, Ordering::Relaxed);
|
||||||
FLOG!(term_support, "default emoji width 2 for iTerm2");
|
FLOG!(term_support, "default emoji width 2 for iTerm2");
|
||||||
|
} else if term_program == "Apple_Terminal" && version as i32 >= 400 {
|
||||||
|
// Apple Terminal on High Sierra
|
||||||
|
FISH_EMOJI_WIDTH.store(2, Ordering::Relaxed);
|
||||||
|
FLOG!(term_support, "default emoji width: 2 for", term_program);
|
||||||
} else {
|
} else {
|
||||||
// Default to whatever the system's wcwidth gives for U+1F603, but only if it's at least
|
// Default to whatever the system's wcwidth gives for U+1F603, but only if it's at least
|
||||||
// 1 and at most 2.
|
// 1 and at most 2.
|
||||||
@@ -372,7 +373,6 @@ pub fn env_dispatch_init(vars: &EnvStack) {
|
|||||||
fn run_inits(vars: &EnvStack) {
|
fn run_inits(vars: &EnvStack) {
|
||||||
init_locale(vars);
|
init_locale(vars);
|
||||||
init_terminal(vars);
|
init_terminal(vars);
|
||||||
guess_emoji_width(vars);
|
|
||||||
update_wait_on_escape_ms(vars);
|
update_wait_on_escape_ms(vars);
|
||||||
update_wait_on_sequence_key_ms(vars);
|
update_wait_on_sequence_key_ms(vars);
|
||||||
handle_read_limit_change(vars);
|
handle_read_limit_change(vars);
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
use crate::reader::reader_test_and_clear_interrupted;
|
use crate::reader::reader_test_and_clear_interrupted;
|
||||||
use crate::terminal::{SCROLL_FORWARD_SUPPORTED, SCROLL_FORWARD_TERMINFO_CODE};
|
use crate::terminal::{SCROLL_FORWARD_SUPPORTED, SCROLL_FORWARD_TERMINFO_CODE};
|
||||||
use crate::threads::iothread_port;
|
use crate::threads::iothread_port;
|
||||||
use crate::tty_handoff::{get_kitty_keyboard_capability, maybe_set_kitty_keyboard_capability};
|
use crate::tty_handoff::{
|
||||||
|
get_kitty_keyboard_capability, maybe_set_kitty_keyboard_capability, XTVERSION,
|
||||||
|
};
|
||||||
use crate::universal_notifier::default_notifier;
|
use crate::universal_notifier::default_notifier;
|
||||||
use crate::wchar::{encode_byte_to_char, prelude::*};
|
use crate::wchar::{encode_byte_to_char, prelude::*};
|
||||||
use crate::wutil::encoding::{mbrtowc, mbstate_t, zero_mbstate};
|
use crate::wutil::encoding::{mbrtowc, mbstate_t, zero_mbstate};
|
||||||
@@ -1439,13 +1441,14 @@ fn parse_xtversion(&mut self, buffer: &mut Vec<u8>) -> Option<()> {
|
|||||||
if buffer.get(3)? != &b'|' {
|
if buffer.get(3)? != &b'|' {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
FLOG!(
|
XTVERSION.get_or_init(|| {
|
||||||
reader,
|
let xtversion = str2wcstring(&buffer[4..buffer.len()]);
|
||||||
format!(
|
FLOG!(
|
||||||
"Received XTVERSION response: {}",
|
reader,
|
||||||
str2wcstring(&buffer[4..buffer.len()])
|
format!("Received XTVERSION response: {}", xtversion)
|
||||||
)
|
);
|
||||||
);
|
xtversion
|
||||||
|
});
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,7 @@
|
|||||||
tok_command, MoveWordStateMachine, MoveWordStyle, TokenType, Tokenizer, TOK_ACCEPT_UNFINISHED,
|
tok_command, MoveWordStateMachine, MoveWordStyle, TokenType, Tokenizer, TOK_ACCEPT_UNFINISHED,
|
||||||
TOK_SHOW_COMMENTS,
|
TOK_SHOW_COMMENTS,
|
||||||
};
|
};
|
||||||
|
use crate::tty_handoff::XTVERSION;
|
||||||
use crate::tty_handoff::{
|
use crate::tty_handoff::{
|
||||||
get_tty_protocols_active, initialize_tty_metadata, maybe_set_kitty_keyboard_capability,
|
get_tty_protocols_active, initialize_tty_metadata, maybe_set_kitty_keyboard_capability,
|
||||||
safe_deactivate_tty_protocols, TtyHandoff,
|
safe_deactivate_tty_protocols, TtyHandoff,
|
||||||
@@ -272,7 +273,7 @@ pub fn terminal_init() -> InputEventQueue {
|
|||||||
let mut input_queue = InputEventQueue::new(STDIN_FILENO);
|
let mut input_queue = InputEventQueue::new(STDIN_FILENO);
|
||||||
|
|
||||||
let _init_tty_metadata = ScopeGuard::new((), |()| {
|
let _init_tty_metadata = ScopeGuard::new((), |()| {
|
||||||
initialize_tty_metadata();
|
initialize_tty_metadata(XTVERSION.get_or_init(WString::new));
|
||||||
});
|
});
|
||||||
|
|
||||||
if !querying_allowed(STDIN_FILENO) {
|
if !querying_allowed(STDIN_FILENO) {
|
||||||
|
|||||||
@@ -14,13 +14,20 @@
|
|||||||
};
|
};
|
||||||
use crate::terminal::{Output, Outputter};
|
use crate::terminal::{Output, Outputter};
|
||||||
use crate::threads::assert_is_main_thread;
|
use crate::threads::assert_is_main_thread;
|
||||||
|
use crate::wchar::prelude::*;
|
||||||
use crate::wchar_ext::ToWString;
|
use crate::wchar_ext::ToWString;
|
||||||
use crate::wutil::perror;
|
use crate::wutil::{perror, wcstoi};
|
||||||
use libc::{EINVAL, ENOTTY, EPERM, STDIN_FILENO, WNOHANG};
|
use libc::{EINVAL, ENOTTY, EPERM, STDIN_FILENO, WNOHANG};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
||||||
|
|
||||||
|
pub static XTVERSION: OnceCell<WString> = OnceCell::new();
|
||||||
|
|
||||||
|
pub fn xtversion() -> Option<&'static wstr> {
|
||||||
|
XTVERSION.get().as_ref().map(|s| s.as_utfstr())
|
||||||
|
}
|
||||||
|
|
||||||
// Facts about our environment, which inform how we handle the tty.
|
// Facts about our environment, which inform how we handle the tty.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TtyMetadata {
|
pub struct TtyMetadata {
|
||||||
@@ -33,13 +40,11 @@ pub struct TtyMetadata {
|
|||||||
|
|
||||||
impl TtyMetadata {
|
impl TtyMetadata {
|
||||||
// Create a new TtyMetadata instance with the current environment.
|
// Create a new TtyMetadata instance with the current environment.
|
||||||
fn detect() -> Self {
|
fn detect(xtversion: &wstr) -> Self {
|
||||||
use std::env::var_os;
|
let in_tmux = xtversion.starts_with(L!("tmux "));
|
||||||
|
|
||||||
let in_tmux = var_os("TMUX").is_some();
|
|
||||||
|
|
||||||
// Detect iTerm2 before 3.5.12.
|
// Detect iTerm2 before 3.5.12.
|
||||||
let pre_kitty_iterm2 = get_iterm2_version().is_some_and(|v| v < (3, 5, 12));
|
let pre_kitty_iterm2 = get_iterm2_version(xtversion).is_some_and(|v| v < (3, 5, 12));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
in_tmux,
|
in_tmux,
|
||||||
pre_kitty_iterm2,
|
pre_kitty_iterm2,
|
||||||
@@ -185,30 +190,21 @@ fn tty_protocols() -> Option<&'static TtyProtocolsSet> {
|
|||||||
unsafe { TTY_PROTOCOLS.load(Ordering::Acquire).as_ref() }
|
unsafe { TTY_PROTOCOLS.load(Ordering::Acquire).as_ref() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the TTY protocols, initializing it if necessary.
|
// Initialize TTY metadata.
|
||||||
// This also initializes the terminal enable and disable serialized commands.
|
// This also initializes the terminal enable and disable serialized commands.
|
||||||
// Note in practice this is only used from the main thread - races are very unlikely.
|
pub fn initialize_tty_metadata(xtversion: &wstr) {
|
||||||
fn get_or_init_tty_protocols() -> &'static TtyProtocolsSet {
|
|
||||||
use std::sync::atomic::Ordering::{Acquire, Release};
|
use std::sync::atomic::Ordering::{Acquire, Release};
|
||||||
// Standard lazy-init pattern from rust-atomics-and-locks.
|
// Standard lazy-init pattern from rust-atomics-and-locks.
|
||||||
let mut p = TTY_PROTOCOLS.load(Acquire);
|
let mut p = TTY_PROTOCOLS.load(Acquire);
|
||||||
if p.is_null() {
|
if p.is_null() {
|
||||||
// Try to swap in a new TTY protocols set.
|
// Try to swap in a new TTY protocols set.
|
||||||
p = Box::into_raw(Box::new(TtyMetadata::detect().get_protocols()));
|
p = Box::into_raw(Box::new(TtyMetadata::detect(xtversion).get_protocols()));
|
||||||
if let Err(e) = TTY_PROTOCOLS.compare_exchange(std::ptr::null_mut(), p, Release, Acquire) {
|
if let Err(_e) = TTY_PROTOCOLS.compare_exchange(std::ptr::null_mut(), p, Release, Acquire) {
|
||||||
// Safety: p comes from Box::into_raw right above,
|
// Safety: p comes from Box::into_raw right above,
|
||||||
// and wasn't shared with any other thread.
|
// and wasn't shared with any other thread.
|
||||||
drop(unsafe { Box::from_raw(p) });
|
drop(unsafe { Box::from_raw(p) });
|
||||||
p = e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Safety: p is not null and points to a properly initialized value.
|
|
||||||
unsafe { &*p }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize TTY metadata.
|
|
||||||
pub fn initialize_tty_metadata() {
|
|
||||||
get_or_init_tty_protocols();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A marker of the current state of the tty protocols.
|
// A marker of the current state of the tty protocols.
|
||||||
@@ -563,17 +559,18 @@ fn drop(&mut self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we are running under iTerm2, get the version as a tuple of (major, minor, patch).
|
// If we are running under iTerm2, get the version as a tuple of (major, minor, patch).
|
||||||
fn get_iterm2_version() -> Option<(u32, u32, u32)> {
|
fn get_iterm2_version(xtversion: &wstr) -> Option<(u32, u32, u32)> {
|
||||||
use std::env::var;
|
// TODO split_once
|
||||||
let term = var("LC_TERMINAL").ok()?;
|
let mut xtversion = xtversion.split(' ');
|
||||||
if term != "iTerm2" {
|
let name = xtversion.next().unwrap();
|
||||||
|
let version = xtversion.next()?;
|
||||||
|
if name != "iTerm2" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let version = var("LC_TERMINAL_VERSION").ok()?;
|
|
||||||
let mut parts = version.split('.');
|
let mut parts = version.split('.');
|
||||||
Some((
|
Some((
|
||||||
parts.next()?.parse().ok()?,
|
wcstoi(parts.next()?).ok()?,
|
||||||
parts.next()?.parse().ok()?,
|
wcstoi(parts.next()?).ok()?,
|
||||||
parts.next()?.parse().ok()?,
|
wcstoi(parts.next()?).ok()?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,15 +62,12 @@ def makeenv(script_path: Path, home: Path) -> Dict[str, str]:
|
|||||||
"LANGUAGE",
|
"LANGUAGE",
|
||||||
"MC_SID",
|
"MC_SID",
|
||||||
"MC_TMPDIR",
|
"MC_TMPDIR",
|
||||||
"LC_TERMINAL",
|
|
||||||
"LC_TERMINAL_VERSION",
|
|
||||||
"COLORTERM",
|
"COLORTERM",
|
||||||
"KONSOLE_VERSION",
|
"KONSOLE_VERSION",
|
||||||
"STY",
|
"STY",
|
||||||
"TERM", # Erase this since we still respect TERM=dumb etc.
|
"TERM", # Erase this since we still respect TERM=dumb etc.
|
||||||
"TERM_PROGRAM",
|
"TERM_PROGRAM",
|
||||||
"TERM_PROGRAM_VERSION",
|
"TERM_PROGRAM_VERSION",
|
||||||
"VTE_VERSION",
|
|
||||||
]:
|
]:
|
||||||
if var in env:
|
if var in env:
|
||||||
del env[var]
|
del env[var]
|
||||||
|
|||||||
Reference in New Issue
Block a user