-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
charles@work ~> fish --version ; echo $version
fish, version 2.6.0
2.6.0
charles@work ~> uname -a ; echo $TERM
Linux work 3.13.0-119-generic #166-Ubuntu SMP Wed May 3 12:18:55 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
screen-256colorUnder bash it is possible to introduce additional variables and environment when entering a shell directly, before the shell is interactive. That is, a script executes something along the lines of (from one of the scripts I use):
bash -i --rcfile <(echo "source ~/.bashrc ; source '${_PYTHONLIB_ENVDIR}/bin/activate'")(or if you wanted to do it with the login shells, through the profile command line options, and then emulating the bash startup sequence in the new profile file)
Why might you do this ? I use it to set up the environment for working, from a script, which ensures that everything is setup and then drops to the shell in the new environment, with things set up like the user had before.
Anyhow. This is all fine and dandy for bash. For fish however, there's no easy way (as far as I can see) to introduce additional environment when starting the shell interactively. In the case of the virtualenv example, above, this has to happen after the user's conf.d has executed, in order that the prompt setup can be modified to reflect the new environment.
The solution I came up with was... let's say it's ugly and leave it at that (this is a fragment of a bash script that sets things up to honour the user's shell):
if [[ "$SHELL" =~ /fish ]] ; then
# Fish does not appear to be able to be given a startup file,
# as far as can be seen.
# BUT we can insert ourselves into the initialisation by
# adding files to the conf.d directory.
__magic_value="$RANDOM.$$"
mkdir -p "${XDG_CONFIG_HOME:-${HOME}/.config}/fish/conf.d"
cat <<EOM > "${XDG_CONFIG_HOME:-${HOME}/.config}/fish/conf.d/pythonlib.$__magic_value.fish"
set -l me "${XDG_CONFIG_HOME:-${HOME}/.config}/fish/conf.d/pythonlib.$__magic_value.fish"
if [ "\$__PYTHONLIB_MAGIC" = "$__magic_value" ]
source "${_PYTHONLIB_ENVDIR}/bin/activate.fish"
# Remove ourselves now that we've been used.
rm "\$me"
else
set -l hours_ago (math \\( (date +%s) - (stat --format '%Z' "\$me") \\) / \\( 60 \\* 60 \\))
if test \$hours_ago -ge 2
# This script hasn't been used for over 2 hours - something has
# gone wrong, and it's not going to be invoked. It should really
# have been run within moments.
rm "\$me"
end
end
EOM
echo "Press ctrl-d, or use 'exit' to end shell."
__PYTHONLIB_MAGIC=${__magic_value} fish
elif [[ "$SHELL" =~ /bash ]] ; then
# Start the bash shell, with the environment activated by
# making the rcfile run the user's file, then the activation.
echo "Press ctrl-d, or use 'exit' to end shell."
bash -i --rcfile <(echo "source ~/.bashrc ; source '${_PYTHONLIB_ENVDIR}/bin/activate'") (anyone wishing to cry should can join me now)
As you can see, the bash solution is a little simpler.
So, what would be awesome, to avoid this 'ugliness', would be if the fish command line offered the ability to source some files after the user's configuration has started. I can obviously work around this by changing my own configuration files to source a file, if a specific variable has been set, but it would be nice if this could be achieved without user-specific intervention in their own shell - the whole point of this is that executing a single command will ensure that variables, paths, and tools are setup and installed from a single command, and that the user's preference for shell is honoured (I don't think it's all that nice to force people to work with only bash in the custom environment; after all, the niceness of the alternative is why we use fish 😄)