如何在 zsh 提示符中格式化路径?

如何在 zsh 提示符中格式化路径?

我希望有一条可读的彩色路径。例如,与其简单地使用 %~ 返回,~/path/to/foo我还想将其格式化以~$RED/$NOCOLORpath$RED/$NOCOLORto$RED/$NOCOLORfoo突出显示路径分隔符。

我可以定义 PROMPT 的内容,以便路径表达式在每次显示时重新评估吗?${${(%):-%~}//\//_some_format_expression/}显然,这样做是行不通的。

或者我应该进一步破解这个问题,并在每次我们更改目录时强制重置 PROMPT 值?

任何实现路径格式化目标的解决方案都会受到欢迎。

谢谢 :)

答案1

尝试这个:

setopt PROMPT_SUBST
PROMPT='%{$(pwd|grep --color=always /)%${#PWD}G%} %(!.%F{red}.%F{cyan})%n%f@%F{yellow}%m%f%(!.%F{red}.)%#%f '

以下是该提示的详细说明:

  • PROMPT_SUBST 打开提示中的命令替换(以及参数扩展和算术扩展)
  • %{...%}- 转义序列
  • $(pwd|grep --color=always /)- 打印当前目录并突出显示/- 颜色将取决于 $GREP_COLORS 环境变量(或其默认值) - 粗体红色是默认值
  • %${#PWD}G- 使用当前目录名称的字符长度作为故障值。这会使 shell 将其视为前一个字符序列(在“ %{”之后)的长度,而不是包含 ANSI 转义序列的字符串的实际长度。这可防止 shell 对光标相对于提示符末尾的位置感到困惑。
    - - - - - - - 这是回答你问题的部分的结尾 - - - - - - -
  • %(!.%F{red}.%F{cyan})- 如果这是特权 shell(root),则将前景色设置为红色,否则为青色
  • %n- 输出用户名
  • %f- 将前景色重置为默认值
  • @- 文字 at 符号
  • %F{yellow}- 将前景色设为黄色
  • %m– 输出主机名
  • %f- 将前景色重置为默认值
  • %(!.%F{red}.)- 如果这是特权 shell(root),则将前景色设置为红色
  • %#- 输出 a#表示有特权的 shell,否则%表示无特权的 shell
  • %f- 将前景色重置为默认值

为了强调,我把路径放在这个提示的第一位,因为问题与路径有关。

替代文本

这是 zsh 的版本,它通过操作$GREP_COLORS变量来根据您是否是 root (特权)来改变斜线颜色:

setopt PROMPT_SUBST
PROMPT='%{$(pwd|([[ $EUID == 0 ]] && GREP_COLORS="mt=01;31" grep --color=always /|| GREP_COLORS="mt=01;34" grep --color=always /))%${#PWD}G%} %(!.%F{red}.%F{cyan})%n%f@%F{yellow}%m%f%(!.%F{red}.)%#%f '

猛击

您可以在 Bash 中执行类似的提示。在此示例中,我将用户和主机名放在首位,并且当 UID 为 0 时,斜线的颜色也会发生变化。警告:这会覆盖 Bash 的$PS1提示变量。除非您正在执行某些特殊操作,或者您希望在直接设置该变量时行为发生变化并且此操作有效,否则这不会成为问题。此外,这使用了一个名为“ usercolor”的变量,该变量可能会与其他变量发生冲突,尽管可以将整个变量放在函数中并将变量声明为本地变量。

PROMPT_COMMAND='usercolor="\[\033[0;36m\]";[[ $EUID == 0 ]] && usercolor="\[\033[1;31m\]";PS1="$(pwd)";PS1="$usercolor\u\[\033[0m\]@\[\033[0;33m\]\h\[\033[0m\]:${PS1//\//$usercolor/\[\033[0m\]}$usercolor\\$\[\033[0m\] "'

替代文本

我利用 Bash 没有 zsh 的“故障”功能这一事实来使用参数扩展替换来有条件地为斜线着色(而不是使用 grep)。

答案2

纯 zsh 解决方案:

PROMPT='%n@%m: %{$PR_BOLD_RED%}${${(%):-%~}//\//${PR_BOLD_RED}/%f}%f '
  • ${(%):-%~}是当前路径。
  • ${xxxxx//\//${PR_BOLD_RED}/%f}将 xxxxx 中的每个 / 替换为粗体红色
  • 当然,PROMPT_SUBST 必须处于打开状态。

我在测试中使用了双引号,这不允许替换。使用单引号一切正常。

答案3

经过一番周折,我可以提供一个解决方案chpwd

doprompt() {
  local my_path=${(%):-%~}
  PROMPT="${yourstuff}${my_path//\//${PR_BOLD_RED}/${reset_color}}${otherstuff}"
}
doprompt

chpwd() {
  doprompt
  # unrelated: set window title
  [[ -t 1 ]] || return;
  print -Pn "\e]2;%n@%m: %~\a";
}
  • 有没有办法改进此代码以摆脱临时my_path变量?我无法直接替换 %~ 内的 /...
  • 任何使用动态语法来避免每次目录更改时调用的解决方案doprompt都可能更清晰。

答案4

这是我的尝试(基于 NicDumZ 的):

setopt PROMPT_SUBST
# red, green, yellow, blue, magenta, cyan, white, black
# B (bold), K(background color), F(foreground color)

function doprompt {
# this is just the directory (%d could be %~ -- I prefer full path always)
PROMPT='%F{yellow}${${(%):-%d}//\//%F{magenta\}%B/%b%F{yellow\}}%f'
}

function chpwd() {
    doprompt
}

不同之处在于我使用的是彩色路径,因此一旦斜线被着色,我就需要将路径恢复为原始颜色。在我的例子中,路径通常是黄色,斜线被着色为洋红色,然后又恢复为黄色。我还更喜欢使用 %F%f 序列,因为它们对我来说更具可读性。

相关内容