Code to dump basic colors from a theme as escape codes
This commit is contained in:
parent
c1791c8d2b
commit
c877b2a5cb
4 changed files with 118 additions and 13 deletions
|
|
@ -427,11 +427,24 @@ def generate_spinners() -> str:
|
|||
|
||||
|
||||
def generate_color_names() -> str:
|
||||
selfg = "" if Options.selection_foreground is None else Options.selection_foreground.as_sharp
|
||||
selbg = "" if Options.selection_background is None else Options.selection_background.as_sharp
|
||||
cursor = "" if Options.cursor is None else Options.cursor.as_sharp
|
||||
return 'package style\n\nvar ColorNames = map[string]RGBA{' + '\n'.join(
|
||||
f'\t"{name}": RGBA{{ Red:{val.red}, Green:{val.green}, Blue:{val.blue} }},'
|
||||
for name, val in color_names.items()
|
||||
) + '\n}' + '\n\nvar ColorTable = [256]uint32{' + ', '.join(
|
||||
f'{x}' for x in Options.color_table) + '}\n'
|
||||
f'{x}' for x in Options.color_table) + '}\n' + f'''
|
||||
var DefaultColors = struct {{
|
||||
Foreground, Background, Cursor, SelectionFg, SelectionBg string
|
||||
}}{{
|
||||
Foreground: "{Options.foreground.as_sharp}",
|
||||
Background: "{Options.background.as_sharp}",
|
||||
Cursor: "{cursor}",
|
||||
SelectionFg: "{selfg}",
|
||||
SelectionBg: "{selbg}",
|
||||
}}
|
||||
'''
|
||||
|
||||
|
||||
def load_ref_map() -> Dict[str, Dict[str, str]]:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package themes
|
|||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -17,6 +18,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -140,12 +142,12 @@ type ThemeMetadata struct {
|
|||
Author string `json:"author"`
|
||||
}
|
||||
|
||||
func parse_theme_metadata(path string) (*ThemeMetadata, string, error) {
|
||||
func parse_theme_metadata(path string) (*ThemeMetadata, map[string]string, error) {
|
||||
var in_metadata, in_blurb, finished_metadata bool
|
||||
ans := ThemeMetadata{}
|
||||
settings := utils.NewSet[string]()
|
||||
settings := map[string]string{}
|
||||
read_is_dark := func(key, val string) (err error) {
|
||||
settings.Add(key)
|
||||
settings[key] = val
|
||||
if key == "background" {
|
||||
val = strings.TrimSpace(val)
|
||||
if val != "" {
|
||||
|
|
@ -197,25 +199,25 @@ func parse_theme_metadata(path string) (*ThemeMetadata, string, error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
source := ""
|
||||
cp := config.ConfigParser{LineHandler: read_is_dark, CommentsHandler: read_metadata, SourceHandler: func(code, path string) { source = code }}
|
||||
cp := config.ConfigParser{LineHandler: read_is_dark, CommentsHandler: read_metadata}
|
||||
err := cp.ParseFiles(path)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
return nil, nil, err
|
||||
}
|
||||
ans.Num_settings = settings.Len()
|
||||
return &ans, source, nil
|
||||
ans.Num_settings = len(settings)
|
||||
return &ans, settings, nil
|
||||
}
|
||||
|
||||
type Theme struct {
|
||||
metadata *ThemeMetadata
|
||||
|
||||
code string
|
||||
settings map[string]string
|
||||
zip_reader *zip.File
|
||||
is_user_defined bool
|
||||
}
|
||||
|
||||
func (self *Theme) Code() (string, error) {
|
||||
func (self *Theme) load_code() (string, error) {
|
||||
if self.zip_reader != nil {
|
||||
f, err := self.zip_reader.Open()
|
||||
self.zip_reader = nil
|
||||
|
|
@ -232,6 +234,86 @@ func (self *Theme) Code() (string, error) {
|
|||
return self.code, nil
|
||||
}
|
||||
|
||||
func (self *Theme) Settings() (map[string]string, error) {
|
||||
if self.zip_reader != nil {
|
||||
code, err := self.load_code()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
self.settings = make(map[string]string, 64)
|
||||
scanner := bufio.NewScanner(strings.NewReader(code))
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line != "" && line[0] != '#' {
|
||||
key, val, found := strings.Cut(line, " ")
|
||||
if found {
|
||||
self.settings[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.settings, nil
|
||||
}
|
||||
|
||||
func (self *Theme) AsEscapeCodes() (string, error) {
|
||||
settings, err := self.Settings()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
w := strings.Builder{}
|
||||
w.Grow(4096)
|
||||
|
||||
w.WriteString("\033]4")
|
||||
set_color := func(i int, sharp string) {
|
||||
w.WriteByte(';')
|
||||
w.WriteString(strconv.Itoa(i))
|
||||
w.WriteByte(';')
|
||||
w.WriteString(sharp)
|
||||
}
|
||||
|
||||
set_default_color := func(name, defval string, num int) {
|
||||
w.WriteString("\033]")
|
||||
defer func() { w.WriteString("\033\\") }()
|
||||
val, found := settings[name]
|
||||
if !found {
|
||||
val = defval
|
||||
}
|
||||
if val != "" {
|
||||
rgba, err := style.ParseColor(val)
|
||||
if err == nil {
|
||||
w.WriteString(strconv.Itoa(num))
|
||||
w.WriteByte(';')
|
||||
w.WriteString(rgba.AsRGBSharp())
|
||||
return
|
||||
}
|
||||
}
|
||||
w.WriteByte('1')
|
||||
w.WriteString(strconv.Itoa(num))
|
||||
}
|
||||
set_default_color("foreground", style.DefaultColors.Foreground, 10)
|
||||
set_default_color("background", style.DefaultColors.Background, 11)
|
||||
set_default_color("cursor", style.DefaultColors.Cursor, 12)
|
||||
set_default_color("selection_background", style.DefaultColors.SelectionBg, 17)
|
||||
set_default_color("selection_foreground", style.DefaultColors.SelectionFg, 19)
|
||||
|
||||
for i := 0; i < 256; i++ {
|
||||
key := "color" + strconv.Itoa(i)
|
||||
val := settings[key]
|
||||
if val != "" {
|
||||
rgba, err := style.ParseColor(val)
|
||||
if err == nil {
|
||||
set_color(i, rgba.AsRGBSharp())
|
||||
continue
|
||||
}
|
||||
}
|
||||
rgba := style.RGBA{}
|
||||
rgba.FromRGB(style.ColorTable[i])
|
||||
set_color(i, rgba.AsRGBSharp())
|
||||
}
|
||||
w.WriteString("\033\\")
|
||||
return w.String(), nil
|
||||
}
|
||||
|
||||
type Themes struct {
|
||||
name_map map[string]*Theme
|
||||
index_map []string
|
||||
|
|
@ -265,7 +347,7 @@ func (self *Themes) add_from_dir(dirpath string) error {
|
|||
if m.Name == "" {
|
||||
m.Name = theme_name_from_file_name(e.Name())
|
||||
}
|
||||
t := Theme{metadata: m, is_user_defined: true, code: conf}
|
||||
t := Theme{metadata: m, is_user_defined: true, settings: conf}
|
||||
self.name_map[m.Name] = &t
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,13 +142,13 @@ func TestThemeCollections(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
defer closer.Close()
|
||||
if code, err := coll.ThemeByName("Empty").Code(); code != "empty" {
|
||||
if code, err := coll.ThemeByName("Empty").load_code(); code != "empty" {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Fatal("failed to load code for empty theme")
|
||||
}
|
||||
if code, err := coll.ThemeByName("Alabaster Dark").Code(); code != "alabaster" {
|
||||
if code, err := coll.ThemeByName("Alabaster Dark").load_code(); code != "alabaster" {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ type RGBA struct {
|
|||
Red, Green, Blue, Inverse_alpha uint8
|
||||
}
|
||||
|
||||
func (self RGBA) AsRGBSharp() string {
|
||||
return fmt.Sprintf("#%02x%02x%02x", self.Red, self.Green, self.Blue)
|
||||
}
|
||||
|
||||
func (self *RGBA) parse_rgb_strings(r string, g string, b string) bool {
|
||||
var rv, gv, bv uint64
|
||||
var err error
|
||||
|
|
@ -77,6 +81,12 @@ func (self *RGBA) AsRGB() uint32 {
|
|||
return uint32(self.Blue) | (uint32(self.Green) << 8) | (uint32(self.Red) << 16)
|
||||
}
|
||||
|
||||
func (self *RGBA) FromRGB(col uint32) {
|
||||
self.Red = uint8((col >> 16) & 0xff)
|
||||
self.Green = uint8((col >> 8) & 0xff)
|
||||
self.Blue = uint8((col) & 0xff)
|
||||
}
|
||||
|
||||
type color_type struct {
|
||||
is_numbered bool
|
||||
val RGBA
|
||||
|
|
|
|||
Loading…
Reference in a new issue