lsp improvements

This commit is contained in:
Kujtim Hoxha
2025-04-19 15:15:29 +02:00
parent bf8cd3bd12
commit 2b5a33e476
15 changed files with 922 additions and 127 deletions

View File

@@ -10,6 +10,7 @@ import (
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"time"
@@ -24,8 +25,10 @@ type GrepParams struct {
}
type grepMatch struct {
path string
modTime time.Time
path string
modTime time.Time
lineNum int
lineText string
}
type GrepResponseMetadata struct {
@@ -147,13 +150,26 @@ func (g *grepTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
if len(matches) == 0 {
output = "No files found"
} else {
output = fmt.Sprintf("Found %d file%s\n%s",
len(matches),
pluralize(len(matches)),
strings.Join(matches, "\n"))
output = fmt.Sprintf("Found %d matches\n", len(matches))
currentFile := ""
for _, match := range matches {
if currentFile != match.path {
if currentFile != "" {
output += "\n"
}
currentFile = match.path
output += fmt.Sprintf("%s:\n", match.path)
}
if match.lineNum > 0 {
output += fmt.Sprintf(" Line %d: %s\n", match.lineNum, match.lineText)
} else {
output += fmt.Sprintf(" %s\n", match.path)
}
}
if truncated {
output += "\n\n(Results are truncated. Consider using a more specific path or pattern.)"
output += "\n(Results are truncated. Consider using a more specific path or pattern.)"
}
}
@@ -166,14 +182,7 @@ func (g *grepTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
), nil
}
func pluralize(count int) string {
if count == 1 {
return ""
}
return "s"
}
func searchFiles(pattern, rootPath, include string, limit int) ([]string, bool, error) {
func searchFiles(pattern, rootPath, include string, limit int) ([]grepMatch, bool, error) {
matches, err := searchWithRipgrep(pattern, rootPath, include)
if err != nil {
matches, err = searchFilesWithRegex(pattern, rootPath, include)
@@ -191,12 +200,7 @@ func searchFiles(pattern, rootPath, include string, limit int) ([]string, bool,
matches = matches[:limit]
}
results := make([]string, len(matches))
for i, m := range matches {
results[i] = m.path
}
return results, truncated, nil
return matches, truncated, nil
}
func searchWithRipgrep(pattern, path, include string) ([]grepMatch, error) {
@@ -205,7 +209,8 @@ func searchWithRipgrep(pattern, path, include string) ([]grepMatch, error) {
return nil, fmt.Errorf("ripgrep not found: %w", err)
}
args := []string{"-l", pattern}
// Use -n to show line numbers and include the matched line
args := []string{"-n", pattern}
if include != "" {
args = append(args, "--glob", include)
}
@@ -228,14 +233,29 @@ func searchWithRipgrep(pattern, path, include string) ([]grepMatch, error) {
continue
}
fileInfo, err := os.Stat(line)
// Parse ripgrep output format: file:line:content
parts := strings.SplitN(line, ":", 3)
if len(parts) < 3 {
continue
}
filePath := parts[0]
lineNum, err := strconv.Atoi(parts[1])
if err != nil {
continue
}
lineText := parts[2]
fileInfo, err := os.Stat(filePath)
if err != nil {
continue // Skip files we can't access
}
matches = append(matches, grepMatch{
path: line,
modTime: fileInfo.ModTime(),
path: filePath,
modTime: fileInfo.ModTime(),
lineNum: lineNum,
lineText: lineText,
})
}
@@ -276,15 +296,17 @@ func searchFilesWithRegex(pattern, rootPath, include string) ([]grepMatch, error
return nil
}
match, err := fileContainsPattern(path, regex)
match, lineNum, lineText, err := fileContainsPattern(path, regex)
if err != nil {
return nil // Skip files we can't read
}
if match {
matches = append(matches, grepMatch{
path: path,
modTime: info.ModTime(),
path: path,
modTime: info.ModTime(),
lineNum: lineNum,
lineText: lineText,
})
if len(matches) >= 200 {
@@ -301,21 +323,24 @@ func searchFilesWithRegex(pattern, rootPath, include string) ([]grepMatch, error
return matches, nil
}
func fileContainsPattern(filePath string, pattern *regexp.Regexp) (bool, error) {
func fileContainsPattern(filePath string, pattern *regexp.Regexp) (bool, int, string, error) {
file, err := os.Open(filePath)
if err != nil {
return false, err
return false, 0, "", err
}
defer file.Close()
scanner := bufio.NewScanner(file)
lineNum := 0
for scanner.Scan() {
if pattern.MatchString(scanner.Text()) {
return true, nil
lineNum++
line := scanner.Text()
if pattern.MatchString(line) {
return true, lineNum, line, nil
}
}
return false, scanner.Err()
return false, 0, "", scanner.Err()
}
func globToRegex(glob string) string {