diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e38af0..2fc0fdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Release Notes +## v0.2.0 (2025-05-30) +- ✨ Add autocompletion for loop object. Now if you type `loop.` inside of a loop, it will show available properties on the object + ## v0.1.4 (2025-05-17) - ✨ Autocomplete suggestions show code example with syntax highlighting. Before, it was just displayed as text diff --git a/analysis/completion.go b/analysis/completion.go index 6dfe903..2efa17f 100644 --- a/analysis/completion.go +++ b/analysis/completion.go @@ -4,10 +4,14 @@ import ( "regexp" "strings" + "github.com/textwire/lsp/internal/logger" "github.com/textwire/lsp/lsp" + twLsp "github.com/textwire/textwire/v2/lsp" "github.com/textwire/textwire/v2/lsp/completions" ) +const locale = "en" + func (s *State) Completion(id int, uri string, pos lsp.Position) (lsp.CompletionResponse, error) { doc, ok := s.Documents[uri] @@ -27,25 +31,59 @@ func (s *State) Completion(id int, uri string, pos lsp.Position) (lsp.Completion directiveRegex := regexp.MustCompile(`(^|[^\\])@(\w*)$`) directiveMatch := directiveRegex.FindStringSubmatch(textBeforeCursor) - if directiveMatch == nil { - return s.completionResponse(id, []lsp.CompletionItem{}), nil + var completionItems []completions.Completion + var err error + + if directiveMatch != nil { + completionItems, err = completions.GetDirectives(locale) + } else if strings.HasSuffix(textBeforeCursor, "loop.") { + doc = removeTrailingChar(doc, pos.Line, pos.Character, '.') + + isInsideLoop, errors := twLsp.IsInLoop(doc, uri, pos.Line, pos.Character) + if errors != nil && len(errors) > 0 { + logger.Error.Println(errors[0]) + return lsp.CompletionResponse{}, err + } + + if isInsideLoop { + completionItems, err = completions.GetLoopObjFields(locale) + } } - directives, err := completions.GetDirectives("en") if err != nil { + logger.Error.Println(err) return lsp.CompletionResponse{}, err } - items := make([]lsp.CompletionItem, 0, len(directives)) + return s.completionResponse(id, s.makeCompletions(completionItems)), nil +} + +func removeTrailingChar(doc string, line, col uint, char byte) string { + lines := strings.Split(doc, "\n") + if int(line) >= len(lines) { + return doc + } + + currentLine := lines[line] + if col > 0 && currentLine[col-1] == char { + currentLine = currentLine[:col-1] + currentLine[col:] + lines[line] = currentLine + } + + return strings.Join(lines, "\n") +} + +func (s *State) makeCompletions(completionItems []completions.Completion) []lsp.CompletionItem { + items := make([]lsp.CompletionItem, 0, len(completionItems)) - for _, dir := range directives { + for _, item := range completionItems { items = append(items, lsp.CompletionItem{ - Label: dir.Label, - FilterText: dir.Insert, - InsertText: dir.Insert, + Label: item.Label, + FilterText: item.Insert, + InsertText: item.Insert, Documentation: lsp.MarkupContent{ Kind: "markdown", - Value: dir.Documentation, + Value: item.Documentation, }, LabelDetails: &lsp.CompletionItemLabelDetails{ Kind: lsp.CIKSnippet, @@ -53,7 +91,7 @@ func (s *State) Completion(id int, uri string, pos lsp.Position) (lsp.Completion }) } - return s.completionResponse(id, items), nil + return items } func (s *State) completionResponse(id int, items []lsp.CompletionItem) lsp.CompletionResponse { diff --git a/go.mod b/go.mod index c07739a..23b0223 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/textwire/lsp go 1.23.3 -require github.com/textwire/textwire/v2 v2.5.6 +require github.com/textwire/textwire/v2 v2.5.9 diff --git a/go.sum b/go.sum index 01df2b8..fe6b3c9 100644 --- a/go.sum +++ b/go.sum @@ -10,3 +10,9 @@ github.com/textwire/textwire/v2 v2.5.4 h1:SXbPEUCRVC7O+9kD8BpMz81GV5zeYbyjTA6zyU github.com/textwire/textwire/v2 v2.5.4/go.mod h1:V0J75qH85DM8OAICWewhXyyXPXVAZYwhhiORGrWgj5I= github.com/textwire/textwire/v2 v2.5.6 h1:jrtI3ALSoC6u6Bf+7GI5yGSi3IHENgASG2GQTUyYgbk= github.com/textwire/textwire/v2 v2.5.6/go.mod h1:V0J75qH85DM8OAICWewhXyyXPXVAZYwhhiORGrWgj5I= +github.com/textwire/textwire/v2 v2.5.7 h1:SVq50BpQTV805MbaMY4hb70Ss9QNWOEN0eXSHb+Xf8k= +github.com/textwire/textwire/v2 v2.5.7/go.mod h1:V0J75qH85DM8OAICWewhXyyXPXVAZYwhhiORGrWgj5I= +github.com/textwire/textwire/v2 v2.5.8 h1:PMPookvEf1eRlUHuTlhoZdOFrH5yviWu5hYTqBKEK2c= +github.com/textwire/textwire/v2 v2.5.8/go.mod h1:V0J75qH85DM8OAICWewhXyyXPXVAZYwhhiORGrWgj5I= +github.com/textwire/textwire/v2 v2.5.9 h1:ZK0v/neW2H5EPv5oPf1vmrPK+0JthrQSbs98V0nZyp4= +github.com/textwire/textwire/v2 v2.5.9/go.mod h1:V0J75qH85DM8OAICWewhXyyXPXVAZYwhhiORGrWgj5I=