Skip to content

Commit

Permalink
query suggestion for autocompletion
Browse files Browse the repository at this point in the history
  • Loading branch information
semihbkgr committed Dec 3, 2023
1 parent ce0b0e1 commit 172b00e
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 17 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ module github.com/semihbkgr/yn
go 1.21.0

require (
github.com/charmbracelet/bubbles v0.16.1
github.com/charmbracelet/bubbles v0.16.2-0.20230928142930-f53b3d9f617a
github.com/charmbracelet/bubbletea v0.24.2
github.com/charmbracelet/lipgloss v0.9.1
github.com/fatih/color v1.16.0
github.com/goccy/go-yaml v1.11.2
github.com/muesli/reflow v0.3.0
github.com/spf13/cobra v1.8.0
)

Expand All @@ -24,6 +23,7 @@ require (
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY=
github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc=
github.com/charmbracelet/bubbles v0.16.2-0.20230928142930-f53b3d9f617a h1:errlaNvz8kRKqI+DmlfVaJpA942ZuSrntU9C152Cznw=
github.com/charmbracelet/bubbles v0.16.2-0.20230928142930-f53b3d9f617a/go.mod h1:XUdibuVUiMfcfKTRla58bmY3TWsdjgF+Rp8pvimQLck=
github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06RaW2cx/SY=
github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg=
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
Expand Down
4 changes: 4 additions & 0 deletions model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type model struct {
func initModel() model {
v := viewport.New(0, 0)
i := textinput.New()
i.ShowSuggestions = true

i.TextStyle = lipgloss.NewStyle().Bold(true)

h := help.New()
Expand All @@ -60,6 +62,8 @@ func NewModel(opts Options) tea.Model {
file, _ := parser.Parse(lexer.Tokenize(opts.File.String()), parser.ParseComments)
m.file = file

m.input.SetSuggestions(yaml.Suggestions(m.file))

m.Navigate()

return m
Expand Down
31 changes: 18 additions & 13 deletions yaml/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func QueryTokens(file *ast.File, path string) QueryResult {
}
nodes = append(nodes, n)

tokens := TokensFromNode(n)
tokens := tokensFromNode(n)
for _, t := range tokens {
tokensMap[*t.Position] = t
parentNodeMap[*t.Position] = n
Expand All @@ -225,7 +225,7 @@ func QueryTokens(file *ast.File, path string) QueryResult {
}

func FindNode(n ast.Node, path string) ast.Node {
if MatchPaths(n, path) {
if matchPaths(n, path) {
return n
}

Expand Down Expand Up @@ -258,28 +258,28 @@ func FindNode(n ast.Node, path string) ast.Node {
return nil
}

func TokensFromNode(n ast.Node) token.Tokens {
func tokensFromNode(n ast.Node) token.Tokens {
var tokens token.Tokens
tokens = append(tokens, n.GetToken())

switch node := n.(type) {
case *ast.MappingNode:
for _, valueNode := range node.Values {
tokens = append(tokens, TokensFromNode(valueNode)...)
tokens = append(tokens, tokensFromNode(valueNode)...)
}
case *ast.MappingValueNode:
tokens = append(tokens, TokensFromNode(node.Key)...)
tokens = append(tokens, TokensFromNode(node.Value)...)
tokens = append(tokens, tokensFromNode(node.Key)...)
tokens = append(tokens, tokensFromNode(node.Value)...)
case *ast.SequenceNode:
for _, valueNode := range node.Values {
tokens = append(tokens, TokensFromNode(valueNode)...)
tokens = append(tokens, tokensFromNode(valueNode)...)
}
}

return tokens
}

func MatchPaths(n ast.Node, path string) bool {
func matchPaths(n ast.Node, path string) bool {
if path == "" {
return false
}
Expand All @@ -292,16 +292,21 @@ func MatchPaths(n ast.Node, path string) bool {

switch node := n.(type) {
case *ast.MappingNode:
nodePath = TrimPath(node.Path)
nodePath = trimPath(node.Path)
}

nodePath = nodePath[1:]
queryPath := nodePathToQueryPath(nodePath)
return queryPath == path
}

func nodePathToQueryPath(nodePath string) string {
if nodePath == "" {
return nodePath
}
re := regexp.MustCompile(`\[(\d+)\]`)
nodePath = re.ReplaceAllString(nodePath, ".$1")
return nodePath == path
return re.ReplaceAllString(nodePath[1:], ".$1")
}

func TrimPath(path string) string {
func trimPath(path string) string {
return path[:strings.LastIndex(path, ".")]
}
45 changes: 45 additions & 0 deletions yaml/suggestion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package yaml

import (
"sort"

"github.com/goccy/go-yaml/ast"
)

func Suggestions(f *ast.File) []string {
suggestionsMap := make(map[string]any)
for _, doc := range f.Docs {
for _, suggestion := range nodeSuggestion(doc) {
suggestionsMap[suggestion] = nil
}
}
suggestions := make([]string, 0, len(suggestionsMap))
for suggestion, _ := range suggestionsMap {

Check failure on line 17 in yaml/suggestion.go

View workflow job for this annotation

GitHub Actions / CI

S1005: unnecessary assignment to the blank identifier (gosimple)
suggestions = append(suggestions, suggestion)
}
sort.Strings(suggestions)
return suggestions
}

func nodeSuggestion(n ast.Node) []string {
suggestions := make([]string, 0)
suggestions = append(suggestions, nodePathToQueryPath(n.GetPath()))

switch node := n.(type) {
case *ast.MappingNode:
for _, valueNode := range node.Values {
suggestions = append(suggestions, nodeSuggestion(valueNode)...)
}
case *ast.MappingValueNode:
suggestions = append(suggestions, nodeSuggestion(node.Key)...)
suggestions = append(suggestions, nodeSuggestion(node.Value)...)
case *ast.SequenceNode:
for _, valueNode := range node.Values {
suggestions = append(suggestions, nodeSuggestion(valueNode)...)
}
case *ast.DocumentNode:
suggestions = append(suggestions, nodeSuggestion(node.Body)...)
}

return suggestions
}

0 comments on commit 172b00e

Please sign in to comment.