-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update ncurses when TERM is assigned. #3060
Comments
/cc @Shados, for he also hit the issue. |
We already do this on startup since c5bc221, so you'll want fish 2.3.0. If you want us to also do it at runtime, is there any particular reason why you are changing these variables then? Usually you'll want to set your terminal to send a proper $TERM value, and if you can't do that you'll want to set it in your config.fish. |
I should probably clarify: Since that commit, setting TERM in config.fish works. Do you need anything more? |
That should be enough, if setting TERMINFO and TERMINFO_DIRS in config.fish is also taken into account. I will try with version 2.3.0, and open a new issue if need be. Thanks for the fast and accurate reply! |
|
@faho, @zanchey Well, I can confirm that setting TERM in config.fish is indeed picked by fish, but setting and/or exporting My terminfo resides in a custom location in my home. The global system is not aware of it, and should not be. The only way for may login shell to work with my terminal is to receive the In zsh, when So all these shells have a way to overwrite If fish does not want to allow live update of these variables, it would still be a good idea to propagate I hope I made the issue clear enough. Reopening for it seems valid with these new elements. [zsh] https://github.com/zsh-users/zsh/blob/master/Src/params.c#L4423-4437 |
@layus: Are you saying you are not exporting set -x TERMINFO_DIRS /some/dir
set -x TERMINFO whatever
set -x TERM my_term_name in your config.fish do you get the expected behavior? Regardless of the answers to the above I'm inclined to agree with @layus. Fish really should be monitoring those vars and resetting ncurses (or whatever is needed to cause it to notice the environment has changed) even if done interactively. Relabeling this as an enhancement since strictly speaking the current behavior isn't in conflict with the documented behavior. |
What I am saying is that if I put
in my config.fish, I get
(yes two lines, I guess the file is evaluated twice) in my terminal. You can also observe that So
I conclude that passing NB: The value of |
Here is a patch that fixes the issue (I am quite proud of the XOR operator :-). Of course, return values are not checked, the style is not perfect, I have no idea if entering multiple times in input_init causes memory leaks or is at all valid and there are algorithmic issues when a valid state is broken by setting some TERM var to an invalid value. This explains why it is not a PR. But it "Just Works!" ™️. Here comes the beast: diff --git a/src/env.cpp b/src/env.cpp
index 56c9deb..6b0f982 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -318,6 +318,10 @@ static void react_to_variable_change(const wcstring &key)
{
update_wait_on_escape_ms();
}
+ else if (key == L"TERM" || key == L"TERMINFO" || key == L"TERMINFO_DIRS")
+ {
+ input_init(true);
+ }
}
/**
diff --git a/src/input.cpp b/src/input.cpp
index b427772..0ec4de0 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -457,15 +457,31 @@ void update_fish_color_support(void)
output_set_color_support(support);
}
-int input_init()
+int input_init(bool update)
{
- if (is_init)
+ // A valid use of XOR:
+ // We want to init if we are not yet initialized,
+ // but we want to update only when it has already been initialized.
+ // There is no sense in updating when not initialized.
+ if (is_init ^ update)
return 1;
is_init = true;
input_common_init(&interrupt_handler);
+ const env_var_t terminfo = env_get_string(L"TERMINFO", ENV_GLOBAL | ENV_EXPORT);
+ if (terminfo.missing())
+ unsetenv("TERMINFO");
+ else
+ setenv("TERMINFO", const_cast<char *>(wcs2string(terminfo).c_str()), 1);
+
+ const env_var_t terminfo_dirs = env_get_string(L"TERMINFO_DIRS", ENV_GLOBAL | ENV_EXPORT);
+ if (terminfo_dirs.missing())
+ unsetenv("TERMINFO_DIRS");
+ else
+ setenv("TERMINFO_DIRS", const_cast<char *>(wcs2string(terminfo_dirs).c_str()), 1);
+
const env_var_t term = env_get_string(L"TERM");
int errret;
if (setupterm(const_cast<char *>(wcs2string(term).c_str()), STDOUT_FILENO, &errret) == ERR)
diff --git a/src/input.h b/src/input.h
index 47315c1..b30b0b0 100644
--- a/src/input.h
+++ b/src/input.h
@@ -27,7 +27,7 @@ wcstring describe_char(wint_t c);
Before calling input_init, terminfo is not initialized and MUST not be used
*/
-int input_init();
+int input_init(bool update = false);
/**
free up memory used by terminal functions. |
That's because somehow you're starting a second fish instance and the system wide fish init scripts are presumably setting Also, Thanks for the proof of concept patch. As you noted, someone will need to answer some of the questions you raised before it is merged. |
😄 I should have used |
@layus: Can you confirm that your system wide fish init scripts are setting |
Yes, your previous post got it right indeed. Printing these variables is exactly what I did.
and my output is as explained in #3060 (comment) My init sequence is
These files are included in fish_config.zip In there, /nix/store/*-set-environment is the one exporting TERMINFO_DIRS, and assigning TERM to itself because this triggers a refresh of the curses data structures in most shell (see comment in the file). The first indirection before sourcing /etc/fish/config.fish is due to fis sourcing ../etc/fish/config.fish relative to its executable. |
I have submitted a safe PR at #3071. It propagates |
My most recent comment to PR #3071: As I feared fish is exporting vars by passing them to the |
The code for handling exported vars in this manner dates back to 2005-09-23 with commit f971e02. The commit comment just says "Exportable universal variables" and, of course, there's no issue linked to that would explain the rationale for this design. I'm not willing to make a radical change to how exported vars are handled given how many other things need to be done (like switching to UTF-8 internally). The simplest solution is to special-case the curses env vars in |
Implementing my own fix for this caused me to notice that |
Fixed by commit 53e865b. |
Fish does not reload/reconfigure the underlying ncurses when TERM is assigned like other shells do (bash, zsh, tcsh). It is annoying because TERMINFO may be customized by profile scripts for custom user environments. Fish needs a way to detect changes to TERM* variables and update itself.
Reproduction Steps:
Trick fish into a wrong TERM, then update TERM from within Fish.
In my use-case, terminfo is located in ~, and therefore not available at fish startup (by ssh).
Expected behavior:
Fish should reconfigure curses when the exported terminal is changed, and optionally when other TERMINFO* variables are changed.
Observed behavior:
...
Additional information:
Fish version: 2.2.0
Operating system: NixOS (linux)
Terminal or terminal emulator: rxvt-unicode-256color
The text was updated successfully, but these errors were encountered: