term: add writeln_color() (#24463)

This commit is contained in:
kbkpbot 2025-05-15 18:37:13 +08:00 committed by GitHub
parent 558c034efd
commit 4c530217d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 97 additions and 2 deletions

View File

@ -3,6 +3,8 @@
// that can be found in the LICENSE file.
module term
import strings
// format_esc produces an ANSI escape code, for selecting the graphics rendition of the following
// text. Each of the attributes that can be passed in `code`, separated by `;`, will be in effect,
// until the terminal encounters another SGR ANSI escape code. For more details about the different
@ -275,3 +277,77 @@ pub fn bright_bg_white(msg string) string {
pub fn highlight_command(command string) string {
return bright_white(bg_cyan(' ${command} '))
}
pub enum TextStyle {
bold = 1
dim = 2
italic = 3
underline = 4
blink = 5
reverse = 7
}
pub enum FgColor {
black = 30
red = 31
green = 32
yellow = 33
blue = 34
magenta = 35
cyan = 36
white = 37
}
pub enum BgColor {
black = 40
red = 41
green = 42
yellow = 43
blue = 44
magenta = 45
cyan = 46
white = 47
}
@[params]
pub struct ColorConfig {
pub mut:
styles []TextStyle
fg ?FgColor
bg ?BgColor
custom string
}
// write_color appends the ANSI colorful string `s` to the buffer.
pub fn write_color(mut b strings.Builder, s string, config ColorConfig) {
mut codes := []string{cap: 3}
for style in config.styles {
codes << int(style).str()
}
if fg := config.fg {
codes << int(fg).str()
}
if bg := config.bg {
codes << int(bg).str()
}
if config.custom != '' {
codes << config.custom
}
if codes.len > 0 {
code_str := codes.join(';')
b.write_string('\x1b[${code_str}m${s}\x1b[0m')
} else {
b.write_string(s)
}
}
// writeln_color appends the ANSI colorful string `s`, and then a newline character.
pub fn writeln_color(mut b strings.Builder, s string, color ColorConfig) {
write_color(mut b, s, color)
b.writeln('')
}

View File

@ -1,5 +1,6 @@
import os
import term
import strings
fn test_get_terminal_size() {
cols, _ := term.get_terminal_size()
@ -113,14 +114,32 @@ fn test_set_tab_title() {
}
fn test_strip_ansi() {
strings := [
string_list := [
'abc',
term.bold('abc'),
term.yellow('abc'),
term.bold(term.red('abc')),
term.strikethrough(term.inverse(term.dim(term.bold(term.bright_bg_blue('abc'))))),
]
for s in strings {
for s in string_list {
assert term.strip_ansi(s) == 'abc'
}
}
fn test_write_color() {
mut sb := strings.new_builder(100)
term.writeln_color(mut sb, 'hello')
term.writeln_color(mut sb, 'hello', fg: .red)
term.writeln_color(mut sb, 'hello', bg: .cyan)
term.writeln_color(mut sb, 'hello', styles: [.bold, .italic, .underline], fg: .red, bg: .cyan)
term.writeln_color(mut sb, 'hello', custom: '38;5;214')
output := sb.str()
println(output)
assert output.contains('\x1b[0m')
assert output.contains('\x1b[31m')
assert output.contains('\x1b[46m')
assert output.contains('\x1b[1;3;4;31;46m')
assert output.contains('\x1b[38;5;214m')
}