使用打印颜色的子命令设置 PS1

Set PS1 with subcommand that prints colors

当在 PS1 中放置 ANSI 颜色代码时,它们需要用 \[\] 包围,否则提示会混淆行的可编辑部分的开始位置。但是,当子命令 ($()) 打印颜色时,\[\] 转义总是按字面意义写入提示...并且在我的历史记录中使用足够长的命令,提示会变得混乱。

这是一个例子:

ps1test() {
    ps1sub() {
        printf '\[3[32m\]Hello!\[3[0m\]'
    }
    PS1='$(ps1sub) $ '
}

预计:

$ ps1test
Hello! $

实际(bash 由 Git 为 Windows 安装):

$ ps1test
\[\]Hello!\[\] $

如何让我的 shell 解释子命令的 \[\] 转义?

仅解释文字字符串中的 \[\[嵌入扩展产生的结果不是。

绕过它的最简单方法是让 PROMPT_COMMAND 每次都将 PS1 设置为新的文字值:

updateps1() {
    ps1sub() {
        printf '\[3[32m\]Hello $RANDOM!\[3[0m\]'
    }
    PS1="$(ps1sub) \$ "
}

PROMPT_COMMAND='updateps1'

如果您正在尝试创建动态提示,您可能更容易通过调用为 PROMPT_COMMAND 的函数设置 PS1 值,例如:

ps1test() {
  ps1sub() {
        printf '\[3[32m\]Hello!\[3[0m\]'
    }
    PS1="$(ps1sub)"' $ ' # notice the double-quote
}
PROMPT_COMMAND=ps1test

这对我来说正确呈现为 Hello! $

我使用 prompt.gem to render my prompt, you can take a look at how it configures PROMPT_COMMAND 来获得一些灵感。

这正是 eval 的正确用例:

ps1test() {  
    ps1sub() {  
        printf '\[3[31m\]Hello!\[3[0m\]';     
    };  
    eval PS1="'$(ps1sub) $ '"; 
}