Linux shell (Bash/Z shell) - 在特定目录下更改背景颜色

Linux shell (Bash/Z shell) - change background color when under a specific directory

我想在每次进入特定目录时更改 shell 的背景颜色(Z shell,但 Bash 也可以)。比如我想每次在/mnt/data的时候把背景颜色改成红色,如果出了/mnt/data就改回正常/...

要更改背景并保留我当前的提示,我这样做:

export PS1="$PS1 %{$'\e[0;41m'%}"

我不确定如何连接它以便在每次更改工作目录时对其进行评估(包装在 if 语句中)。

诀窍是使用 PS1 中的命令替换。 Bash 中的以下类型对我有用:

PS1='$(if [[ $PWD == /mnt/data* ]] ; then printf "\[\e[0;41m\]" ; else printf "\[\e[m\]" ; fi) %'

我所说的“有点”是指在更改 to/from 目录后立即在命令行上的行为有点奇怪(例如,在您按下 Backspace 后背景发生变化).

您还可以使用 PROMPT_COMMAND shell 变量,它比提示本身更适合代码:

PROMPT_COMMAND='if [[ $PWD == /mnt/data* ]] ; then printf "\e[0;41m" ; else printf "\e[m" ; fi'

将代码保留在具有所有正确缩进的函数中,并从变量中调用函数会更简洁:

colour_mnt_data () {
    if [[ $PWD == /mnt/data* ]] ; then
        printf '\e[0;41m'
    else
        printf '\e[m'
    fi
}
PROMPT_COMMAND='colour_mnt_data'

您需要编写一个脚本文件,其中包含您可以调用的函数以确定您的 PS1 应该是什么,因为您所在的目录。

然后,您在 .bashrc 中获取此脚本文件并设置 PS1 以便它调用脚本文件中的函数来设置其值。

  . ~/.myCleverPS1

  export PS1='$PS1 $(myCleverPS1func " (%s)") $ '

您可以查看的一个示例是 git-completion 脚本,它会在您位于 git 存储库目录时将当前分支的名称添加到提示中(并且也可以选择着色).

参见示例:https://github.com/git/git/tree/master/contrib/completion

zsh的答案(虽然第二部分可以改编为bash):

这是一个两部分的问题:

  1. 对目录更改进行操作: 对于 zsh 你可以只使用 chpwd 钩子函数。每次更改当前工作目录时,都会调用 chpwd 以及 chpwd_functions 数组中列出的任何函数。

    所以,如果你想对某些目录做出反应,你可以使用类似这样的东西

    # load helper function to manipulate hook arrays
    autoload -Uz add-zsh-hook
    
    # define hook function, decide on action based on $PWD, the new pwd.
    chback_on_chdir () {
        case $PWD in
            /mnt/data/* )
                # change background, when entering subdirectories of "/mnt/data"
                ;;
            /home )
                # change background, when entering exactly "/home"
                ;;
            /usr | /usr/* ) 
                # change background, when entering "/usr" or a subdirectory thereof
                ;;
            * )
                # change background, when entering any other directory
                ;;
        esac
    }
    
    # add chback_on_chdir to chpwd_functions
    add-zsh-hook chpwd chback_on_chdir
    
  2. 更改背景颜色: 其实有两种方法可以更改背景颜色。

    • 您可以在终端可用的颜色范围内更改以下打印字符的背景(即您在示例中所做的)。在 zsh 中,这可以像这样完成(chdir 钩子的简化示例):

      # allow for parameter substitution in prompts
      setopt PROMPT_SUBST
      # add string `$COLOR` to $PS1. 
      # Note the `\` before `${COLOR}`, which prevents immediate evaluation.
      # `${COLOR}` will be substituted each time the prompt is printed
      PS1="$PS1${COLOR}"
      
      chpwd () {
          case $PWD in
              /mnt/data/* )
                  # set background color to red
                  COLOR='%K{red}'
                  ;;
              * )
                  # reset background color to default
                  COLOR='%k'
                  # could also be just an empty string
                  #COLOR=''
                  # or unset
                  #unset COLOR
                  ;;
          esac
      }
      
    • 在某些(很多?)终端中,您还可以重新定义默认背景颜色。这实际上会改变所有地方的背景颜色,甚至在已经打印的文本和 "unprinted" 位置。这可以通过利用 XTerm Control Sequences 来完成,尽管它们的名称不同,它也可以在其他终端仿真器中工作。 (我用 xtermurxvtgnome-terminaltermite 测试成功)。有问题的控制顺序是

      ESC]11;<color>ST
      

      其中 ESC 是转义字符 \e<color> 是颜色规范(例如 red#ff0000rgb:ff/00/00rgbi:1/0/0 - 实际工作可能取决于终端)和 ST 字符串终止符 \e\ (ESC\)。您可以使用

      将其发送到终端
      printf "\e]11;red\e\"
      

      您可以使用控制序列将颜色重置为配置的默认值

      ESC]111ST
      

      使用命令

      printf "\e]111\e\"
      

      因此,如果您通常有黑色背景,并且想在进入 /mnt/data 或它下面的目录时将其稍微染成红色,您可以使用:

      chpwd () {
          case $PWD in
              /mnt/data | /mnt/data/* )
                  # set background color to a dark red
                  printf "\e]11;#1f0000\e\"
                  ;;
              * )
                  # reset the background color to configured default
                  printf "\e]111\e\"
                  ;;
          esac
      }
      

      注意:我发现如果启用透明度,它似乎在 urxvt 上不起作用。

      可以通过将颜色规范替换为 ?:

      来检索当前值
      printf "\e]11;?\e\" ; sleep 1
      

      需要 sleep 1 以便输出不会立即被提示覆盖。