ZSH提示替换问题

时间:2015-07-01 16:07:12

标签: 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手册页指出%{...%}应被视为原始转义码,但这似乎并未发生。将该字符串传递给print -P也会导致上面的输出。我在互联网上找到了ZSH的示例提示,似乎也表明上述语法应该有效。有关一个示例,请参阅this - $ FG和$ FX数组填充了转义码,并定义为here。我已经通过合并上面的两个文件直接尝试了这个例子,将setopt prompt_subst添加到开头只是为了确保它已设置,然后获取它并且提示符是一堆转义代码。

以下作品

setopt prompt_subst
autoload -U colors && colors
PROMPT=$'%{\e[00m\e[38;5;245m%}test %D%{\e[00m%}'

我得到test 15-07-01的正确颜色的预期结果。

我在OSX Yosimite的ZSH 5.0.5,MacPorts的5.0.7和Debian的4.3.17上进行了测试,结果相同。我知道我已经通过工作示例为我自己的问题提供了一个有效的解决方案,但我想知道为什么第一个语法不能正常工作。

1 个答案:

答案 0 :(得分:0)

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

因此有两个逃避问题: PROMPT="%{[00m[38;5;245m%}test %D%{[00m%}"

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

      

    PROMPT="%{\e[00m\e[38;5;245m%}test %D%{\e[00m%}"

  2. 这实际上很好地代表了下一个逃避问题。有些滑稽\e[实际上是ESC的表示,因此它本身就是一个转义序列标记,是的,由\转义。对于旧\\\\\\\\\\这个笑话,这是一个riff。现在,显而易见,我们必须清楚终端的转义表达式和提示符的字符串替换之间的区别,伪代码:

      

    PROMPT="%{terminal colour stuff%}test %D%{terminal colour stuff%}"

    现在我怀疑正在发生的事情,虽然我找不到任何证明它的文件,但是一旦ZSH完成了替换,或者在替换过程中,所有文字字符,无论逃避意义如何,都被提升为真实的人物¹。为了进一步推进这场闹剧,这次推广很可能是通过逃避所有逃脱角色来完成的。例如,如果您确实想在命令行上打印'\ e',则必须执行echo "\\\e"。因此,为了克服这个问题,我们只需要确保在分配给PROMPT之前评估'终端颜色东西'转义序列并且可以完成只需使用$''模式,就像这样:

      

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

    请注意,$''$()${}属于同一类,但其唯一的功能是解释转义序列。

  3. [1]我对此的怀疑是基于这样一个事实,即您实际上可以执行以下操作:

      

    PROMPT='$(date)'

    其中$(date)%D的用途相同,方法是将每个新提示输出的 live 版本打印到屏幕上。这个具体的例子用来证明PROMPT变量应该被认为是迷你脚本的存储,而不是字符串(尽管这两个概念之间存在重叠,从而导致混淆)。因此,作为脚本,字符串首先评估,然后打印。我没有看过ZSH的快速渲染代码,但我认为这样的评估会受益于转义序列的本地使用。例如,如果要将转义序列作为参数传递给提示中的命令(为每个提示渲染运行的命令),该怎么办?例如,以下功能与上面讨论的提示相同:

      

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

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