使用Golang创建终端提示符
使用Golang创建终端提示符 我最近开始着手一个小的业余项目,目标是创建一个属于自己的终端提示符。这个提示符可以通过JSON文件进行配置,因为我对bash和**.bashrc**几乎一无所知。当我在终端中运行我的程序时,它看起来还行,颜色也能正常显示:

第一行是我当前的提示符,所以请忽略第一行。第二行显示的是我程序当前的输出,请忽略它极其丑陋的外观以及颜色乱七八糟的情况,这不是问题所在。我目前正在测试很多东西,只是在我的JSON文件中随意挑选想到的第一个颜色。
问题是,当我在我的**.bashrc**中写入:
PS1="\$(/home/per/code/go-prompt/build/go_prompt)"
然后提示符就失去了所有的颜色:

这可能是一个bash问题,而不是Go问题,所以这可能不是提出此类问题的最佳论坛,但我先在这里尝试一下。有谁知道为什么颜色会消失吗?我是否需要在Go程序中添加一个或几个特殊字符来初始化颜色(以便终端理解颜色),或者我需要在**.bashrc中添加一些东西,还是说根本不可能使用另一种语言(除了bash**)来创建终端提示符?
如果这很重要的话,我是在一台运行Linux Mint 20.2的机器上测试的,并且我使用的是Go 1.17。
(不完整的)代码可以在这里找到:GitHub - Hultan/goprompt: A terminal prompt configurable using a JSON file
更多关于使用Golang创建终端提示符的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我只是粗略浏览了代码,但你似乎使用了一个库,如果它没有检测到TTY,就会禁用颜色。这通常是件好事。你需要找到一种方法,在没有TTY可用的情况下强制启用颜色。
更多关于使用Golang创建终端提示符的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
啊,谢谢!我刚刚做了一个小测试,发现有一个名为 NoColor 的标志(在 color 包中),当通过 .bashrc 运行时,它的值是不同的。所以你几乎肯定是正确的,现在我知道该如何继续了……谢谢!
编辑:color 包中有一个名为 enableColor() 的函数,它解决了这个问题。现在即使通过 .bashrc 使用,我也有颜色了。我之前太专注于 bash 是问题所在,以至于完全忽略了这一点。再次感谢!
这是一个典型的终端转义序列处理问题。当你在.bashrc中设置PS1时,bash会解析其中的转义字符,导致颜色代码被错误处理。
问题在于bash会解析PS1中的反斜杠转义序列。你需要使用\[和\]来包裹ANSI转义序列,这样bash就知道这些序列不占用可见空间。
在你的Go程序中,你需要输出带\[和\]包裹的颜色代码。修改你的颜色输出函数:
package main
import (
"fmt"
)
const (
Reset = "\\[\\033[0m\\]"
Bold = "\\[\\033[1m\\]"
Red = "\\[\\033[31m\\]"
Green = "\\[\\033[32m\\]"
Yellow = "\\[\\033[33m\\]"
Blue = "\\[\\033[34m\\]"
Magenta = "\\[\\033[35m\\]"
Cyan = "\\[\\033[36m\\]"
White = "\\[\\033[37m\\]"
BgRed = "\\[\\033[41m\\]"
BgGreen = "\\[\\033[42m\\]"
BgYellow = "\\[\\033[43m\\]"
BgBlue = "\\[\\033[44m\\]"
BgMagenta = "\\[\\033[45m\\]"
BgCyan = "\\[\\033[46m\\]"
BgWhite = "\\[\\033[47m\\]"
)
func main() {
// 示例:输出带颜色的提示符
fmt.Printf("%s%suser@host%s:%s%s~%s$ %s",
Green, Bold, Reset, Blue, Bold, Reset, Reset)
}
或者,更好的方法是创建一个函数来生成带转义的颜色代码:
func colorize(colorCode, text string) string {
return fmt.Sprintf("\\[\\033[%sm\\]%s\\[\\033[0m\\]", colorCode, text)
}
func main() {
// 使用示例
fmt.Print(colorize("1;32", "user@host")) // 粗体绿色
fmt.Print(":")
fmt.Print(colorize("1;34", "~")) // 粗体蓝色
fmt.Print("$ ")
}
另一个解决方案是在.bashrc中使用单引号而不是双引号,并让Go程序输出原始ANSI代码:
PS1='$(/home/per/code/go-prompt/build/go_prompt)'
然后在Go中输出原始ANSI序列:
const (
Reset = "\033[0m"
Red = "\033[31m"
Green = "\033[32m"
// ... 其他颜色
)
func main() {
fmt.Printf("%s%suser@host%s:%s%s~%s$ %s",
Green, Bold, Reset, Blue, Bold, Reset, Reset)
}
两种方法都可以,但第一种方法(在Go中输出\[和\])更可靠,因为它明确告诉bash哪些部分是非打印字符。

