ZSH提示替换问题

ZSH提示替换问题,zsh,prompt,ansi-escape,Zsh,Prompt,Ansi Escape,我在这里和谷歌上搜索了几个答案,但我仍然不确定我的提示出了什么问题 根据我读过的文档,这应该行得通 setopt prompt_subst autoload -U colors && colors PROMPT="%{[00m[38;5;245m%}test %D%{[00m%}" 但是,我的提示如下: [00m[38;5;245mtest 15-07-01[00m 请注意,日期扩展实际上是有效的,因此即时替换是有效的。用于提示扩展的ZSH手册页声明,%{…%}应被视为原始转

我在这里和谷歌上搜索了几个答案,但我仍然不确定我的提示出了什么问题

根据我读过的文档,这应该行得通

setopt prompt_subst
autoload -U colors && colors
PROMPT="%{[00m[38;5;245m%}test %D%{[00m%}"
但是,我的提示如下:

[00m[38;5;245mtest 15-07-01[00m
请注意,日期扩展实际上是有效的,因此即时替换是有效的。用于提示扩展的ZSH手册页声明,
%{…%}
应被视为原始转义代码,但这似乎没有发生。将该字符串传递到
print-P
也会产生上述输出。我在互联网上找到了ZSH的示例提示,它似乎也表明上述语法应该有效。请参见一个示例,$FG和$FX数组由转义码填充并定义。我通过合并上面的两个文件直接尝试了这个示例,将
setopt prompt\u subst
添加到开头,只是为了确保它已设置,然后将其寻源,提示是一堆转义代码

以下作品

setopt prompt_subst
autoload -U colors && colors
PROMPT=$'%{\e[00m\e[38;5;245m%}test %D%{\e[00m%}'
我得到了测试15-07-01的预期结果,颜色正确


我已经在OSX Yosimite中的ZSH 5.0.5、MacPorts中的5.0.7和Debian上的4.3.17上进行了测试,得到了相同的结果。我知道我已经用这个工作示例为我自己的问题提供了一个有效的解决方案,但是我想知道为什么第一个语法没有像它看起来应该的那样工作。

我认为这一切都与逃避这个永恒的问题有关。值得提醒我们自己转义是什么意思,简单地说:转义字符是计算机的一个指示器,后面的内容不应该按字面意思输出

因此,有两个逃逸问题:
PROMPT=“%{[00m[38;5;245m%}测试%D%{[00m%}”

  • 首先,颜色转义序列(例如,
    [00m
    )都应该以控制字符开头,如so
    \e[00m
    。您可能还看到它被写成
    ^[00m
    \003[00m
    。我怀疑发生的是,其中一种变体的常见命运是,作者或网站框架堆栈的复制/粘贴(无论是在数据库、HTTP呈现还是JS解析中的某个地方)无意中逃逸了。控制字符(即,
    ^
    \e
    \003
    ),正如您可能知道的,没有文字表示,比如说,如果您在键盘上按它。这就是为什么web堆栈可能会决定不显示任何内容,如果它在字符串中看到它。现在让我们更正一下:

    PROMPT=“%{\e[00m\e[38;5;245m%}测试%D%{\e[00m%}”

  • 这实际上很好地进入了下一个转义问题[实际上是
    ESC
    的一种表示形式,因此它本身就是一个转义序列标记,是的,它反过来又被
    转义。这是旧
    的一种重复。现在,重要的是,我们必须弄清楚终端转义表达式和字符串替代表达式之间的区别以伪代码形式显示提示的ON:

    PROMPT=“%{terminal color stuff%}测试%D%{terminal color stuff%}”

    现在我怀疑正在发生的事情,尽管我找不到任何文档来证明这一点,是一旦ZSH完成了它的替换,或者在替换过程中,所有的文字字符,不管转义的含义如何,都会被提升为真实的字符。为了更进一步的闹剧,这种提升很可能是通过转义所有的转义来完成的cape字符。例如,如果您确实想在命令行上打印“\e”,则必须执行
    echo“\\\e”
    。为了克服这个问题,我们只需要确保“终端颜色填充”转义序列在分配给
    提示符之前得到评估,这可以通过
    $”
    模式简单地完成,如下所示:

    PROMPT=$'%{\e[00m\e[38;5;245m%}测试%D%{\e[00m%}'

    请注意,
    $'
    $()
    ${}
    具有相同的功能,只是它的唯一功能是解释转义序列

  • [1] 我对此的怀疑是基于这样一个事实,即你实际上可以做如下事情:

    PROMPT='$(日期)

    其中,
    $(date)
    的作用与
    %D
    相同,即为屏幕上的每个新提示输出打印日期的实时版本。此特定示例旨在说明
    提示
    变量实际上应被视为迷你脚本的存储,而不是字符串(尽管承认这两个概念之间存在重叠,因此会产生混淆)。因此,作为脚本,首先对字符串求值,然后打印。我没有看过ZSH的提示呈现代码,但我认为这种求值将受益于转义序列的本机使用。例如,如果希望将转义序列作为参数传递给某个命令(为每个提示呈现运行的命令),该怎么办例如,在提示中,以下功能与上面讨论的提示相同:

    PROMPT='%{$(print“\e[00m\e[38;5;245m”)%}test$(date)%{$(print“\e[00m”)%}


    转义序列按字面形式存储,仅在每次提示呈现时进行解释。

    这里没有问题;如果您正在阅读的文档省略了转义字符,则是错误的。指示终端切换颜色的ANSI代码都以
    ESC[
    开头,而不仅仅是
    [
    。请注意,使用内置转义来更改颜色比处理原始控制序列更容易。
    prompt=“%F{245}test%D%F”
    您可能会假设
    %{…%}
    为每个序列的开头提供转义字符;它实际上只是指示shell大括号的内容在输出中占据零空间,以便计算正确的屏幕提示长度。Th