73 lines
2.7 KiB
Go
73 lines
2.7 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package presentation
|
|
|
|
import (
|
|
"fmt"
|
|
"git.stormux.org/storm/fenrir/internal/i18n"
|
|
"git.stormux.org/storm/fenrir/internal/screen"
|
|
"strings"
|
|
)
|
|
|
|
// Default_attribute_format is Python Fenrir's default, including its tokens.
|
|
const Default_attribute_format = "Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize"
|
|
|
|
func attribute_color(color uint32, background bool) string {
|
|
if color == screen.ColorDefault {
|
|
return i18n.T("default")
|
|
}
|
|
if color&screen.ColorIndexed == 0 {
|
|
return fmt.Sprintf("#%06x", color)
|
|
}
|
|
index := color &^ screen.ColorIndexed
|
|
names := []string{"black", "red", "green", "brown/yellow", "blue", "magenta", "cyan", "light gray", "dark gray", "light red", "light green", "light yellow", "light blue", "light magenta", "light cyan", "white"}
|
|
if index < 16 {
|
|
if background && index == 7 {
|
|
return i18n.T("white")
|
|
}
|
|
return i18n.T(names[index])
|
|
}
|
|
// xterm's fixed 256-color cube and grayscale, without approximate names.
|
|
if index < 232 {
|
|
level := []uint32{0, 95, 135, 175, 215, 255}
|
|
index -= 16
|
|
return fmt.Sprintf("#%02x%02x%02x", level[index/36], level[index/6%6], level[index%6])
|
|
}
|
|
value := 8 + 10*(index-232)
|
|
return fmt.Sprintf("#%02x%02x%02x", value, value, value)
|
|
}
|
|
|
|
// Format_attributes substitutes the Python tokens. Font metadata is not
|
|
// available from either backend; default means unspecified, not a detected font.
|
|
func Format_attributes(attribute screen.Attribute, format string) string {
|
|
pairs := []string{"fenrirFGColor", attribute_color(attribute.Foreground, false), "fenrirBGColor", attribute_color(attribute.Background, true), "fenrirFontSize", i18n.T("default"), "fenrirFont", i18n.T("default")}
|
|
for _, style := range []struct {
|
|
token, text string
|
|
mask uint32
|
|
}{
|
|
{"fenrirBold", "bold", screen.Bold}, {"fenrirItalics", "italic", screen.Italic},
|
|
{"fenrirUnderline", "underline", screen.Underline}, {"fenrirStrikethrough", "strikethrough", screen.Strike},
|
|
{"fenrirReverse", "reverse", screen.Reverse}, {"fenrirBlink", "blink", screen.Blink},
|
|
} {
|
|
text := ""
|
|
if attribute.Style&style.mask != 0 {
|
|
text = i18n.T(style.text)
|
|
}
|
|
pairs = append(pairs, style.token, text)
|
|
}
|
|
return strings.NewReplacer(pairs...).Replace(format)
|
|
}
|
|
|
|
func Attribute_message(attribute screen.Attribute, mode, format string) Message {
|
|
text := Format_attributes(attribute, format)
|
|
if mode == "beeps" || strings.TrimSpace(text) == "" && !attribute.Default() {
|
|
text = i18n.T("has attribute")
|
|
}
|
|
message := Message{Text: text, Attributes: &Attributes{Speech: mode != "beeps"}}
|
|
if mode == "beeps" || mode == "both" {
|
|
message.Cue = HasAttributes
|
|
}
|
|
return message
|
|
}
|