forked from Archives/fx
Move part of the code to pkg
parent
aa0964a12e
commit
bf166fafda
@ -1,26 +0,0 @@
|
||||
package main
|
||||
|
||||
type dict struct {
|
||||
keys []string
|
||||
values map[string]interface{}
|
||||
}
|
||||
|
||||
func newDict() *dict {
|
||||
return &dict{
|
||||
keys: make([]string, 0),
|
||||
values: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dict) get(key string) (interface{}, bool) {
|
||||
val, exists := d.values[key]
|
||||
return val, exists
|
||||
}
|
||||
|
||||
func (d *dict) set(key string, value interface{}) {
|
||||
_, exists := d.values[key]
|
||||
if !exists {
|
||||
d.keys = append(d.keys, key)
|
||||
}
|
||||
d.values[key] = value
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parse(t *testing.T) {
|
||||
input := `{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"a": 3,
|
||||
"slice": [{"z": "z", "1": "1"}]
|
||||
}`
|
||||
|
||||
p, err := parse(json.NewDecoder(strings.NewReader(input)))
|
||||
if err != nil {
|
||||
t.Error("JSON parse error", err)
|
||||
}
|
||||
o := p.(*dict)
|
||||
|
||||
expectedKeys := []string{
|
||||
"a",
|
||||
"b",
|
||||
"slice",
|
||||
}
|
||||
for i := range o.keys {
|
||||
if o.keys[i] != expectedKeys[i] {
|
||||
t.Error("Wrong key order ", i, o.keys[i], "!=", expectedKeys[i])
|
||||
}
|
||||
}
|
||||
|
||||
s, ok := o.get("slice")
|
||||
if !ok {
|
||||
t.Error("slice missing")
|
||||
}
|
||||
a := s.(array)
|
||||
z := a[0].(*dict)
|
||||
|
||||
expectedKeys = []string{
|
||||
"z",
|
||||
"1",
|
||||
}
|
||||
for i := range z.keys {
|
||||
if z.keys[i] != expectedKeys[i] {
|
||||
t.Error("Wrong key order for nested map ", i, z.keys[i], "!=", expectedKeys[i])
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package dict
|
||||
|
||||
type Dict struct {
|
||||
Keys []string
|
||||
Values map[string]interface{}
|
||||
}
|
||||
|
||||
func NewDict() *Dict {
|
||||
return &Dict{
|
||||
Keys: make([]string, 0),
|
||||
Values: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dict) Get(key string) (interface{}, bool) {
|
||||
val, exists := d.Values[key]
|
||||
return val, exists
|
||||
}
|
||||
|
||||
func (d *Dict) Set(key string, value interface{}) {
|
||||
_, exists := d.Values[key]
|
||||
if !exists {
|
||||
d.Keys = append(d.Keys, key)
|
||||
}
|
||||
d.Values[key] = value
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
. "github.com/antonmedv/fx/pkg/dict"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parse(t *testing.T) {
|
||||
input := `{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"a": 3,
|
||||
"slice": [{"z": "z", "1": "1"}]
|
||||
}`
|
||||
|
||||
p, err := Parse(json.NewDecoder(strings.NewReader(input)))
|
||||
if err != nil {
|
||||
t.Error("JSON parse error", err)
|
||||
}
|
||||
o := p.(*Dict)
|
||||
|
||||
expectedKeys := []string{
|
||||
"a",
|
||||
"b",
|
||||
"slice",
|
||||
}
|
||||
for i := range o.Keys {
|
||||
if o.Keys[i] != expectedKeys[i] {
|
||||
t.Error("Wrong key order ", i, o.Keys[i], "!=", expectedKeys[i])
|
||||
}
|
||||
}
|
||||
|
||||
s, ok := o.Get("slice")
|
||||
if !ok {
|
||||
t.Error("slice missing")
|
||||
}
|
||||
a := s.(Array)
|
||||
z := a[0].(*Dict)
|
||||
|
||||
expectedKeys = []string{
|
||||
"z",
|
||||
"1",
|
||||
}
|
||||
for i := range z.Keys {
|
||||
if z.Keys[i] != expectedKeys[i] {
|
||||
t.Error("Wrong key order for nested map ", i, z.Keys[i], "!=", expectedKeys[i])
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/antonmedv/fx/pkg/dict"
|
||||
"github.com/antonmedv/fx/pkg/theme"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func PrettyPrint(v interface{}, level int, theme theme.Theme) string {
|
||||
ident := strings.Repeat(" ", level)
|
||||
subident := strings.Repeat(" ", level-1)
|
||||
switch v.(type) {
|
||||
case nil:
|
||||
return theme.Null("null")
|
||||
|
||||
case bool:
|
||||
if v.(bool) {
|
||||
return theme.Boolean("true")
|
||||
} else {
|
||||
return theme.Boolean("false")
|
||||
}
|
||||
|
||||
case json.Number:
|
||||
return theme.Number(v.(json.Number).String())
|
||||
|
||||
case string:
|
||||
return theme.String(fmt.Sprintf("%q", v))
|
||||
|
||||
case *dict.Dict:
|
||||
keys := v.(*dict.Dict).Keys
|
||||
if len(keys) == 0 {
|
||||
return theme.Syntax("{}")
|
||||
}
|
||||
output := theme.Syntax("{")
|
||||
output += "\n"
|
||||
for i, k := range keys {
|
||||
key := theme.Key(i, len(keys))(fmt.Sprintf("%q", k))
|
||||
value, _ := v.(*dict.Dict).Get(k)
|
||||
delim := theme.Syntax(": ")
|
||||
line := ident + key + delim + PrettyPrint(value, level+1, theme)
|
||||
if i < len(keys)-1 {
|
||||
line += theme.Syntax(",")
|
||||
}
|
||||
line += "\n"
|
||||
output += line
|
||||
}
|
||||
return output + subident + theme.Syntax("}")
|
||||
|
||||
case []interface{}:
|
||||
slice := v.([]interface{})
|
||||
if len(slice) == 0 {
|
||||
return theme.Syntax("[]")
|
||||
}
|
||||
output := theme.Syntax("[\n")
|
||||
for i, value := range v.([]interface{}) {
|
||||
line := ident + PrettyPrint(value, level+1, theme)
|
||||
if i < len(slice)-1 {
|
||||
line += ",\n"
|
||||
} else {
|
||||
line += "\n"
|
||||
}
|
||||
output += line
|
||||
}
|
||||
return output + subident + theme.Syntax("]")
|
||||
|
||||
default:
|
||||
return "unknown type"
|
||||
}
|
||||
}
|
@ -1,28 +1,31 @@
|
||||
package main
|
||||
package json
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
. "github.com/antonmedv/fx/pkg/dict"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_stringify(t *testing.T) {
|
||||
t.Run("dict", func(t *testing.T) {
|
||||
arg := newDict()
|
||||
arg.set("a", number("1"))
|
||||
arg.set("b", number("2"))
|
||||
arg := NewDict()
|
||||
arg.Set("a", Number("1"))
|
||||
arg.Set("b", Number("2"))
|
||||
want := `{"a": 1,"b": 2}`
|
||||
if got := stringify(arg); got != want {
|
||||
if got := Stringify(arg); got != want {
|
||||
t.Errorf("stringify() = %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("array", func(t *testing.T) {
|
||||
arg := array{number("1"), number("2")}
|
||||
arg := Array{Number("1"), Number("2")}
|
||||
want := `[1,2]`
|
||||
if got := stringify(arg); got != want {
|
||||
if got := Stringify(arg); got != want {
|
||||
t.Errorf("stringify() = %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("array_with_dict", func(t *testing.T) {
|
||||
arg := array{newDict(), array{}}
|
||||
arg := Array{NewDict(), Array{}}
|
||||
want := `[{},[]]`
|
||||
if got := stringify(arg); got != want {
|
||||
if got := Stringify(arg); got != want {
|
||||
t.Errorf("stringify() = %v, want %v", got, want)
|
||||
}
|
||||
})
|
@ -0,0 +1,47 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "github.com/antonmedv/fx/pkg/dict"
|
||||
)
|
||||
|
||||
type Iterator struct {
|
||||
Object interface{}
|
||||
Path, Parent string
|
||||
}
|
||||
|
||||
func Dfs(object interface{}, f func(it Iterator)) {
|
||||
sub(Iterator{Object: object}, f)
|
||||
}
|
||||
|
||||
func sub(it Iterator, f func(it Iterator)) {
|
||||
f(it)
|
||||
switch it.Object.(type) {
|
||||
case *Dict:
|
||||
keys := it.Object.(*Dict).Keys
|
||||
for _, k := range keys {
|
||||
subpath := it.Path + "." + k
|
||||
value, _ := it.Object.(*Dict).Get(k)
|
||||
sub(Iterator{
|
||||
Object: value,
|
||||
Path: subpath,
|
||||
Parent: it.Path,
|
||||
}, f)
|
||||
}
|
||||
|
||||
case Array:
|
||||
slice := it.Object.(Array)
|
||||
for i, value := range slice {
|
||||
subpath := accessor(it.Path, i)
|
||||
sub(Iterator{
|
||||
Object: value,
|
||||
Path: subpath,
|
||||
Parent: it.Path,
|
||||
}, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func accessor(path string, to interface{}) string {
|
||||
return fmt.Sprintf("%v[%v]", path, to)
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package json
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Number = json.Number
|
||||
type Array = []interface{}
|
@ -0,0 +1,185 @@
|
||||
package theme
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/mazznoer/colorgrad"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Theme struct {
|
||||
Cursor Color
|
||||
Syntax Color
|
||||
Preview Color
|
||||
StatusBar Color
|
||||
Search Color
|
||||
Key func(i, len int) Color
|
||||
String Color
|
||||
Null Color
|
||||
Boolean Color
|
||||
Number Color
|
||||
}
|
||||
type Color func(s string) string
|
||||
|
||||
var (
|
||||
defaultCursor = lipgloss.NewStyle().Reverse(true).Render
|
||||
defaultPreview = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("8")).Render
|
||||
defaultStatusBar = lipgloss.NewStyle().Background(lipgloss.Color("7")).Foreground(lipgloss.Color("0")).Render
|
||||
defaultSearch = lipgloss.NewStyle().Background(lipgloss.Color("11")).Foreground(lipgloss.Color("16")).Render
|
||||
defaultNull = fg("8")
|
||||
)
|
||||
|
||||
var Themes = map[string]Theme{
|
||||
"0": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: noColor,
|
||||
StatusBar: noColor,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return noColor },
|
||||
String: noColor,
|
||||
Null: noColor,
|
||||
Boolean: noColor,
|
||||
Number: noColor,
|
||||
},
|
||||
"1": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return boldFg("4") },
|
||||
String: boldFg("2"),
|
||||
Null: defaultNull,
|
||||
Boolean: boldFg("3"),
|
||||
Number: boldFg("6"),
|
||||
},
|
||||
"2": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return fg("#00F5D4") },
|
||||
String: fg("#00BBF9"),
|
||||
Null: defaultNull,
|
||||
Boolean: fg("#F15BB5"),
|
||||
Number: fg("#9B5DE5"),
|
||||
},
|
||||
"3": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return fg("#faf0ca") },
|
||||
String: fg("#f4d35e"),
|
||||
Null: defaultNull,
|
||||
Boolean: fg("#ee964b"),
|
||||
Number: fg("#ee964b"),
|
||||
},
|
||||
"4": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return fg("#4D96FF") },
|
||||
String: fg("#6BCB77"),
|
||||
Null: defaultNull,
|
||||
Boolean: fg("#FF6B6B"),
|
||||
Number: fg("#FFD93D"),
|
||||
},
|
||||
"5": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return boldFg("42") },
|
||||
String: boldFg("213"),
|
||||
Null: defaultNull,
|
||||
Boolean: boldFg("201"),
|
||||
Number: boldFg("201"),
|
||||
},
|
||||
"6": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return gradient("rgb(125,110,221)", "rgb(90%,45%,97%)", "hsl(229,79%,85%)") },
|
||||
String: fg("195"),
|
||||
Null: defaultNull,
|
||||
Boolean: fg("195"),
|
||||
Number: fg("195"),
|
||||
},
|
||||
"7": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: func(_, _ int) Color { return gradient("rgb(123,216,96)", "rgb(255,255,255)") },
|
||||
String: noColor,
|
||||
Null: defaultNull,
|
||||
Boolean: noColor,
|
||||
Number: noColor,
|
||||
},
|
||||
"8": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: gradientKeys("#ff0000", "#ff8700", "#ffd300", "#deff0a", "#a1ff0a", "#0aff99", "#0aefff", "#147df5", "#580aff", "#be0aff"),
|
||||
String: noColor,
|
||||
Null: defaultNull,
|
||||
Boolean: noColor,
|
||||
Number: noColor,
|
||||
},
|
||||
"9": {
|
||||
Cursor: defaultCursor,
|
||||
Syntax: noColor,
|
||||
Preview: defaultPreview,
|
||||
StatusBar: defaultStatusBar,
|
||||
Search: defaultSearch,
|
||||
Key: gradientKeys("rgb(34,126,34)", "rgb(168,251,60)"),
|
||||
String: gradient("rgb(34,126,34)", "rgb(168,251,60)"),
|
||||
Null: defaultNull,
|
||||
Boolean: noColor,
|
||||
Number: noColor,
|
||||
},
|
||||
}
|
||||
|
||||
func noColor(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func fg(color string) Color {
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color(color)).Render
|
||||
}
|
||||
|
||||
func boldFg(color string) Color {
|
||||
return lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(color)).Render
|
||||
}
|
||||
|
||||
func gradient(colors ...string) Color {
|
||||
grad, _ := colorgrad.NewGradient().HtmlColors(colors...).Build()
|
||||
return func(s string) string {
|
||||
runes := []rune(s)
|
||||
colors := grad.ColorfulColors(uint(len(runes)))
|
||||
var out strings.Builder
|
||||
for i, r := range runes {
|
||||
style := lipgloss.NewStyle().Foreground(lipgloss.Color(colors[i].Hex()))
|
||||
out.WriteString(style.Render(string(r)))
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func gradientKeys(colors ...string) func(i, len int) Color {
|
||||
grad, _ := colorgrad.NewGradient().HtmlColors(colors...).Build()
|
||||
return func(i, len int) Color {
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color(grad.At(float64(i) / float64(len)).Hex())).Render
|
||||
}
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/mazznoer/colorgrad"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Theme struct {
|
||||
cursor Color
|
||||
syntax Color
|
||||
preview Color
|
||||
statusBar Color
|
||||
search Color
|
||||
key func(i, len int) Color
|
||||
string Color
|
||||
null Color
|
||||
boolean Color
|
||||
number Color
|
||||
}
|
||||
type Color func(s string) string
|
||||
|
||||
func fg(color string) Color {
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color(color)).Render
|
||||
}
|
||||
|
||||
func boldFg(color string) Color {
|
||||
return lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(color)).Render
|
||||
}
|
||||
|
||||
var (
|
||||
defaultCursor = lipgloss.NewStyle().Reverse(true).Render
|
||||
defaultPreview = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("8")).Render
|
||||
defaultStatusBar = lipgloss.NewStyle().Background(lipgloss.Color("7")).Foreground(lipgloss.Color("0")).Render
|
||||
defaultSearch = lipgloss.NewStyle().Background(lipgloss.Color("11")).Foreground(lipgloss.Color("16")).Render
|
||||
defaultNull = fg("8")
|
||||
)
|
||||
|
||||
var themes = map[string]Theme{
|
||||
"0": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: noColor,
|
||||
statusBar: noColor,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return noColor },
|
||||
string: noColor,
|
||||
null: noColor,
|
||||
boolean: noColor,
|
||||
number: noColor,
|
||||
},
|
||||
"1": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return boldFg("4") },
|
||||
string: boldFg("2"),
|
||||
null: defaultNull,
|
||||
boolean: boldFg("3"),
|
||||
number: boldFg("6"),
|
||||
},
|
||||
"2": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return fg("#00F5D4") },
|
||||
string: fg("#00BBF9"),
|
||||
null: defaultNull,
|
||||
boolean: fg("#F15BB5"),
|
||||
number: fg("#9B5DE5"),
|
||||
},
|
||||
"3": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return fg("#faf0ca") },
|
||||
string: fg("#f4d35e"),
|
||||
null: defaultNull,
|
||||
boolean: fg("#ee964b"),
|
||||
number: fg("#ee964b"),
|
||||
},
|
||||
"4": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return fg("#4D96FF") },
|
||||
string: fg("#6BCB77"),
|
||||
null: defaultNull,
|
||||
boolean: fg("#FF6B6B"),
|
||||
number: fg("#FFD93D"),
|
||||
},
|
||||
"5": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return boldFg("42") },
|
||||
string: boldFg("213"),
|
||||
null: defaultNull,
|
||||
boolean: boldFg("201"),
|
||||
number: boldFg("201"),
|
||||
},
|
||||
"6": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return gradient("rgb(125,110,221)", "rgb(90%,45%,97%)", "hsl(229,79%,85%)") },
|
||||
string: fg("195"),
|
||||
null: defaultNull,
|
||||
boolean: fg("195"),
|
||||
number: fg("195"),
|
||||
},
|
||||
"7": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: func(_, _ int) Color { return gradient("rgb(123,216,96)", "rgb(255,255,255)") },
|
||||
string: noColor,
|
||||
null: defaultNull,
|
||||
boolean: noColor,
|
||||
number: noColor,
|
||||
},
|
||||
"8": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: gradientKeys("#ff0000", "#ff8700", "#ffd300", "#deff0a", "#a1ff0a", "#0aff99", "#0aefff", "#147df5", "#580aff", "#be0aff"),
|
||||
string: noColor,
|
||||
null: defaultNull,
|
||||
boolean: noColor,
|
||||
number: noColor,
|
||||
},
|
||||
"9": {
|
||||
cursor: defaultCursor,
|
||||
syntax: noColor,
|
||||
preview: defaultPreview,
|
||||
statusBar: defaultStatusBar,
|
||||
search: defaultSearch,
|
||||
key: gradientKeys("rgb(34,126,34)", "rgb(168,251,60)"),
|
||||
string: gradient("rgb(34,126,34)", "rgb(168,251,60)"),
|
||||
null: defaultNull,
|
||||
boolean: noColor,
|
||||
number: noColor,
|
||||
},
|
||||
}
|
||||
|
||||
func noColor(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func gradient(colors ...string) Color {
|
||||
grad, _ := colorgrad.NewGradient().HtmlColors(colors...).Build()
|
||||
return func(s string) string {
|
||||
runes := []rune(s)
|
||||
colors := grad.ColorfulColors(uint(len(runes)))
|
||||
var out strings.Builder
|
||||
for i, r := range runes {
|
||||
style := lipgloss.NewStyle().Foreground(lipgloss.Color(colors[i].Hex()))
|
||||
out.WriteString(style.Render(string(r)))
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func gradientKeys(colors ...string) func(i, len int) Color {
|
||||
grad, _ := colorgrad.NewGradient().HtmlColors(colors...).Build()
|
||||
return func(i, len int) Color {
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color(grad.At(float64(i) / float64(len)).Hex())).Render
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package main
|
||||
|
||||
type iterator struct {
|
||||
object interface{}
|
||||
path, parent string
|
||||
}
|
||||
|
||||
func dfs(object interface{}, f func(it iterator)) {
|
||||
sub(iterator{object: object}, f)
|
||||
}
|
||||
|
||||
func sub(it iterator, f func(it iterator)) {
|
||||
f(it)
|
||||
switch it.object.(type) {
|
||||
case *dict:
|
||||
keys := it.object.(*dict).keys
|
||||
for _, k := range keys {
|
||||
subpath := it.path + "." + k
|
||||
value, _ := it.object.(*dict).get(k)
|
||||
sub(iterator{
|
||||
object: value,
|
||||
path: subpath,
|
||||
parent: it.path,
|
||||
}, f)
|
||||
}
|
||||
|
||||
case array:
|
||||
slice := it.object.(array)
|
||||
for i, value := range slice {
|
||||
subpath := accessor(it.path, i)
|
||||
sub(iterator{
|
||||
object: value,
|
||||
path: subpath,
|
||||
parent: it.path,
|
||||
}, f)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue