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) {
|
func Test_stringify(t *testing.T) {
|
||||||
t.Run("dict", func(t *testing.T) {
|
t.Run("dict", func(t *testing.T) {
|
||||||
arg := newDict()
|
arg := NewDict()
|
||||||
arg.set("a", number("1"))
|
arg.Set("a", Number("1"))
|
||||||
arg.set("b", number("2"))
|
arg.Set("b", Number("2"))
|
||||||
want := `{"a": 1,"b": 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.Errorf("stringify() = %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("array", func(t *testing.T) {
|
t.Run("array", func(t *testing.T) {
|
||||||
arg := array{number("1"), number("2")}
|
arg := Array{Number("1"), Number("2")}
|
||||||
want := `[1,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.Errorf("stringify() = %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("array_with_dict", func(t *testing.T) {
|
t.Run("array_with_dict", func(t *testing.T) {
|
||||||
arg := array{newDict(), array{}}
|
arg := Array{NewDict(), Array{}}
|
||||||
want := `[{},[]]`
|
want := `[{},[]]`
|
||||||
if got := stringify(arg); got != want {
|
if got := Stringify(arg); got != want {
|
||||||
t.Errorf("stringify() = %v, want %v", 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