mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 05:53:59 +00:00
put curses/terminfo vars into the environment
We need to actually export the curses/terminfo env vars in order for `setupterm()` to be able to use them. While fixing this I reworked the fallback logic implemented by @zanchey in response to issue #1060 in order to simplify the logic and clarify the error messages. This does not allow someone to change the curses/terminfo env vars after the first prompt is displayed (you can but it won't affect the current fish process). It only makes it possible to set `TERM`, `TERMINFO`, and `TERMINFO_DIRS` in *config.fish* or similar config file and have them be honored by fish.
This commit is contained in:
parent
57f289850c
commit
53e865b654
4 changed files with 53 additions and 42 deletions
43
src/env.cpp
43
src/env.cpp
|
@ -124,10 +124,15 @@ static null_terminated_array_t<char> export_array;
|
||||||
static bool has_changed_exported = true;
|
static bool has_changed_exported = true;
|
||||||
static void mark_changed_exported() { has_changed_exported = true; }
|
static void mark_changed_exported() { has_changed_exported = true; }
|
||||||
|
|
||||||
/// List of all locale variable names.
|
/// List of all locale environment variable names.
|
||||||
static const wchar_t *const locale_variable[] = {L"LANG", L"LC_ALL", L"LC_COLLATE",
|
static const wchar_t *const locale_variable[] = {
|
||||||
L"LC_CTYPE", L"LC_MESSAGES", L"LC_MONETARY",
|
L"LANG", L"LANGUAGE", L"LC_ALL", L"LC_ADDRESS", L"LC_COLLATE",
|
||||||
L"LC_NUMERIC", L"LC_TIME", NULL};
|
L"LC_CTYPE", L"LC_IDENTIFICATION", L"LC_MEASUREMENT", L"LC_MESSAGES", L"LC_MONETARY",
|
||||||
|
L"LC_NAME", L"LC_NUMERIC", L"LC_PAPER", L"LC_TELEPHONE", L"LC_TIME",
|
||||||
|
NULL};
|
||||||
|
|
||||||
|
/// List of all curses environment variable names.
|
||||||
|
static const wchar_t *const curses_variable[] = {L"TERM", L"TERMINFO", L"TERMINFO_DIRS", NULL};
|
||||||
|
|
||||||
const var_entry_t *env_node_t::find_entry(const wcstring &key) {
|
const var_entry_t *env_node_t::find_entry(const wcstring &key) {
|
||||||
const var_entry_t *result = NULL;
|
const var_entry_t *result = NULL;
|
||||||
|
@ -200,10 +205,40 @@ static void handle_locale() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the specified variable is a locale variable.
|
||||||
|
static bool var_is_curses(const wcstring &key) {
|
||||||
|
for (size_t i = 0; curses_variable[i]; i++) {
|
||||||
|
if (key == curses_variable[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Push all curses/terminfo env vars into the global environment where they can be found by those
|
||||||
|
/// libraries.
|
||||||
|
static void handle_curses() {
|
||||||
|
for (size_t i = 0; curses_variable[i]; i++) {
|
||||||
|
const wchar_t *key = curses_variable[i];
|
||||||
|
const env_var_t var = env_get_string(key);
|
||||||
|
if (!var.empty()) {
|
||||||
|
const std::string &name = wcs2string(key);
|
||||||
|
const std::string &value = wcs2string(var);
|
||||||
|
setenv(name.c_str(), value.c_str(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Modify input_init() to allow calling it when the terminfo env vars are dynamically
|
||||||
|
// changed. At the present time it can be called just once. Also, we should really only do this
|
||||||
|
// if the TERM var is set.
|
||||||
|
// input_init();
|
||||||
|
}
|
||||||
|
|
||||||
/// React to modifying the given variable.
|
/// React to modifying the given variable.
|
||||||
static void react_to_variable_change(const wcstring &key) {
|
static void react_to_variable_change(const wcstring &key) {
|
||||||
if (var_is_locale(key)) {
|
if (var_is_locale(key)) {
|
||||||
handle_locale();
|
handle_locale();
|
||||||
|
} else if (var_is_curses(key)) {
|
||||||
|
handle_curses();
|
||||||
} else if (key == L"fish_term256" || key == L"fish_term24bit") {
|
} else if (key == L"fish_term256" || key == L"fish_term24bit") {
|
||||||
update_fish_color_support();
|
update_fish_color_support();
|
||||||
reader_react_to_color_change();
|
reader_react_to_color_change();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Functions for reading a character of input from stdin.
|
// Functions for reading a character of input from stdin.
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
@ -339,35 +338,25 @@ void update_fish_color_support(void) {
|
||||||
|
|
||||||
int input_init() {
|
int input_init() {
|
||||||
if (is_init) return 1;
|
if (is_init) return 1;
|
||||||
|
|
||||||
is_init = true;
|
is_init = true;
|
||||||
|
|
||||||
input_common_init(&interrupt_handler);
|
input_common_init(&interrupt_handler);
|
||||||
|
|
||||||
const env_var_t term = env_get_string(L"TERM");
|
int err_ret;
|
||||||
int errret;
|
if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) {
|
||||||
if (setupterm(const_cast<char *>(wcs2string(term).c_str()), STDOUT_FILENO, &errret) == ERR) {
|
env_var_t term = env_get_string(L"TERM");
|
||||||
debug(0, _(L"Could not set up terminal"));
|
debug(0, _(L"Your TERM value of '%ls' is not valid"), term.c_str());
|
||||||
if (errret == 0) {
|
debug(0, _(L"Check that your terminal type is supported on this system"));
|
||||||
debug(0, _(L"Check that your terminal type, '%ls', is supported on this system"),
|
env_set(L"TERM", DEFAULT_TERM, ENV_GLOBAL | ENV_EXPORT);
|
||||||
term.c_str());
|
if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) {
|
||||||
debug(0, _(L"Attempting to use '%ls' instead"), DEFAULT_TERM);
|
debug(0, _(L"Unable to setup terminal using your TERM or the '%ls' fallback"),
|
||||||
env_set(L"TERM", DEFAULT_TERM, ENV_GLOBAL | ENV_EXPORT);
|
DEFAULT_TERM);
|
||||||
const std::string default_term = wcs2string(DEFAULT_TERM);
|
|
||||||
if (setupterm(const_cast<char *>(default_term.c_str()), STDOUT_FILENO, &errret) ==
|
|
||||||
ERR) {
|
|
||||||
debug(0, _(L"Could not set up terminal"));
|
|
||||||
exit_without_destructors(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
exit_without_destructors(1);
|
exit_without_destructors(1);
|
||||||
|
} else {
|
||||||
|
debug(0, _(L"Using fallback terminal type '%ls' instead"), DEFAULT_TERM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(!term.missing());
|
|
||||||
output_set_term(term);
|
|
||||||
|
|
||||||
input_terminfo_init();
|
input_terminfo_init();
|
||||||
|
|
||||||
update_fish_color_support();
|
update_fish_color_support();
|
||||||
|
|
||||||
// If we have no keybindings, add a few simple defaults.
|
// If we have no keybindings, add a few simple defaults.
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "env.h"
|
||||||
#include "fallback.h" // IWYU pragma: keep
|
#include "fallback.h" // IWYU pragma: keep
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "wutil.h" // IWYU pragma: keep
|
#include "wutil.h" // IWYU pragma: keep
|
||||||
|
@ -33,9 +34,6 @@ static int writeb_internal(char c);
|
||||||
/// The function used for output.
|
/// The function used for output.
|
||||||
static int (*out)(char c) = writeb_internal;
|
static int (*out)(char c) = writeb_internal;
|
||||||
|
|
||||||
/// Name of terminal.
|
|
||||||
static wcstring current_term;
|
|
||||||
|
|
||||||
/// Whether term256 and term24bit are supported.
|
/// Whether term256 and term24bit are supported.
|
||||||
static color_support_t color_support = 0;
|
static color_support_t color_support = 0;
|
||||||
|
|
||||||
|
@ -416,18 +414,13 @@ rgb_color_t parse_color(const wcstring &val, bool is_background) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_set_term(const wcstring &term) { current_term.assign(term); }
|
|
||||||
|
|
||||||
const wchar_t *output_get_term() {
|
|
||||||
return current_term.empty() ? L"<unknown>" : current_term.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void writembs_check(char *mbs, const char *mbs_name, const char *file, long line) {
|
void writembs_check(char *mbs, const char *mbs_name, const char *file, long line) {
|
||||||
if (mbs != NULL) {
|
if (mbs != NULL) {
|
||||||
tputs(mbs, 1, &writeb);
|
tputs(mbs, 1, &writeb);
|
||||||
} else {
|
} else {
|
||||||
|
env_var_t term = env_get_string(L"TERM");
|
||||||
debug(0, _(L"Tried to use terminfo string %s on line %ld of %s, which is undefined in "
|
debug(0, _(L"Tried to use terminfo string %s on line %ld of %s, which is undefined in "
|
||||||
L"terminal of type \"%ls\". Please report this error to %s"),
|
L"terminal of type \"%ls\". Please report this error to %s"),
|
||||||
mbs_name, line, file, output_get_term(), PACKAGE_BUGREPORT);
|
mbs_name, line, file, term.c_str(), PACKAGE_BUGREPORT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,12 +76,6 @@ void output_set_writer(int (*writer)(char));
|
||||||
/// Return the current output writer.
|
/// Return the current output writer.
|
||||||
int (*output_get_writer())(char);
|
int (*output_get_writer())(char);
|
||||||
|
|
||||||
/// Set the terminal name.
|
|
||||||
void output_set_term(const wcstring &term);
|
|
||||||
|
|
||||||
/// Return the terminal name.
|
|
||||||
const wchar_t *output_get_term();
|
|
||||||
|
|
||||||
/// Sets what colors are supported.
|
/// Sets what colors are supported.
|
||||||
enum { color_support_term256 = 1 << 0, color_support_term24bit = 1 << 1 };
|
enum { color_support_term256 = 1 << 0, color_support_term24bit = 1 << 1 };
|
||||||
typedef unsigned int color_support_t;
|
typedef unsigned int color_support_t;
|
||||||
|
|
Loading…
Reference in a new issue