Conditional pwd in an PS1 definition

2019-08-01 03:25发布

I want to display the current working directory in my prompt differently if I am in a symlink than not.

I have this far:

[[ `pwd -P` = `pwd` ]] && echo "\[1;31m\]$(pwd -P)" || echo "\[1;32m\]$(pwd)"

will return the desired output but it will not work as a replacement for \w in the command prompt.

I tried wrapping it with backticks but that just results in pwd -Ppwd in the PS1.

I want to conditionally change the color and the value if it is a symlink or not which is why I want the if/else type decision.

标签: bash ps1
2条回答
兄弟一词,经得起流年.
2楼-- · 2019-08-01 04:01

This is what I ended up with:

I wanted to change the pwd value as well as the color when it is a symlink.

# look up color codes for our terminal rather than assuming ANSI
declare -r red=$(tput setaf 1)
declare -r green=$(tput setaf 2)
declare -r white=$(tput setaf 9)
declare -r aqua=$(tput setaf 6)
declare -r reset=$(tput sgr0)

colorize_msg() {
   printf -v $1 "\[%s\]%s" ${2} ${3}
}

set_prompt() {

    declare prompt_pwd=""
    # only rerun this code when changing directories!
    if [[ last_prompt_pwdL != $PWD ]]; then
        declare -g last_prompt_pwdL=$PWD # logical path
        declare -r last_prompt_pwdP=$(pwd -P) # physical path
        if [[ $last_prompt_pwdL = $last_prompt_pwdP ]]; then
          colorize_msg prompt_pwd $green $last_prompt_pwdL
        else
          colorize_msg prompt_pwd $red $last_prompt_pwdP
        fi

        # ...actually could have just "return"ed above, but this way we can change other
        # aspects of the prompt even when we don't need to do a new directory lookup.
        declare prompt=""
        declare msg=""
        colorize_msg msg $white "["
        prompt+=$msg
        colorize_msg msg $aqua "\u"
        prompt+=$msg
        colorize_msg msg $red "@"
        prompt+=$msg
        colorize_msg msg $aqua"\h"
        prompt+=$msg
        colorize_msg msg $white "] ["
        prompt+=$msg
        prompt+=${prompt_pwd}
        colorize_msg msg $white "]"
        prompt+=$msg
        prompt+="${reset}\n"
        PS1=$prompt
    fi
}
查看更多
Rolldiameter
3楼-- · 2019-08-01 04:06

If you want this to actually be efficient (and prompts should be fast to render!), then you'll want to cache the physical lookups, and use $PWD rather than $(pwd) for the logical ones.

# global variables are prefixed with funcname__ to avoid conflicts

# look up color codes for our terminal rather than assuming ANSI
set_prompt__red=$(tput setaf 1)
set_prompt__green=$(tput setaf 2)
set_prompt__reset=$(tput sgr0)

set_prompt() {

  # only rerun this code when changing directories!
  if [[ $set_prompt__lastPWDl != "$PWD" ]]; then
    set_prompt__lastPWDl=$PWD
    set_prompt__lastPWDp=$(pwd -P)
    if [[ "$set_prompt__lastPWDl" = "$set_prompt__lastPWDp" ]]; then
      set_prompt__pwd_color="$set_prompt__red"
    else
      set_prompt__pwd_color="$set_prompt__green"
    fi
  fi

  # ...actually could have just "return"ed above, but this way we can change other
  # aspects of the prompt even when we don't need to do a new directory lookup.
  PS1='...whatever prefix...'
  PS1+="\[${set_prompt__pwd_color}\]${PWD}\[${set_prompt__reset}\]"
  PS1+='...whatever suffix...'
}
PROMPT_COMMAND=set_prompt
查看更多
登录 后发表回答