Skip to content
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

Prompt element colours will not use customised colours #153

Closed
kopischke opened this issue Mar 21, 2019 · 12 comments · Fixed by #199
Closed

Prompt element colours will not use customised colours #153

kopischke opened this issue Mar 21, 2019 · 12 comments · Fixed by #199
Labels
🐛 bug something that doesn't works as expected
Milestone

Comments

@kopischke
Copy link

kopischke commented Mar 21, 2019

Because the colours of the prompt elements like the success and error prompt symbols (pure_color_prompt_on_symbols and pure_color_prompt_on_error) are assigned and exported in a conf.d snippet, which is sourced before the user configuration file (config.fish), overriding colour variables (pure_color_X) in config.fish per the README will not actually affect the colours of elements assigned this colour in interactive login shell sessions.

To reproduce

on macOS 10.14, using Terminal.app and fish set as default shell via chsh

  1. install pure

  2. add the following line to your config.fish:

    set --export pure_color_success (set_color green)
  3. start a new fish session by opening a new Terminal window

Expected result: the success prompt symbol is green

Actual result: the success prompt symbol is magenta

Notes: oddly enough, this works as expected in a subshell (“oddly enough” because the fish help clearly states all configuration files, including snippets, are read on every shell start, but this behaviour only makes sense if fish actually skips reading snippets in a non-login shell).

@edouard-lopez
Copy link
Member

You will need to erase the variable before overriding them as discussed in #138

set --erase pure_color_success
set --global pure_color_success (set_color green)

@andreiborisov
Copy link
Collaborator

@edouard-lopez apart from the fact that we need to elaborate this in README, as anything we can do to simplify this?

@andreiborisov
Copy link
Collaborator

andreiborisov commented Mar 22, 2019

So, just to be clear, the problem lies in the fact that config.fish sourced the last one after all other files in conf.d (see https://fishshell.com/docs/current/index.html#initialization), but variables evaluate they value on set instead of storing reference.

Here is a couple of solutions:

  1. We can store feature variables as text effectively storing reference instead of the value
set $pure_color_prompt_on_error \$pure_color_danger

and evaluate their values on invocation

eval echo $pure_color_prompt_on_error

Obviously this is quite ugly and hacky (maybe even a bit slower).

  1. We can provide function pure_set which would do appropriate erasing for the user. Somewhat acceptable, but the need to use special function to set variables is unintuitive.

  2. We can recommend users to set pure color variables as universal so it won't be rewritten by _pure_set_default. This is probably the most idiomatic solution.

  3. We can move pure.fish from conf.d and source it manually from config.fish (like we used to), so it will be executed after config.fish and _pure_set_default would work as intended.

If @jorgebucaran like to chime in and talk wisdom to us, that would be very helpful too☺️

@jorgebucaran
Copy link
Contributor

Don't tell people to use pure_color_success, pure_color_mute, etc. Use them internally to set the actual variables and tell people to use pure_color_prompt_on_success, etc.

set -x pure_color_prompt_on_success (set_color green)

@andreiborisov
Copy link
Collaborator

I would like to salvage ability to set base colors for users though, seems useful to me

@jorgebucaran
Copy link
Contributor

@schrodincat Then something like this.

function _pure_prompt_symbol
    set -l prompt_color $pure_color_prompt_on_success
    if set -q pure_color_success
        set prompt_color $pure_color_success
    end

    # ...

    echo "$prompt_color$prompt_symbol"
end

@andreiborisov
Copy link
Collaborator

andreiborisov commented Mar 22, 2019

@jorgebucaran although it implicitly assumes that $pure_color_prompt_on_success should inherit from $pure_color_success (which is not always the case, for example, when a user sets base $pure_color_success color and tweaks specific feature$pure_color_prompt_on_success color), this seems like a nice middle ground.

For now, though, I've tried to fix this making base color variables universal.

@kopischke
Copy link
Author

kopischke commented Mar 23, 2019

@schrodincat I very much appreciate you trying to tackle the issue, but I am not sure how making colour variables universal will achieve this? As you stated quite correctly

the problem lies in the fact that config.fish sourced the last one after all other files in conf.d (see https://fishshell.com/docs/current/index.html#initialization), but variables evaluate they value on set instead of storing reference.

to my best understanding, this means that after the changes

  1. conf.d/pure.fish will still unconditionally set the colour defaults , as neither it nor _pure_set_default.fish check if the variable is set, [EDIT: _pure_set_default.fish actually does, this was an error of mine (or, for the Americans: “my bad”)] and fish’s set command unconditionally sets a variable value. Also, before somebody waves --erase like a magic wand in front of my nose again: unless I completely misunderstand both fish’s docs and its actual behaviour in my terminal, that flag is useful to prevent scope shadowing issues; it is not needed to re-assign a variable;
  2. the colour assignment to $pure_color_prompt_on_success in conf.d/pure.fish will still be static;
  3. changes to base colours in config.fish thus will still not propagate to derived properties.

Am I missing something? To me, it appears that the universal variable solution would only work if

1. either conf.d/pure.fish or _pure_set_default.fish bail when a variable is already set;
2. you instruct users to re-start their fish session after setting universal colour variables for them to take effect, which is counterintuitive as the whole point of universal vars is that they need not be set for every session.

Assuming my analysis is correct, making base colours universal is the right first step, but you will need a dynamic evaluation of the assignment of base colours to derived prompt properties, be it through an eval hack or through an intermediary function, as the second. If you want a user friendly way of configuring base colours, that is, which I happen to think is the correct approach.

@andreiborisov
Copy link
Collaborator

andreiborisov commented Mar 23, 2019

@kopischke

conf.d/pure.fish will still unconditionally set the colour defaults, as neither it nor _pure_set_default.fish check if the variable is set

_pure_set_default always checked for the existence of a variable before setting it, that's basically the reason it exists.

you instruct users to re-start their fish session after setting universal color variables for them to take effect, which is counterintuitive as the whole point of universal vars is that they need not be set for every session

Universal variables are meant to be set mainly by hand in a terminal, it's kind of a replacement for config.fish in that sense: instead of setting a variable on every shell load in config.fish similar to what you'd do in bash, you only set the variable once and it persists across sessions (stored in fish_variables file). This file loads before files in conf.d directory. So if you'll do set -U pure_color_success (set_color green) for example, the new value propagates to feature colors on the next load. You still can add the same command in the config.fish, however there will be a minor inconvenience indeed, the new value won't propagate to feature colors on the first load. Only on the second one. But since universal variables are not really meant to be set this way, I see it as an acceptable trade-off.

In my opinion, all other proposed solutions are making the code either slower or too convoluted because they are essentially trying to fight how fish actually works.

@kopischke
Copy link
Author

kopischke commented Mar 23, 2019

@schrodincat

_pure_set_default always checked for the existence of a variable before setting it, that's basically the reason it exists.

So it does, you are right and I was wrong; apologies for a hasty misreading.

Universal variables are meant to be set mainly by hand in a terminal, it's kind of a replacement for config.fish in that sense …

You are missing one essential behaviour of universal variables, the one making them far more than a way to set variables persistently without touching config.fish: they immediately affect all running fish sessions (that is where the “universal” comes from) – no need to restart the session. As the fish docs state succinctly:

Universal variables are variables that are shared between all the users' fish sessions on the computer. Fish stores many of its configuration options as universal variables. This means that in order to change fish settings, all you have to do is change the variable value once, and it will be automatically updated for all sessions, and preserved across computer reboots and login/logout.

(emphasis mine). I have made a GIF illustrating exactly that:

Screen capture of two fish terminal sessions illustrating how universal variables are immediately effective in all running fish sessions

This behaviour makes uvars ideal for shell wide persistent user settings; in fact, as the docs mention, one of their functions out of the box is to set fish’s own colours persistently and across all sessions 😉. Switching pure’s colour variables to universal vars thus is a good step; the problem is these universal variables will currently still only be assigned to prompt elements on shell start-up, no matter how the uvars were set (the right way, interactively, or the pointless way, in config.fish). That in turn means you still need to launch a new session for the assignment to the variable to take effect after a change, which is exactly what using universal variables is meant to avoid.

@andreiborisov
Copy link
Collaborator

@kopischke I think I misunderstood jorgebucaran solution the first time. I’ll be able to solve this issue without enforcing universal scope on to variables, like you want me too, in more idiomatic way. PR is coming, however, it won’t be available till the end of the next week.

@kopischke
Copy link
Author

@schrodincat very cool! Thanks for that, and no rush.

@edouard-lopez edouard-lopez added this to the v2.1.x-next milestone Apr 3, 2019
@andreiborisov andreiborisov added the 🐛 bug something that doesn't works as expected label Dec 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug something that doesn't works as expected
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants