当从bash迁移到zsh时,当无法再使用PS1来更改终端标题时,可以采取以下解决方法

首先

在从Bash转换到Zsh的过程中,我正在将.bashrc文件改写为.zshrc文件,但是以下的提示显示设置部分无法正常工作了。

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

原因:转义字符处理的差异。

导致无法移动的原因是在$PS1中使用了转义字符\e。
\[\e]0;~\a\]是用来改变xterm图标名称和标题的控制序列。
ESC ]表示OS控制命令的开始,OSC 0 ; BEL 可以将标题更改为。

 

在zsh中,与bash不同的是对转义字符的处理。在bash中,\[~\]被用作转义处理的开始和结束标记,但在zsh中,我们使用%{~%}来表示转义处理的开始和结束。
然而,zsh中的%{~%}不能在普通的引号字符串(’~’或”~”)中使用,似乎需要将其变为特殊字符字符串($’~’)并加上$符号。

 

解决方法1: 提取出逃逸处理并置入另一个环境变量中

如果将“~”替换为$’~’,似乎只有转义处理了,环境变量没有被替换。

# bashのプロンプト設定
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"

# zsh用に"~"を$'~'、\u@\hを%n@%m、\wを%~に置き換えるが動かない
PS1=$'\e]0;${debian_chroot:+($debian_chroot)}%n@%m: %~\a$PS1'
-> これは${debian_chroot:+($debian_chroot)}$PS1が置き換えられず、
   タイトルが ${debian_chroot:+($debian_chroot)}%n@%m: %~ になり
   $PS1 とプロンプトにそのまま表示されてしまう

将执行“エスケープ処理”的部分在$’~’中,并准备一个独立的环境变量来使用,这样不知为什么就可以正常运行。
(可能是处理顺序的问题?)

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    DISABLE_AUTO_TITLE=true # タイトルをプロンプト表示時に書き換えるために自動設定を解除する
    PS1_TITLE=$'\e]0;${debian_chroot:+($debian_chroot)}%n@%m: %~\a' # bashで\[~\]だった部分
    PS1="${PS1_TITLE}${PS1}"
    ;;
*)
    ;;
esac

解决方案2:在precmd中设置标题变更,在显示提示符之前。

在zsh中,有一个称为precmd的hook函数(在bash中称为PROMPT_COMMAND变量)被定义。
因此,通过自定义precmd函数,可以执行各种处理操作。

# bashの場合
PROMPT_COMMAND="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]"

# zshの場合
function precmd() { print -Pn $'\e]0;${debian_chroot:+($debian_chroot)}%n@%m: %~\a' }

用以下方式可以进行改写。

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    DISABLE_AUTO_TITLE=true # タイトルをプロンプト表示時に書き換えるために自動設定を解除する
    function precmd() { print -Pn $'\e]0;${debian_chroot:+($debian_chroot)}%n@%m: %~\a' }
    ;;
*)
    ;;
esac

 

选项1: 添加一个自定义函数来将标题更改为precmd处理

据说zsh的hook函数有一种机制,即在函数名后面加上_functions,可以定义一个与该hook函数相同执行的函数数组,并且使用add-zsh-hook这个shell函数,可以对函数数组进行添加和删除操作。

# hookに追加する自作関数
function myhook () {
  # hookで実行したい処理
}

# hookへの追加
autoload -Uz add-zsh-hook
add-zsh-hook <hook名> myhook

如果在precmd中已经定义了其他处理,则可以使用它来添加自定义函数到precmd。

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    DISABLE_AUTO_TITLE=true # タイトルをプロンプト表示時に書き換えるために自動設定を解除する
    function precmd_mytitle() { print -Pn $'\e]0;${debian_chroot:+($debian_chroot)}%n@%m: %~\a' }
    autoload -Uz add-zsh-hook    
    add-zsh-hook precmd precmd_mytitle # precmdにprecmd_mytitle関数を追加
    ;;
*)
    ;;
esac

 

总结

在使用bash和zsh时,它们之间有微妙的区别,切换对我来说有点困难。

广告
将在 10 秒后关闭
bannerAds