mirror of
https://github.com/antonmedv/fx.git
synced 2024-09-11 18:27:10 +03:00
Add better dig path word jumping
This commit is contained in:
parent
e2c42139ae
commit
a4c1e94962
27
main.go
27
main.go
@ -262,6 +262,31 @@ func (m *model) handleDigKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case key.Matches(msg, textinput.DefaultKeyMap.WordBackward):
|
||||||
|
value := m.digInput.Value()
|
||||||
|
pth, ok := jsonpath.Split(value[0:m.digInput.Position()])
|
||||||
|
if ok {
|
||||||
|
if len(pth) > 0 {
|
||||||
|
pth = pth[:len(pth)-1]
|
||||||
|
m.digInput.SetCursor(len(jsonpath.Join(pth)))
|
||||||
|
} else {
|
||||||
|
m.digInput.CursorStart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case key.Matches(msg, textinput.DefaultKeyMap.WordForward):
|
||||||
|
value := m.digInput.Value()
|
||||||
|
fullPath, ok1 := jsonpath.Split(value)
|
||||||
|
pth, ok2 := jsonpath.Split(value[0:m.digInput.Position()])
|
||||||
|
if ok1 && ok2 {
|
||||||
|
if len(pth) < len(fullPath) {
|
||||||
|
pth = append(pth, fullPath[len(pth)])
|
||||||
|
m.digInput.SetCursor(len(jsonpath.Join(pth)))
|
||||||
|
} else {
|
||||||
|
m.digInput.CursorEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if key.Matches(msg, key.NewBinding(key.WithKeys("."))) {
|
if key.Matches(msg, key.NewBinding(key.WithKeys("."))) {
|
||||||
m.digInput.SetValue(m.cursorPath())
|
m.digInput.SetValue(m.cursorPath())
|
||||||
@ -752,7 +777,7 @@ func (m *model) cursorPath() string {
|
|||||||
if at.key != nil {
|
if at.key != nil {
|
||||||
quoted := string(at.key)
|
quoted := string(at.key)
|
||||||
unquoted, err := strconv.Unquote(quoted)
|
unquoted, err := strconv.Unquote(quoted)
|
||||||
if err == nil && identifier.MatchString(unquoted) {
|
if err == nil && jsonpath.Identifier.MatchString(unquoted) {
|
||||||
path = "." + unquoted + path
|
path = "." + unquoted + path
|
||||||
} else {
|
} else {
|
||||||
path = "[" + quoted + "]" + path
|
path = "[" + quoted + "]" + path
|
||||||
|
4
node.go
4
node.go
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
jsonpath "github.com/antonmedv/fx/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
type node struct {
|
type node struct {
|
||||||
@ -177,7 +179,7 @@ func (n *node) paths(prefix string, paths *[]string, nodes *[]*node) {
|
|||||||
if it.key != nil {
|
if it.key != nil {
|
||||||
quoted := string(it.key)
|
quoted := string(it.key)
|
||||||
unquoted, err := strconv.Unquote(quoted)
|
unquoted, err := strconv.Unquote(quoted)
|
||||||
if err == nil && identifier.MatchString(unquoted) {
|
if err == nil && jsonpath.Identifier.MatchString(unquoted) {
|
||||||
path = prefix + "." + unquoted
|
path = prefix + "." + unquoted
|
||||||
} else {
|
} else {
|
||||||
path = prefix + "[" + quoted + "]"
|
path = prefix + "[" + quoted + "]"
|
||||||
|
20
path/path.go
20
path/path.go
@ -1,6 +1,7 @@
|
|||||||
package path
|
package path
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
@ -174,3 +175,22 @@ func Split(p string) ([]any, bool) {
|
|||||||
func isProp(ch rune) bool {
|
func isProp(ch rune) bool {
|
||||||
return unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_' || ch == '$'
|
return unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_' || ch == '$'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Identifier = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
|
||||||
|
|
||||||
|
func Join(path []any) string {
|
||||||
|
s := ""
|
||||||
|
for _, v := range path {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
if Identifier.MatchString(v) {
|
||||||
|
s += "." + v
|
||||||
|
} else {
|
||||||
|
s += "[" + strconv.Quote(v) + "]"
|
||||||
|
}
|
||||||
|
case int:
|
||||||
|
s += "[" + strconv.Itoa(v) + "]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
@ -135,3 +135,52 @@ func Test_SplitPath_negative(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJoin(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input []any
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: []any{},
|
||||||
|
want: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo"},
|
||||||
|
want: ".foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo", "bar"},
|
||||||
|
want: ".foo.bar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo", 42},
|
||||||
|
want: ".foo[42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo", "bar", 42},
|
||||||
|
want: ".foo.bar[42]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo", "bar", 42, "baz"},
|
||||||
|
want: ".foo.bar[42].baz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo", "bar", 42, "baz", 1},
|
||||||
|
want: ".foo.bar[42].baz[1]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo", "bar", 42, "baz", 1, "qux"},
|
||||||
|
want: ".foo.bar[42].baz[1].qux",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []any{"foo bar"},
|
||||||
|
want: "[\"foo bar\"]",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.want, func(t *testing.T) {
|
||||||
|
require.Equal(t, tt.want, path.Join(tt.input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
utils.go
3
utils.go
@ -1,12 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var identifier = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
|
|
||||||
|
|
||||||
func isHexDigit(ch byte) bool {
|
func isHexDigit(ch byte) bool {
|
||||||
return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
|
return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user