使用Golang创建终端提示符

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

goPrompt-ugly-but-working

第一行是我当前的提示符,所以请忽略第一行。第二行显示的是我程序当前的输出,请忽略它极其丑陋的外观以及颜色乱七八糟的情况,这不是问题所在。我目前正在测试很多东西,只是在我的JSON文件中随意挑选想到的第一个颜色。

问题是,当我在我的**.bashrc**中写入:

PS1="\$(/home/per/code/go-prompt/build/go_prompt)"	

然后提示符就失去了所有的颜色:

goPrompt-not-working

这可能是一个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

3 回复

我只是粗略浏览了代码,但你似乎使用了一个库,如果它没有检测到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哪些部分是非打印字符。

回到顶部