Skip to content

Commit

Permalink
somewhat working locals
Browse files Browse the repository at this point in the history
  • Loading branch information
topi314 committed Jun 18, 2024
1 parent a01466d commit 44b6f08
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 95 deletions.
1 change: 1 addition & 0 deletions config/queries/go/locals.scm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
name: (identifier) @local.definition))

(parameter_declaration (identifier) @local.definition)

(variadic_parameter_declaration (identifier) @local.definition)

(short_var_declaration
Expand Down
2 changes: 1 addition & 1 deletion gopad/editor/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ func (f *File) View(width int, height int, border bool, debug bool) string {
slices.Reverse(matches)
var currentMatches []string
for _, match := range matches {
currentMatches = append(currentMatches, fmt.Sprintf("%s (%s: [%d, %d] - [%d, %d]) ", match.Type, match.Source, match.Range.Start.Row, match.Range.Start.Col, match.Range.End.Row, match.Range.End.Col))
currentMatches = append(currentMatches, fmt.Sprintf("%s (%s) (%s: [%d, %d] - [%d, %d]) ", match.Type, match.ReferenceType, match.Source, match.Range.Start.Row, match.Range.Start.Col, match.Range.End.Row, match.Range.End.Col))
}
editorCode += "\n" + borderStyle(fmt.Sprintf(" Current Matches: %s", strings.Join(currentMatches, ", ")))

Expand Down
216 changes: 201 additions & 15 deletions gopad/editor/syntax_highlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package editor

import (
"fmt"
"log"
"strconv"
"strings"

"github.com/charmbracelet/lipgloss"
sitter "go.gopad.dev/go-tree-sitter"

"go.gopad.dev/gopad/gopad/buffer"
"go.gopad.dev/gopad/gopad/config"
Expand Down Expand Up @@ -40,30 +43,213 @@ func (f *File) MatchesForLineCol(row int, col int) []Match {

func (f *File) HighestMatchStyle(style lipgloss.Style, row int, col int) lipgloss.Style {
var currentStyle *lipgloss.Style
var referenceStyle *lipgloss.Style
for _, match := range f.MatchesForLineCol(row, col) {
matchType := match.Type
if match.ReferenceType != "" {
newStyle := getMatchingStyle(match.ReferenceType, f.language.Name)
if newStyle != nil {
referenceStyle = newStyle
}
continue
}

newStyle := getMatchingStyle(match.Type, f.language.Name)
if newStyle != nil {
currentStyle = newStyle
}
}

if currentStyle == nil && referenceStyle == nil {
return style
}

if referenceStyle != nil {
return style.Copy().Inherit(*referenceStyle)
}

return style.Copy().Inherit(*currentStyle)
}

func getMatchingStyle(matchType string, name string) *lipgloss.Style {
var currentStyle *lipgloss.Style

for {
codeStyle, ok := config.Theme.Editor.CodeStyles[fmt.Sprintf("%s.%s", matchType, name)]
if ok {
currentStyle = &codeStyle
break
}
codeStyle, ok = config.Theme.Editor.CodeStyles[matchType]
if ok {
currentStyle = &codeStyle
break
}
lastDot := strings.LastIndex(matchType, ".")
if lastDot == -1 {
break
}
matchType = matchType[:lastDot]
}

return currentStyle
}

type Match struct {
Range buffer.Range
Type string
ReferenceType string
Priority int
Source string
}

type LocalDef struct {
Name string
Type string
}

type LocalScope struct {
Inherits bool
Range buffer.Range
LocalDefs []*LocalDef
}

func (f *File) HighlightTree() {
if f.tree == nil || f.tree.Tree == nil || f.tree.Language.Grammar == nil {
return
}
version := f.Version()

matches := highlightTree(f.tree.Copy())
// slices.SortFunc(matches, func(a, b Match) int {
// return b.Priority - a.Priority
// })

f.SetMatches(version, matches)
}

func highlightTree(tree *Tree) []Match {
query := tree.Language.Grammar.HighlightsQuery
queryCursor := sitter.NewQueryCursor()
queryCursor.Exec(query.Query, tree.Tree.RootNode())

var matches []Match
var scopes []*LocalScope
var localRef *LocalDef
var localDef *LocalDef
var lastMatch *sitter.QueryMatch
for {
match, index, ok := queryCursor.NextCapture()
if !ok {
break
}
capture := match.Captures[index]

log.Println("Capture:", match.ID, capture.Index, query.Query.CaptureNameForID(capture.Index))

captureRange := buffer.Range{
Start: buffer.Position{
Row: int(capture.StartPoint().Row),
Col: int(capture.StartPoint().Column),
},
End: buffer.Position{
Row: int(capture.EndPoint().Row),
Col: int(capture.EndPoint().Column),
},
}

for {
codeStyle, ok := config.Theme.Editor.CodeStyles[fmt.Sprintf("%s.%s", matchType, f.language.Config.Grammar.Name)]
if ok {
currentStyle = &codeStyle
if len(scopes) == 0 {
break
}
codeStyle, ok = config.Theme.Editor.CodeStyles[matchType]
if ok {
currentStyle = &codeStyle
break
lastScope := scopes[len(scopes)-1]
if captureRange.Start.GreaterThan(lastScope.Range.End) {
scopes = scopes[:len(scopes)-1]
continue
}
lastDot := strings.LastIndex(matchType, ".")
if lastDot == -1 {
break

break
}

if uint32(match.PatternIndex) < query.HighlightsPatternIndex {
if query.ScopeCaptureID != nil && capture.Index == *query.ScopeCaptureID {
log.Println("New scope")
scopes = append(scopes, &LocalScope{
Inherits: true,
Range: captureRange,
LocalDefs: nil,
})
} else if query.DefinitionCaptureID != nil && capture.Index == *query.DefinitionCaptureID {
log.Println("Definition:", capture.Node.Content())
if len(scopes) > 0 {
def := &LocalDef{
Name: capture.Node.Content(),
Type: "",
}

localDef = def

scope := scopes[len(scopes)-1]
scope.LocalDefs = append(scope.LocalDefs, def)
}

} else if query.ReferenceCaptureID != nil && capture.Index == *query.ReferenceCaptureID {
log.Println("Reference:", capture.Node.Content())
for i := len(scopes) - 1; i >= 0; i-- {
for _, def := range scopes[i].LocalDefs {
if def.Name == capture.Node.Content() {
log.Println("Found Definition for Reference:", def)
localRef = def
break
}
}
if !scopes[i].Inherits {
break
}
}
}
lastMatch = match
continue
}

priority := 100
if priorityStr, ok := match.Properties["priority"]; ok {
if parsedPriority, err := strconv.Atoi(priorityStr); err == nil {
priority = parsedPriority
}
matchType = matchType[:lastDot]
}

if localDef != nil {
log.Println("Adding definition type:", query.Query.CaptureNameForID(capture.Index))
localDef.Type = query.Query.CaptureNameForID(capture.Index)
}

highlightMatch := Match{
Range: buffer.Range{
Start: buffer.Position{Row: int(capture.StartPoint().Row), Col: int(capture.StartPoint().Column)},
End: buffer.Position{Row: int(capture.EndPoint().Row), Col: max(0, int(capture.EndPoint().Column)-1)}, // -1 to exclude the last character idk why this is like this tbh
},
Type: query.Query.CaptureNameForID(capture.Index),
Priority: priority,
Source: tree.Language.Name,
}

if localRef != nil {
log.Println("Adding reference type:", *localRef)
highlightMatch.ReferenceType = localRef.Type
}

matches = append(matches, highlightMatch)
if lastMatch != nil && lastMatch.ID != match.ID {
localRef = nil
localDef = nil
}
lastMatch = match
}

if currentStyle == nil {
return style
for _, subTree := range tree.SubTrees {
subMatches := highlightTree(subTree)
matches = append(matches, subMatches...)
}

return style.Copy().Inherit(*currentStyle)
return matches
}
79 changes: 0 additions & 79 deletions gopad/editor/tree_sitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package editor
import (
"context"
"fmt"
"log"
"slices"
"strconv"
"strings"
"sync"
"time"
Expand All @@ -16,15 +14,11 @@ import (
"go.gopad.dev/gopad/gopad/ls"
)

type Scope struct {
}

type Tree struct {
Tree *sitter.Tree
Language *Language
SubTrees map[string]*Tree
Ranges []sitter.Range
Scopes []Scope
}

func (t *Tree) Copy() *Tree {
Expand Down Expand Up @@ -287,79 +281,6 @@ func validateTree(tree *Tree) []ls.Diagnostic {
return diagnostics
}

type Match struct {
Range buffer.Range
Type string
Priority int
Source string
}

func (f *File) HighlightTree() {
if f.tree == nil || f.tree.Tree == nil || f.tree.Language.Grammar == nil {
return
}
version := f.Version()

matches := highlightTree(f.tree.Copy())
// slices.SortFunc(matches, func(a, b Match) int {
// return b.Priority - a.Priority
// })

f.SetMatches(version, matches)
}

func highlightTree(tree *Tree) []Match {
query := tree.Language.Grammar.HighlightsQuery
queryCursor := sitter.NewQueryCursor()
queryCursor.Exec(query.Query, tree.Tree.RootNode())

var matches []Match
for {
match, index, ok := queryCursor.NextCapture()
if !ok {
break
}
capture := match.Captures[index]

log.Println("Capture: ", capture.Index, " ", match.PatternIndex, " ", query.Query.CaptureNameForID(capture.Index), query.HighlightsPatternIndex)

if uint32(match.PatternIndex) < query.HighlightsPatternIndex {
if query.ScopeCaptureID != nil && capture.Index == *query.ScopeCaptureID {
log.Println("ScopeCaptureID")
} else if query.DefinitionCaptureID != nil && capture.Index == *query.DefinitionCaptureID {
log.Println("DefinitionCaptureID")
} else if query.ReferenceCaptureID != nil && capture.Index == *query.ReferenceCaptureID {
log.Println("ReferenceCaptureID")
}
continue
}

priority := 100
if priorityStr, ok := match.Properties["priority"]; ok {
if parsedPriority, err := strconv.Atoi(priorityStr); err == nil {
priority = parsedPriority
}
}

matches = append(matches, Match{
Range: buffer.Range{
Start: buffer.Position{Row: int(capture.StartPoint().Row), Col: int(capture.StartPoint().Column)},
End: buffer.Position{Row: int(capture.EndPoint().Row), Col: max(0, int(capture.EndPoint().Column)-1)}, // -1 to exclude the last character idk why this is like this tbh
},
Type: query.Query.CaptureNameForID(capture.Index),
Priority: priority,
Source: tree.Language.Name,
})
}

for _, subTree := range tree.SubTrees {
subMatches := highlightTree(subTree)
matches = append(matches, subMatches...)
}

return matches
}

type OutlineItem struct {
Range buffer.Range
Text []OutlineItemChar
Expand Down

0 comments on commit 44b6f08

Please sign in to comment.