7

I would like to customize my terminal prompt. Normally when a conda environment is activated the name of the environment is prepended to the PS1 string. I would like to customize this a bit more but have not been able to figure it out.

If I add changeps1: false to my .condarc file the terminal prompt is not modified when I activate a new environment. I can then modify the environment variable in my .bash_profile for example:

PS1+="\[${cyan}\]<$(basename $CONDA_DEFAULT_ENV)> ";

This returns the name of the environment colored how I would like surrounded by carrots, however this only works after I run source .bash_profile activating the environment has no effect, which is not unexpected.

My question is how to I update the prompt when activating the environment, or is there a better way of go about this?

This is related to this question

And this example profile However those do not directly address the issue that I am running into of the prompt not changing when activating environments

0xSheepdog
  • 2,750
johnchase
  • 123

2 Answers2

10

The problem here is that you're using double quotes and using a direct command substitution, which means the value of $(basename $CONDA_DEFAULT_ENV) (and therefore $CONDA_DEFAULT_ENV) will only be evaluated once, when that line of code is executed, and will be incorporated into PS1 as a verbatim string.

The way bash processes PS1, it will evaluate $(...) sequences every time the prompt is printed, so what you need to do is preserve the sequence in its literal form (by escaping the $s with backslashes, for example), which should yield the result you're looking for.

So this should work:

PS1+="\[${cyan}\]<\$(basename \$CONDA_DEFAULT_ENV)> ";

Or, better, add double quotes around the variable, so that the basename command will keep working if $CONDA_DEFAULT_ENV has spaces, or if it's empty or unset:

PS1+="\[${cyan}\]<\$(basename \"\$CONDA_DEFAULT_ENV)\"> ";

Note that I didn't escape ${cyan}, since it's OK to evaluate that only once, as it's not expected to change...

Escaping metacharacters (such as $ and ") starts getting heavy at some point, so using single quotes to preserve the string verbatim is probably a better choice at some point, so we can do that. But since we want to still expand ${cyan}, let's mix double quotes and single quotes to achieve the desired result with minimal escaping:

PS1+="\[${cyan}\]"'<$(basename "$CONDA_DEFAULT_ENV")> ';

You might still have problems with setting the color to cyan without resetting it at the end... But that should be easy to fix, by adding another "\[${...}\]" block at the end with the code to reset formatting (not sure where your color constants are coming from, so check those for the reset code.) But it's possible that's not a problem in your specific environment, if you have further lines appending to PS1 to further modify it, that are also changing the color. (Which I imagine is your case, since you say what you have works whenever you source your profile.)

filbranden
  • 21,751
  • 4
  • 63
  • 86
  • 1
    This works, and I also I appreciate the explanation of what was failing in my example. Thanks for a great answer! – johnchase Oct 17 '18 at 15:07
0

Expanding a bit on filbranden's answer, if you want to avoid the <> when no env is set, you can do something like:

# CONDA
function parse_conda_env () {
    if [ ! -z "$CONDA_DEFAULT_ENV" ]
    then
        echo "<$(basename "$CONDA_DEFAULT_ENV")> "
    fi
}

COLORS

BLUE="[\033[0;34m]" RED="[\033[0;31m]" YELLOW="[\033[0;33m]" GREEN="[\033[0;32m]" CYAN="[\033[0;36m]" NO_COLOR="[\033[0m]"

PROMPT_DIRTRIM=2 PS1="$CYAN$(parse_conda_env)$GREEN\h$BLUE:\w$YELLOW$(parse_git_branch)$NO_COLOR$ ";