PS1 中的 ANSI 转义序列导致长度计算不正确

PS1 中的 ANSI 转义序列导致长度计算不正确

PS1我的设置包含.zshrc多个 ANSI 转义序列。等效的定义在 Bash 中运行良好,但在 Zsh (v5.8.1) 中它似乎会导致 shell 错误地计算提示符的宽度。因此,当输入较长的命令时,命令行突然消失,我正在盲打。在某些情况下,它会导致光标被放置在提示后的下一行,即使PS1不包含换行符。

我已经在使用\001…\002转义序列readline 使用它们来调整每个 ANSI 转义序列的长度计算。不幸的是,这对于 Zsh 来说似乎还不够(在下面的例子中,他们似乎没有任何效果,但在我真实的、更复杂的情况下PS1,他们似乎改善了情况有些, 至少)。

下面是一个演示该问题的示例(注释强调了我认为需要用 括起来的 ANSI 转义序列部分\001…\002):

PS1=$'\001\e[38;2;1;1;1m\e[48;5;250m\002}\001\e[38;5;250m\e[48;2;1;1;1m\002} '
#     \001--------------------------\002 \001--------------------------\002

有了这个提示,并使用 80 列终端,在我输入 25 个字符后,包括提示在内的整个命令都会消失。使用退格键不会使字符重新出现,而是使光标转到上一行。

这是 Asciinema 对这种行为的记录。

对于此演示,我禁用了 shell 的所有其他自定义。

(实际上我正在使用nf-pl-left_hard_dividerU+E0B0,来自书呆子字体而不是}s,但这不会影响问题。)

我究竟做错了什么?如何在 Zsh 提示符定义中使用 ANSI 转义序列?

答案1

在 中zsh,您可以使用%{%}提示转义符。从info zsh 'prompt expansion':

%{...%}
包含一个字符串作为文字转义序列。大括号内的字符串不应更改光标位置。支撑对可以嵌套。

% 和 { 之间的正数值参数按照下面 %G 的描述进行处理。

因此,除了PS1='%{\e[...m%}'您不需要在 zsh 中硬编码转义序列之外,因为它有自己的提示扩展运算符来实现大多数视觉效果。

例如,要将256 调色板中的F背景颜色设置为 RGB#010101并将背景颜色设置为 250,您可以执行以下操作:B

PS1='%F{#010101}%K{250}Text%f%k%# '

您可以使用print -P它也进行提示扩展,以查看正在生成哪些相应的转义序列:

$ print -rP '%F{#010101}%K{250}' | sed -n l
\033[38;2;1;1;1m\033[48;5;250m$

甚至还有一个模块可以为不支持真彩色转义序列(但支持 256 调色板)的终端上的规范zsh/nearcolor提供最接近的颜色:#RRGGBB

$ zmodload zsh/nearcolor
$ print -rP '%F{#010101}%K{250}' | sed -n l
\033[38;5;16m\033[48;5;250m$

相关内容