Finish port of themes kitten to Go

This commit is contained in:
Kovid Goyal
2023-03-14 20:24:21 +05:30
parent 0c20a4d980
commit 0805330b77
5 changed files with 116 additions and 53 deletions

View File

@@ -4,6 +4,7 @@ package themes
import (
"archive/zip"
"bytes"
"encoding/json"
"errors"
"fmt"
@@ -20,6 +21,7 @@ import (
"kitty/tools/cli"
"kitty/tools/config"
"kitty/tools/tty"
"kitty/tools/tui/subseq"
"kitty/tools/utils"
"kitty/tools/utils/style"
@@ -31,6 +33,7 @@ import (
)
var _ = fmt.Print
var DebugPrintln = tty.DebugPrintln
var AllColorSettingNames = map[string]bool{ // {{{
// generated by gen-config.py do not edit
@@ -325,12 +328,33 @@ type JSONMetadata struct {
var ErrNoCacheFound = errors.New("No cache found and max cache age is negative")
func set_comment_in_zip_file(path string, comment string) error {
src, err := zip.OpenReader(path)
if err != nil {
return err
}
defer src.Close()
buf := bytes.Buffer{}
dest := zip.NewWriter(&buf)
dest.SetComment(comment)
for _, sf := range src.File {
err = dest.Copy(sf)
if err != nil {
return err
}
}
dest.Close()
utils.AtomicUpdateFile(path, buf.Bytes(), 0o644)
return nil
}
func fetch_cached(name, url, cache_path string, max_cache_age time.Duration) (string, error) {
cache_path = filepath.Join(cache_path, name+".zip")
zf, err := zip.OpenReader(cache_path)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return "", err
}
defer zf.Close()
var jm JSONMetadata
if err == nil {
@@ -362,6 +386,12 @@ func fetch_cached(name, url, cache_path string, max_cache_age time.Duration) (st
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
if resp.StatusCode == http.StatusNotModified {
jm.Timestamp = utils.ISO8601Format(time.Now())
comment, _ := json.Marshal(jm)
err = set_comment_in_zip_file(cache_path, utils.UnsafeBytesToString(comment))
if err != nil {
return "", err
}
return cache_path, nil
}
return "", fmt.Errorf("Failed to download %s with HTTP error: %s", url, resp.Status)
@@ -760,14 +790,18 @@ func (self *Themes) At(x int) *Theme {
}
func (self *Themes) Names() []string { return self.index_map }
func (self *Themes) create_index_map() {
self.index_map = maps.Keys(self.name_map)
self.index_map = utils.StableSortWithKey(self.index_map, strings.ToLower)
}
func (self *Themes) Filtered(is_ok func(*Theme) bool) *Themes {
themes := utils.Filter(maps.Values(self.name_map), is_ok)
ans := Themes{name_map: make(map[string]*Theme, len(themes))}
for _, theme := range themes {
ans.name_map[theme.metadata.Name] = theme
}
ans.index_map = maps.Keys(ans.name_map)
ans.index_map = utils.StableSortWithKey(ans.index_map, strings.ToLower)
ans.create_index_map()
return &ans
}
@@ -873,23 +907,24 @@ func (self *Themes) ApplySearch(expression string, marks ...string) []string {
if len(marks) == 2 {
mark_before, mark_after = marks[0], marks[1]
}
results := match(expression, maps.Keys(self.name_map))
results := utils.Filter(match(expression, self.index_map), func(x *subseq.Match) bool { return x.Score > 0 })
name_map := make(map[string]*Theme, len(results))
for _, m := range results {
name_map[m.Text] = self.name_map[m.Text]
}
self.name_map = name_map
self.index_map = self.index_map[:0]
ans := make([]string, 0, len(results))
for _, m := range results {
k := m.Text
text := m.Text
positions := m.Positions
for i := len(positions) - 1; i >= 0; i-- {
p := positions[i]
text = text[:p] + mark_before + text[p:p+1] + mark_after + text[p+1:]
}
name_map[k] = self.name_map[k]
ans = append(ans, text)
self.index_map = append(self.index_map, m.Text)
}
self.name_map = name_map
self.index_map = maps.Keys(name_map)
self.index_map = utils.StableSortWithKey(self.index_map, strings.ToLower)
return ans
}
@@ -905,8 +940,7 @@ func LoadThemes(cache_age time.Duration) (ans *Themes, closer io.Closer, err err
if err = ans.add_from_dir(filepath.Join(utils.ConfigDir(), "themes")); err != nil {
return nil, nil, err
}
ans.index_map = maps.Keys(ans.name_map)
ans.index_map = utils.StableSortWithKey(ans.index_map, strings.ToLower)
ans.create_index_map()
return ans, closer, nil
}