Remove dead code checking for uninitialized terminal

See 75f7cda6ab (Add xterm-256color fallback, 2024-01-28).
This commit is contained in:
Johannes Altmanninger
2025-04-06 21:30:31 +02:00
parent 594daf8f64
commit 423a5a20ba
6 changed files with 56 additions and 89 deletions

View File

@@ -4,7 +4,7 @@
use crate::color::RgbColor;
use crate::common::str2wcstring;
use crate::output::{self, Outputter};
use crate::terminal::{self, Term};
use crate::terminal::{self, term, Term};
#[allow(clippy::too_many_arguments)]
fn print_modifiers(
@@ -79,9 +79,16 @@ fn print_colors(
let term = terminal::term();
for color_name in args {
if streams.out_is_terminal() {
if let Some(term) = term.as_ref() {
print_modifiers(outp, term, bold, underline, italics, dim, reverse, bg);
}
print_modifiers(
outp,
term.as_ref(),
bold,
underline,
italics,
dim,
reverse,
bg,
);
let color = RgbColor::from_wstr(color_name).unwrap_or(RgbColor::NONE);
outp.set_color(color, RgbColor::NONE);
if !bg.is_none() {
@@ -92,9 +99,7 @@ fn print_colors(
if !bg.is_none() {
// If we have a background, stop it after the color
// or it goes to the end of the line and looks ugly.
if let Some(term) = term.as_ref() {
outp.tputs_if_some(&term.exit_attribute_mode);
}
outp.tputs_if_some(&term.exit_attribute_mode);
}
outp.writech('\n');
} // conveniently, 'normal' is always the last color so we don't need to reset here
@@ -217,9 +222,7 @@ pub fn set_color(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -
// Test if we have at least basic support for setting fonts, colors and related bits - otherwise
// just give up...
let Some(term) = terminal::term() else {
return Err(STATUS_CMD_ERROR);
};
let term = term();
let Some(exit_attribute_mode) = &term.exit_attribute_mode else {
return Err(STATUS_CMD_ERROR);
};

View File

@@ -382,7 +382,7 @@ fn update_fish_color_support(vars: &EnvStack) {
.get(L!("TERM"))
.map(|v| v.as_string())
.unwrap_or_else(WString::new);
let max_colors = terminal::term().and_then(|term| term.max_colors);
let max_colors = terminal::term().max_colors;
let mut supports_256color = false;
let mut supports_24bit = false;
@@ -578,9 +578,7 @@ fn init_terminal(vars: &EnvStack) {
apply_non_term_hacks(vars);
// Store some global variables that reflect the term's capabilities
if let Some(term) = terminal::term() {
TERM_HAS_XN.store(term.eat_newline_glitch, Ordering::Relaxed);
}
TERM_HAS_XN.store(terminal::term().eat_newline_glitch, Ordering::Relaxed);
update_fish_color_support(vars);
// Invalidate the cached escape sequences since they may no longer be valid.

View File

@@ -2,7 +2,7 @@
use crate::color::{self, RgbColor};
use crate::common::{self, wcs2string_appending};
use crate::env::EnvVar;
use crate::terminal::{self, tparm1, Term};
use crate::terminal::{tparm1, Term};
use crate::threads::MainThread;
use crate::wchar::prelude::*;
use bitflags::bitflags;
@@ -173,18 +173,15 @@ fn maybe_flush(&mut self) {
/// Unconditionally write the color string to the output.
/// Exported for builtin_set_color's usage only.
pub fn write_color(&mut self, color: RgbColor, is_fg: bool) -> bool {
let Some(term) = terminal::term() else {
return false;
};
let term: &Term = &term;
let term = crate::terminal::term();
let supports_term24bit = get_color_support().contains(ColorSupport::TERM_24BIT);
if !supports_term24bit || !color.is_rgb() {
// Indexed or non-24 bit color.
let idx = index_for_color(color);
if is_fg {
return write_foreground_color(self, idx, term);
return write_foreground_color(self, idx, &term);
} else {
return write_background_color(self, idx, term);
return write_background_color(self, idx, &term);
};
}
@@ -223,10 +220,7 @@ pub fn write_color(&mut self, color: RgbColor, is_fg: bool) -> bool {
pub fn set_color(&mut self, mut fg: RgbColor, mut bg: RgbColor) {
// Test if we have at least basic support for setting fonts, colors and related bits - otherwise
// just give up...
let Some(term) = terminal::term() else {
return;
};
let term: &Term = &term;
let term = crate::terminal::term();
let Term {
enter_bold_mode,
enter_underline_mode,
@@ -238,7 +232,7 @@ pub fn set_color(&mut self, mut fg: RgbColor, mut bg: RgbColor) {
enter_standout_mode,
exit_attribute_mode,
..
} = term;
} = &*term;
let Some(exit_attribute_mode) = exit_attribute_mode else {
return;
};
@@ -261,7 +255,7 @@ pub fn set_color(&mut self, mut fg: RgbColor, mut bg: RgbColor) {
self.reset_modes();
// If we exit attribute mode, we must first set a color, or previously colored text might
// lose its color. Terminals are weird...
write_foreground_color(self, 0, term);
write_foreground_color(self, 0, &term);
self.tputs(exit_attribute_mode);
return;
}
@@ -304,7 +298,7 @@ pub fn set_color(&mut self, mut fg: RgbColor, mut bg: RgbColor) {
self.tputs(exit_attribute_mode);
self.reset_modes();
// We don't know if exit_attribute_mode resets colors, so we set it to something known.
if write_foreground_color(self, 0, term) {
if write_foreground_color(self, 0, &term) {
self.last_color = RgbColor::BLACK;
}
}
@@ -312,7 +306,7 @@ pub fn set_color(&mut self, mut fg: RgbColor, mut bg: RgbColor) {
if self.last_color != fg {
if fg.is_normal() {
write_foreground_color(self, 0, term);
write_foreground_color(self, 0, &term);
self.tputs(exit_attribute_mode);
self.last_color2 = RgbColor::NORMAL;
@@ -325,7 +319,7 @@ pub fn set_color(&mut self, mut fg: RgbColor, mut bg: RgbColor) {
if self.last_color2 != bg {
if bg.is_normal() {
write_background_color(self, 0, term);
write_background_color(self, 0, &term);
self.tputs(exit_attribute_mode);
if !self.last_color.is_normal() {

View File

@@ -18,7 +18,6 @@
use crate::reader::{fish_is_unwinding_for_exit, reader_schedule_prompt_repaint};
use crate::redirection::RedirectionSpecList;
use crate::signal::{signal_set_handlers_once, Signal};
use crate::terminal::term;
use crate::threads::MainThread;
use crate::topic_monitor::{topic_monitor_principal, GenerationsList, Topic};
use crate::wait_handle::{InternalJobId, WaitHandle, WaitHandleRef, WaitHandleStore};
@@ -1214,7 +1213,7 @@ pub fn set_job_control_mode(mode: JobControl) {
/// Notify the user about stopped or terminated jobs, and delete completed jobs from the job list.
/// If `interactive` is set, allow removing interactive jobs; otherwise skip them.
/// Return whether text was printed to stdout.
pub fn job_reap(parser: &Parser, allow_interactive: bool) -> bool {
pub fn job_reap(parser: &Parser, interactive: bool) -> bool {
parser.assert_can_execute();
// Early out for the common case that there are no jobs.
@@ -1223,7 +1222,7 @@ pub fn job_reap(parser: &Parser, allow_interactive: bool) -> bool {
}
process_mark_finished_children(parser, false /* not block_ok */);
process_clean_after_marking(parser, allow_interactive)
process_clean_after_marking(parser, interactive)
}
/// Return the list of background jobs which we should warn the user about, if the user attempts to
@@ -1774,7 +1773,7 @@ fn save_wait_handle_for_completed_job(job: &Job, store: &mut WaitHandleStore) {
/// Remove completed jobs from the job list, printing status messages as appropriate.
/// Return whether something was printed.
fn process_clean_after_marking(parser: &Parser, allow_interactive: bool) -> bool {
fn process_clean_after_marking(parser: &Parser, interactive: bool) -> bool {
parser.assert_can_execute();
// This function may fire an event handler, we do not want to call ourselves recursively (to
@@ -1785,10 +1784,6 @@ fn process_clean_after_marking(parser: &Parser, allow_interactive: bool) -> bool
let _cleaning = parser.push_scope(|s| s.is_cleaning_procs = true);
// This may be invoked in an exit handler, after the TERM has been torn down
// Don't try to print in that case (#3222)
let interactive = allow_interactive && term().is_some();
// Remove all disowned jobs.
remove_disowned_jobs(&mut parser.jobs_mut());

View File

@@ -667,7 +667,6 @@ pub fn reset_abandoning_line(&mut self, screen_width: usize) {
// omitted_newline_char in common.rs.
let non_space_width = get_omitted_newline_width();
let term = term();
let term = term.as_ref();
// We do `>` rather than `>=` because the code below might require one extra space.
if screen_width > non_space_width {
let mut justgrey = true;
@@ -678,18 +677,15 @@ pub fn reset_abandoning_line(&mut self, screen_width: usize) {
abandon_line_string.push_utfstr(&str2wcstring(s.as_bytes()));
true
};
if let Some(enter_dim_mode) = term.and_then(|term| term.enter_dim_mode.as_ref()) {
if let Some(enter_dim_mode) = term.enter_dim_mode.as_ref() {
if add(&mut abandon_line_string, Some(enter_dim_mode.clone())) {
// Use dim if they have it, so the color will be based on their actual normal
// color and the background of the terminal.
justgrey = false;
}
}
if let (true, Some(set_a_foreground)) = (
justgrey,
term.and_then(|term| term.set_a_foreground.as_ref()),
) {
let max_colors = term.unwrap().max_colors.unwrap_or_default();
if let (true, Some(set_a_foreground)) = (justgrey, term.set_a_foreground.as_ref()) {
let max_colors = term.max_colors.unwrap_or_default();
if max_colors >= 238 {
// draw the string in a particular grey
add(&mut abandon_line_string, tparm1(set_a_foreground, 237));
@@ -697,7 +693,7 @@ pub fn reset_abandoning_line(&mut self, screen_width: usize) {
// bright black (the ninth color, looks grey)
add(&mut abandon_line_string, tparm1(set_a_foreground, 8));
} else if max_colors >= 2 {
if let Some(enter_bold_mode) = term.unwrap().enter_bold_mode.as_ref() {
if let Some(enter_bold_mode) = term.enter_bold_mode.as_ref() {
// we might still get that color by setting black and going bold for bright
add(&mut abandon_line_string, Some(enter_bold_mode.clone()));
add(&mut abandon_line_string, tparm1(set_a_foreground, 0));
@@ -707,9 +703,7 @@ pub fn reset_abandoning_line(&mut self, screen_width: usize) {
abandon_line_string.push_utfstr(&get_omitted_newline_str());
if let Some(exit_attribute_mode) =
term.and_then(|term| term.exit_attribute_mode.as_ref())
{
if let Some(exit_attribute_mode) = term.exit_attribute_mode.as_ref() {
// normal text ANSI escape sequence
add(&mut abandon_line_string, Some(exit_attribute_mode.clone()));
}
@@ -739,7 +733,7 @@ pub fn reset_abandoning_line(&mut self, screen_width: usize) {
// pasting your terminal log becomes a pain. This commit clears that line, making it an
// actual empty line.
if !is_dumb() {
if let Some(clr_eol) = term.unwrap().clr_eol.as_ref() {
if let Some(clr_eol) = term.clr_eol.as_ref() {
abandon_line_string.push_utfstr(&str2wcstring(clr_eol.as_bytes()));
}
}
@@ -909,10 +903,7 @@ fn do_move(&mut self, new_x: usize, new_y: usize) {
let y_steps =
isize::try_from(new_y).unwrap() - isize::try_from(self.actual.cursor.y).unwrap();
let Some(term) = term() else {
return;
};
let term = term.as_ref();
let term = term();
let s = if y_steps < 0 {
term.cursor_up.as_ref()
@@ -1101,12 +1092,11 @@ fn update(
}
let term = term();
let term = term.as_ref();
// Output the left prompt if it has changed.
if self.scrolled() && !is_final_rendering {
self.r#move(0, 0);
self.write_mbs_if_some(&term.and_then(|term| term.clr_eol.as_ref()));
self.write_mbs_if_some(&term.clr_eol.as_ref());
self.actual_left_prompt = None;
self.actual.cursor.x = 0;
} else if self
@@ -1130,7 +1120,7 @@ fn update(
|| (self.scrolled() && is_final_rendering)
{
for (i, &line_break) in left_prompt_layout.line_breaks.iter().enumerate() {
self.write_mbs_if_some(&term.and_then(|term| term.clr_eol.as_ref()));
self.write_mbs_if_some(&term.clr_eol);
if i == 0 {
osc_133_prompt_start(self);
}
@@ -1167,7 +1157,7 @@ fn s_line(zelf: &Screen, i: usize) -> &Line {
// Don't issue clr_eos if we think the cursor will end up in the last column - see #6951.
let should_clear_screen_this_line = need_clear_screen
&& i + 1 == self.desired.line_count()
&& term.is_some_and(|term| term.clr_eos.is_some())
&& term.clr_eos.is_some()
&& !(self.desired.cursor.x == 0
&& self.desired.cursor.y == self.desired.line_count());
@@ -1184,11 +1174,11 @@ fn s_line(zelf: &Screen, i: usize) -> &Line {
if shared_prefix < o_line(self, i).indentation {
if o_line(self, i).indentation > s_line(self, i).indentation
&& !has_cleared_screen
&& term.is_some_and(|term| term.clr_eol.is_some() && term.clr_eos.is_some())
&& term.clr_eol.is_some()
&& term.clr_eos.is_some()
{
set_color(self, HighlightSpec::new());
self.r#move(0, i);
let term = term.unwrap();
self.write_mbs_if_some(if should_clear_screen_this_line {
&term.clr_eos
} else {
@@ -1248,7 +1238,7 @@ fn s_line(zelf: &Screen, i: usize) -> &Line {
{
set_color(self, HighlightSpec::new());
self.r#move(current_width, i);
self.write_mbs_if_some(&term.and_then(|term| term.clr_eos.as_ref()));
self.write_mbs_if_some(&term.clr_eos.as_ref());
has_cleared_screen = true;
}
if done {
@@ -1291,9 +1281,7 @@ fn s_line(zelf: &Screen, i: usize) -> &Line {
// This means that we switch background correctly on the next,
// including our weird implicit bolding.
set_color(self, HighlightSpec::new());
if let (true, Some(clr_eol)) =
(clear_remainder, term.and_then(|term| term.clr_eol.as_ref()))
{
if let (true, Some(clr_eol)) = (clear_remainder, term.clr_eol.as_ref()) {
self.r#move(current_width, i);
self.write_mbs(clr_eol);
}
@@ -1332,11 +1320,9 @@ fn s_line(zelf: &Screen, i: usize) -> &Line {
}
// Clear remaining lines (if any) if we haven't cleared the screen.
if let (false, true, Some(clr_eol)) = (
has_cleared_screen,
need_clear_screen,
term.and_then(|term| term.clr_eol.as_ref()),
) {
if let (false, true, Some(clr_eol)) =
(has_cleared_screen, need_clear_screen, term.clr_eol.as_ref())
{
set_color(self, HighlightSpec::new());
for i in self.desired.line_count()..lines_with_stuff {
self.r#move(0, i);
@@ -1366,7 +1352,7 @@ pub fn mtime_stdout_stderr() -> (Option<SystemTime>, Option<SystemTime>) {
pub fn screen_force_clear_to_end() {
Outputter::stdoutput()
.borrow_mut()
.tputs_if_some(&term().unwrap().clr_eos);
.tputs_if_some(&term().clr_eos);
}
/// Information about the layout of a prompt.
@@ -1587,7 +1573,6 @@ pub fn escape_code_length(code: &wstr) -> Option<usize> {
pub fn screen_clear() -> WString {
term()
.unwrap()
.clear_screen
.as_ref()
.map(|clear_screen| str2wcstring(clear_screen.as_bytes()))
@@ -1621,7 +1606,7 @@ fn try_sequence(seq: &[u8], s: &wstr) -> usize {
/// Returns the number of columns left until the next tab stop, given the current cursor position.
fn next_tab_stop(current_line_width: usize) -> usize {
// Assume tab stops every 8 characters if undefined.
let tab_width = term().unwrap().init_tabs.unwrap_or(8);
let tab_width = term().init_tabs.unwrap_or(8);
((current_line_width / tab_width) + 1) * tab_width
}
@@ -1629,7 +1614,7 @@ fn next_tab_stop(current_line_width: usize) -> usize {
/// physical line on a wrapped logical line; instead we just output it.
fn allow_soft_wrap() -> bool {
// Should we be looking at eat_newline_glitch as well?
term().unwrap().auto_right_margin
term().auto_right_margin
}
/// Does this look like the escape sequence for setting a screen name?
@@ -1747,7 +1732,7 @@ fn is_csi_style_escape_seq(code: &wstr) -> Option<usize> {
/// Detect whether the escape sequence sets one of the terminal attributes that affects how text is
/// displayed other than the color.
fn is_visual_escape_seq(code: &wstr) -> Option<usize> {
let term = term()?;
let term = term();
let esc2 = [
&term.enter_bold_mode,
&term.exit_attribute_mode,
@@ -1930,12 +1915,11 @@ fn line_shared_prefix(a: &Line, b: &Line) -> usize {
/// Returns true if we are using a dumb terminal.
pub(crate) fn is_dumb() -> bool {
term().is_none_or(|term| {
term.cursor_up.is_none()
|| term.cursor_down.is_none()
|| term.cursor_left.is_none()
|| term.cursor_right.is_none()
})
let term = term();
term.cursor_up.is_none()
|| term.cursor_down.is_none()
|| term.cursor_left.is_none()
|| term.cursor_right.is_none()
}
// Exposed for testing.

View File

@@ -13,10 +13,6 @@
/// The [`Term`] singleton. Initialized via a call to [`setup()`] and surfaced to the outside world via [`term()`].
///
/// It isn't guaranteed that fish will ever be able to successfully call `setup()`, so this must
/// remain an `Option` instead of returning `Term` by default and just panicking if [`term()`] was
/// called before `setup()`.
///
/// We can't just use an [`AtomicPtr<Arc<Term>>`](std::sync::atomic::AtomicPtr) here because there's a race condition when the old Arc
/// gets dropped - we would obtain the current (non-null) value of `TERM` in [`term()`] but there's
/// no guarantee that a simultaneous call to [`setup()`] won't result in this refcount being
@@ -26,11 +22,8 @@
/// Returns a reference to the global [`Term`] singleton or `None` if not preceded by a successful
/// call to [`terminal::setup()`](setup).
pub fn term() -> Option<Arc<Term>> {
TERM.lock()
.expect("Mutex poisoned!")
.as_ref()
.map(Arc::clone)
pub fn term() -> Arc<Term> {
Arc::clone(TERM.lock().expect("Mutex poisoned!").as_ref().unwrap())
}
/// The safe wrapper around terminfo functionality, initialized by a successful call to [`setup()`]