tools: remove old individual cmd/ binaries
All tool logic lives in the multicall main.go at each family root. Move .meta files to data/tools/ (single canonical location). Expand test-core to cover all tools.
This commit is contained in:
parent
27ba54a163
commit
a73ef13fb5
3
Makefile
3
Makefile
|
|
@ -50,7 +50,6 @@ tools:
|
||||||
ln -sf lsptools $$name; \
|
ln -sf lsptools $$name; \
|
||||||
done
|
done
|
||||||
install -m644 data/tools/*.meta $(CONFIG_DIR)/tools/
|
install -m644 data/tools/*.meta $(CONFIG_DIR)/tools/
|
||||||
find tools -name '*.meta' -exec install -m644 {} $(CONFIG_DIR)/tools/ \;
|
|
||||||
for f in data/tools/*; do [ -f "$$f" ] && [ -x "$$f" ] && install -m755 "$$f" $(CONFIG_DIR)/tools/; done; true
|
for f in data/tools/*; do [ -f "$$f" ] && [ -x "$$f" ] && install -m755 "$$f" $(CONFIG_DIR)/tools/; done; true
|
||||||
cp -a data/tools/_lib $(CONFIG_DIR)/tools/
|
cp -a data/tools/_lib $(CONFIG_DIR)/tools/
|
||||||
|
|
||||||
|
|
@ -110,7 +109,7 @@ install-data:
|
||||||
test: test-core test-9p
|
test: test-core test-9p
|
||||||
|
|
||||||
test-core:
|
test-core:
|
||||||
go test ./cmd/olliesrv/... ./cmd/toolsrv/... ./log/... ./toolsrv/... ./util/... ./tools/codeintel/...
|
go test ./cmd/olliesrv/... ./cmd/toolsrv/... ./log/... ./toolsrv/... ./util/... ./tools/...
|
||||||
|
|
||||||
test-9p:
|
test-9p:
|
||||||
go test ./cmd/ollie-9p/... ./kde/lib9p/...
|
go test ./cmd/ollie-9p/... ./kde/lib9p/...
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/codeintel/internal/codeintel"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var a struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Language string `json:"language"`
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&a); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
p, err := filepath.Abs(a.Path)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
ds, err := codeintel.Dependencies(p, a.Language)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
for _, d := range ds {
|
|
||||||
fmt.Println(d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func fail(e error) { fmt.Fprintln(os.Stderr, "error:", e); os.Exit(1) }
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"ollie/tools/codeintel/internal/codeintel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type arguments struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Language string `json:"language"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var a arguments
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&a); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
p, err := filepath.Abs(a.Path)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
d, err := codeintel.Parse(p, a.Language)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
defer d.Close()
|
|
||||||
for _, s := range codeintel.Symbols(d) {
|
|
||||||
fmt.Printf("%s:%d: %s [%s]\n", s.Path, s.Line, s.Name, s.Kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func fail(e error) { fmt.Fprintln(os.Stderr, "error:", e); os.Exit(1) }
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/codeintel/internal/codeintel"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
type arguments struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Language string `json:"language"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
}
|
|
||||||
var a arguments
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&a); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
p, err := filepath.Abs(a.Path)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
cs, err := codeintel.Query(p, a.Language, a.Query)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
for _, c := range cs {
|
|
||||||
fmt.Printf("%s:%d: %s = %s\n", c.Name, c.Line, c.Name, c.Text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func fail(e error) { fmt.Fprintln(os.Stderr, "error:", e); os.Exit(1) }
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/codeintel/internal/codeintel"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
type arguments struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Language string `json:"language"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
Replacement string `json:"replacement"`
|
|
||||||
DryRun bool `json:"dry_run"`
|
|
||||||
}
|
|
||||||
var a arguments
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&a); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
p, err := filepath.Abs(a.Path)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
out, err := codeintel.ReplaceMatches(p, a.Language, a.Query, a.Replacement)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
if a.DryRun {
|
|
||||||
fmt.Print(string(out))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := os.WriteFile(p, out, 0644); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func fail(e error) { fmt.Fprintln(os.Stderr, "error:", e); os.Exit(1) }
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/codeintel/internal/codeintel"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var a struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&a); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
root, err := filepath.Abs(a.Path)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
ss, err := codeintel.MatchSymbols(root, a.Query)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
for _, s := range ss {
|
|
||||||
fmt.Printf("%s:%d: %s [%s]\n", s.Path, s.Line, s.Name, s.Kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func fail(e error) { fmt.Fprintln(os.Stderr, "error:", e); os.Exit(1) }
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"ollie/tools/codeintel/internal/codeintel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var a args
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&a); err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
root, err := filepath.Abs(a.Path)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
files, err := codeintel.Files(root)
|
|
||||||
if err != nil {
|
|
||||||
fail(err)
|
|
||||||
}
|
|
||||||
start := a.Offset
|
|
||||||
if start < 0 {
|
|
||||||
fail(fmt.Errorf("offset must be non-negative"))
|
|
||||||
}
|
|
||||||
if a.Limit < 0 {
|
|
||||||
fail(fmt.Errorf("limit must be non-negative"))
|
|
||||||
}
|
|
||||||
if start >= len(files) {
|
|
||||||
start = len(files)
|
|
||||||
}
|
|
||||||
end := len(files)
|
|
||||||
if a.Limit > 0 && start+a.Limit < end {
|
|
||||||
end = start + a.Limit
|
|
||||||
}
|
|
||||||
fmt.Printf("# Codebase Overview\n\nPath: `%s`\n\n", root)
|
|
||||||
if len(files) > 0 && (start > 0 || end < len(files)) {
|
|
||||||
fmt.Printf("Files %d-%d of %d. Next offset: %d\n\n", start+1, end, len(files), end)
|
|
||||||
}
|
|
||||||
for _, f := range files[start:end] {
|
|
||||||
d, err := codeintel.Parse(f.Path, f.Language)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Printf("## `%s` (%s)\n\n", rel(root, f.Path), f.Language)
|
|
||||||
for _, s := range codeintel.Symbols(d) {
|
|
||||||
fmt.Printf("- %s `%s` — line %d\n", strings.Repeat(" ", min(s.Depth, 4)), s.Name, s.Line)
|
|
||||||
}
|
|
||||||
fmt.Println()
|
|
||||||
d.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func rel(root, path string) string { p, _ := filepath.Rel(root, path); return p }
|
|
||||||
func min(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func fail(err error) { fmt.Fprintln(os.Stderr, "error:", err); os.Exit(1) }
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/filetools/internal/filetools"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() { run(filetools.Edit) }
|
|
||||||
func run(fn func(map[string]any) (string, error)) {
|
|
||||||
var m map[string]any
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&m); err != nil {
|
|
||||||
fail("invalid JSON input: %v", err)
|
|
||||||
}
|
|
||||||
out, err := fn(m)
|
|
||||||
if err != nil {
|
|
||||||
if out != "" {
|
|
||||||
fmt.Fprintln(os.Stdout, out)
|
|
||||||
}
|
|
||||||
fail("%v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(out)
|
|
||||||
}
|
|
||||||
func fail(f string, a ...any) { fmt.Fprintf(os.Stderr, "error: "+f+"\n", a...); os.Exit(1) }
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/filetools/internal/filetools"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() { run(filetools.Glob) }
|
|
||||||
func run(fn func(map[string]any) (string, error)) {
|
|
||||||
var m map[string]any
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&m); err != nil {
|
|
||||||
fail("invalid JSON input: %v", err)
|
|
||||||
}
|
|
||||||
out, err := fn(m)
|
|
||||||
if err != nil {
|
|
||||||
if out != "" {
|
|
||||||
fmt.Fprintln(os.Stdout, out)
|
|
||||||
}
|
|
||||||
fail("%v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(out)
|
|
||||||
}
|
|
||||||
func fail(f string, a ...any) { fmt.Fprintf(os.Stderr, "error: "+f+"\n", a...); os.Exit(1) }
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/filetools/internal/filetools"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() { run(filetools.Grep) }
|
|
||||||
func run(fn func(map[string]any) (string, error)) {
|
|
||||||
var m map[string]any
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&m); err != nil {
|
|
||||||
fail("invalid JSON input: %v", err)
|
|
||||||
}
|
|
||||||
out, err := fn(m)
|
|
||||||
if err != nil {
|
|
||||||
if out != "" {
|
|
||||||
fmt.Fprintln(os.Stdout, out)
|
|
||||||
}
|
|
||||||
fail("%v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(out)
|
|
||||||
}
|
|
||||||
func fail(f string, a ...any) { fmt.Fprintf(os.Stderr, "error: "+f+"\n", a...); os.Exit(1) }
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/filetools/internal/filetools"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() { run(filetools.Read) }
|
|
||||||
func run(fn func(map[string]any) (string, error)) {
|
|
||||||
var m map[string]any
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&m); err != nil {
|
|
||||||
fail("invalid JSON input: %v", err)
|
|
||||||
}
|
|
||||||
out, err := fn(m)
|
|
||||||
if err != nil {
|
|
||||||
if out != "" {
|
|
||||||
fmt.Fprintln(os.Stdout, out)
|
|
||||||
}
|
|
||||||
fail("%v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(out)
|
|
||||||
}
|
|
||||||
func fail(f string, a ...any) { fmt.Fprintf(os.Stderr, "error: "+f+"\n", a...); os.Exit(1) }
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"ollie/tools/filetools/internal/filetools"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() { run(filetools.Write) }
|
|
||||||
func run(fn func(map[string]any) (string, error)) {
|
|
||||||
var m map[string]any
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&m); err != nil {
|
|
||||||
fail("invalid JSON input: %v", err)
|
|
||||||
}
|
|
||||||
out, err := fn(m)
|
|
||||||
if err != nil {
|
|
||||||
if out != "" {
|
|
||||||
fmt.Fprintln(os.Stdout, out)
|
|
||||||
}
|
|
||||||
fail("%v", err)
|
|
||||||
}
|
|
||||||
fmt.Println(out)
|
|
||||||
}
|
|
||||||
func fail(f string, a ...any) { fmt.Fprintf(os.Stderr, "error: "+f+"\n", a...); os.Exit(1) }
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
// lsp_completion — Completion candidates at cursor position.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.Run("completion", func(result json.RawMessage) {
|
|
||||||
var list struct {
|
|
||||||
Items []completionItem `json:"items"`
|
|
||||||
}
|
|
||||||
if json.Unmarshal(result, &list) == nil && len(list.Items) > 0 {
|
|
||||||
for _, item := range list.Items {
|
|
||||||
printItem(item)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var items []completionItem
|
|
||||||
if json.Unmarshal(result, &items) == nil {
|
|
||||||
for _, item := range items {
|
|
||||||
printItem(item)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("(no completions)")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func printItem(item completionItem) {
|
|
||||||
kind := completionKind(item.Kind)
|
|
||||||
if item.Detail != "" {
|
|
||||||
fmt.Printf("%s %s [%s]\n", item.Label, item.Detail, kind)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%s [%s]\n", item.Label, kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type completionItem struct {
|
|
||||||
Label string `json:"label"`
|
|
||||||
Kind int `json:"kind"`
|
|
||||||
Detail string `json:"detail"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func completionKind(k int) string {
|
|
||||||
kinds := map[int]string{
|
|
||||||
1: "Text", 2: "Method", 3: "Function", 4: "Constructor",
|
|
||||||
5: "Field", 6: "Variable", 7: "Class", 8: "Interface",
|
|
||||||
9: "Module", 10: "Property", 11: "Unit", 12: "Value",
|
|
||||||
13: "Enum", 14: "Keyword", 15: "Snippet", 16: "Color",
|
|
||||||
17: "File", 18: "Reference", 19: "Folder", 20: "EnumMember",
|
|
||||||
21: "Constant", 22: "Struct", 23: "Event", 24: "Operator",
|
|
||||||
25: "TypeParameter",
|
|
||||||
}
|
|
||||||
if name, ok := kinds[k]; ok {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
return "Unknown"
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestCompletionKind(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
|
||||||
in int
|
|
||||||
want string
|
|
||||||
}{{1, "Text"}, {2, "Method"}, {3, "Function"}, {25, "TypeParameter"}, {0, "Unknown"}, {99, "Unknown"}} {
|
|
||||||
if got := completionKind(tc.in); got != tc.want {
|
|
||||||
t.Errorf("completionKind(%d)=%q want %q", tc.in, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
// lsp_definition — Go to definition of symbol at position.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/lsp"
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.Run("definition", func(result json.RawMessage) {
|
|
||||||
var locations []struct {
|
|
||||||
URI string `json:"uri"`
|
|
||||||
TargetURI string `json:"targetUri"`
|
|
||||||
Range *rang `json:"range"`
|
|
||||||
TargetRange *rang `json:"targetRange"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(result, &locations); err != nil {
|
|
||||||
var single struct {
|
|
||||||
URI string `json:"uri"`
|
|
||||||
TargetURI string `json:"targetUri"`
|
|
||||||
Range *rang `json:"range"`
|
|
||||||
TargetRange *rang `json:"targetRange"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(result, &single); err != nil {
|
|
||||||
fmt.Println("(no definition found)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
locations = append(locations, single)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, loc := range locations {
|
|
||||||
uri := loc.URI
|
|
||||||
if uri == "" {
|
|
||||||
uri = loc.TargetURI
|
|
||||||
}
|
|
||||||
path := lsp.URIToPath(uri)
|
|
||||||
r := loc.Range
|
|
||||||
if r == nil {
|
|
||||||
r = loc.TargetRange
|
|
||||||
}
|
|
||||||
if r == nil {
|
|
||||||
fmt.Println(path)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Printf("%s:%d:%d\n", path, r.Start.Line+1, r.Start.Character+1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type rang struct {
|
|
||||||
Start position `json:"start"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type position struct {
|
|
||||||
Line int `json:"line"`
|
|
||||||
Character int `json:"character"`
|
|
||||||
}
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
// lsp_diagnostics — Errors and warnings for a file.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/lsp"
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.RunCustom(func() {
|
|
||||||
var args struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&args); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, _ := filepath.Abs(args.Path)
|
|
||||||
|
|
||||||
result, err := lsp.ClientRequest(&lsp.BridgeRequest{
|
|
||||||
Method: "diagnostics",
|
|
||||||
File: file,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if result == nil || string(result) == "null" || string(result) == "[]" {
|
|
||||||
fmt.Println("(no diagnostics)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var diags []diagnostic
|
|
||||||
if err := json.Unmarshal(result, &diags); err != nil {
|
|
||||||
fmt.Println("(no diagnostics)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range diags {
|
|
||||||
sev := severity(d.Severity)
|
|
||||||
line := d.Range.Start.Line + 1
|
|
||||||
col := d.Range.Start.Character + 1
|
|
||||||
fmt.Printf("%s:%d:%d: %s: %s\n", file, line, col, sev, d.Message)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type diagnostic struct {
|
|
||||||
Range struct {
|
|
||||||
Start struct {
|
|
||||||
Line int `json:"line"`
|
|
||||||
Character int `json:"character"`
|
|
||||||
} `json:"start"`
|
|
||||||
} `json:"range"`
|
|
||||||
Severity int `json:"severity"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func severity(s int) string {
|
|
||||||
switch s {
|
|
||||||
case 1:
|
|
||||||
return "error"
|
|
||||||
case 2:
|
|
||||||
return "warning"
|
|
||||||
case 3:
|
|
||||||
return "info"
|
|
||||||
case 4:
|
|
||||||
return "hint"
|
|
||||||
default:
|
|
||||||
return "diagnostic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestSeverity(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
|
||||||
in int
|
|
||||||
want string
|
|
||||||
}{{1, "error"}, {2, "warning"}, {3, "info"}, {4, "hint"}, {0, "diagnostic"}, {9, "diagnostic"}} {
|
|
||||||
if got := severity(tc.in); got != tc.want {
|
|
||||||
t.Errorf("severity(%d)=%q want %q", tc.in, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
// lsp_hover — Type signature and documentation for symbol at position.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.Run("hover", func(result json.RawMessage) {
|
|
||||||
var hover struct {
|
|
||||||
Contents struct {
|
|
||||||
Kind string `json:"kind"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
} `json:"contents"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(result, &hover); err != nil {
|
|
||||||
var plain struct {
|
|
||||||
Contents string `json:"contents"`
|
|
||||||
}
|
|
||||||
if json.Unmarshal(result, &plain) == nil {
|
|
||||||
fmt.Println(plain.Contents)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println("(no hover information)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(hover.Contents.Value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
// lsp_references — Find all references to symbol at position.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/lsp"
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.Run("references", func(result json.RawMessage) {
|
|
||||||
var locations []struct {
|
|
||||||
URI string `json:"uri"`
|
|
||||||
Range struct {
|
|
||||||
Start struct {
|
|
||||||
Line int `json:"line"`
|
|
||||||
Character int `json:"character"`
|
|
||||||
} `json:"start"`
|
|
||||||
} `json:"range"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(result, &locations); err != nil {
|
|
||||||
fmt.Println("(no references found)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("STATUS=ok MATCH_COUNT=%d\n", len(locations))
|
|
||||||
for _, loc := range locations {
|
|
||||||
path := lsp.URIToPath(loc.URI)
|
|
||||||
fmt.Printf("%s:%d:%d\n", path, loc.Range.Start.Line+1, loc.Range.Start.Character+1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
// lsp_rename — Rename symbol across workspace. Applies edits directly.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/lsp"
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.RunCustom(func() {
|
|
||||||
var args struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Line string `json:"line"`
|
|
||||||
Col string `json:"col"`
|
|
||||||
NewName string `json:"new_name"`
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&args); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, _ := filepath.Abs(args.Path)
|
|
||||||
line, _ := strconv.Atoi(args.Line)
|
|
||||||
col, _ := strconv.Atoi(args.Col)
|
|
||||||
|
|
||||||
result, err := lsp.ClientRequest(&lsp.BridgeRequest{
|
|
||||||
Method: "rename",
|
|
||||||
File: file,
|
|
||||||
Line: line - 1,
|
|
||||||
Col: col - 1,
|
|
||||||
NewName: args.NewName,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if result == nil || string(result) == "null" {
|
|
||||||
fmt.Println("(rename produced no changes)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
summary := applyWorkspaceEdit(result)
|
|
||||||
if summary == "" {
|
|
||||||
fmt.Println("(rename produced no changes)")
|
|
||||||
} else {
|
|
||||||
fmt.Print(summary)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func applyWorkspaceEdit(raw json.RawMessage) string {
|
|
||||||
var edit struct {
|
|
||||||
Changes map[string][]textEdit `json:"changes"`
|
|
||||||
DocumentChanges []struct {
|
|
||||||
TextDocument struct {
|
|
||||||
URI string `json:"uri"`
|
|
||||||
} `json:"textDocument"`
|
|
||||||
Edits []textEdit `json:"edits"`
|
|
||||||
} `json:"documentChanges"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(raw, &edit); err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
changes := make(map[string][]textEdit)
|
|
||||||
if len(edit.DocumentChanges) > 0 {
|
|
||||||
for _, dc := range edit.DocumentChanges {
|
|
||||||
path := lsp.URIToPath(dc.TextDocument.URI)
|
|
||||||
changes[path] = append(changes[path], dc.Edits...)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for uri, edits := range edit.Changes {
|
|
||||||
path := lsp.URIToPath(uri)
|
|
||||||
changes[path] = edits
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sb strings.Builder
|
|
||||||
totalEdits := 0
|
|
||||||
for path, edits := range changes {
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lines := strings.SplitAfter(string(data), "\n")
|
|
||||||
|
|
||||||
sort.Slice(edits, func(i, j int) bool {
|
|
||||||
if edits[i].Range.Start.Line != edits[j].Range.Start.Line {
|
|
||||||
return edits[i].Range.Start.Line > edits[j].Range.Start.Line
|
|
||||||
}
|
|
||||||
return edits[i].Range.Start.Character > edits[j].Range.Start.Character
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, e := range edits {
|
|
||||||
sl, sc := e.Range.Start.Line, e.Range.Start.Character
|
|
||||||
el, ec := e.Range.End.Line, e.Range.End.Character
|
|
||||||
if sl >= len(lines) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
before := strings.Join(lines[:sl], "") + lines[sl][:min(sc, len(lines[sl]))]
|
|
||||||
var after string
|
|
||||||
if el < len(lines) {
|
|
||||||
after = lines[el][min(ec, len(lines[el])):] + strings.Join(lines[el+1:], "")
|
|
||||||
}
|
|
||||||
content := before + e.NewText + after
|
|
||||||
lines = strings.SplitAfter(content, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
os.WriteFile(path, []byte(strings.Join(lines, "")), 0644)
|
|
||||||
totalEdits += len(edits)
|
|
||||||
fmt.Fprintf(&sb, "%s: %d edit(s)\n", path, len(edits))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&sb, "total: %d file(s), %d edit(s)\n", len(changes), totalEdits)
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
type textEdit struct {
|
|
||||||
Range struct {
|
|
||||||
Start struct {
|
|
||||||
Line int `json:"line"`
|
|
||||||
Character int `json:"character"`
|
|
||||||
} `json:"start"`
|
|
||||||
End struct {
|
|
||||||
Line int `json:"line"`
|
|
||||||
Character int `json:"character"`
|
|
||||||
} `json:"end"`
|
|
||||||
} `json:"range"`
|
|
||||||
NewText string `json:"newText"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func min(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
// lsp_symbols — List symbols in a file, or search workspace-wide.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"ollie/tools/lsp/internal/lsp"
|
|
||||||
"ollie/tools/lsp/internal/cmdutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmdutil.RunCustom(func() {
|
|
||||||
var args struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(os.Stdin).Decode(&args); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, _ := filepath.Abs(args.Path)
|
|
||||||
workspace := args.Query != ""
|
|
||||||
|
|
||||||
result, err := lsp.ClientRequest(&lsp.BridgeRequest{
|
|
||||||
Method: "symbols",
|
|
||||||
File: file,
|
|
||||||
Query: args.Query,
|
|
||||||
Workspace: workspace,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if result == nil || string(result) == "null" {
|
|
||||||
fmt.Println("(no symbols found)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var docSymbols []documentSymbol
|
|
||||||
if json.Unmarshal(result, &docSymbols) == nil && len(docSymbols) > 0 {
|
|
||||||
printDocSymbols(docSymbols, 0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var wsSymbols []workspaceSymbol
|
|
||||||
if json.Unmarshal(result, &wsSymbols) == nil && len(wsSymbols) > 0 {
|
|
||||||
for _, s := range wsSymbols {
|
|
||||||
path := lsp.URIToPath(s.Location.URI)
|
|
||||||
line := s.Location.Range.Start.Line + 1
|
|
||||||
fmt.Printf("%s:%d %s [%s]\n", path, line, s.Name, symbolKind(s.Kind))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("(no symbols found)")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func printDocSymbols(symbols []documentSymbol, indent int) {
|
|
||||||
prefix := ""
|
|
||||||
for i := 0; i < indent; i++ {
|
|
||||||
prefix += " "
|
|
||||||
}
|
|
||||||
for _, s := range symbols {
|
|
||||||
line := s.Range.Start.Line + 1
|
|
||||||
fmt.Printf("%s%s L%d [%s]\n", prefix, s.Name, line, symbolKind(s.Kind))
|
|
||||||
if len(s.Children) > 0 {
|
|
||||||
printDocSymbols(s.Children, indent+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type documentSymbol struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Kind int `json:"kind"`
|
|
||||||
Range rang `json:"range"`
|
|
||||||
Children []documentSymbol `json:"children"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type workspaceSymbol struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Kind int `json:"kind"`
|
|
||||||
Location struct {
|
|
||||||
URI string `json:"uri"`
|
|
||||||
Range rang `json:"range"`
|
|
||||||
} `json:"location"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type rang struct {
|
|
||||||
Start struct {
|
|
||||||
Line int `json:"line"`
|
|
||||||
} `json:"start"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func symbolKind(k int) string {
|
|
||||||
kinds := map[int]string{
|
|
||||||
1: "File", 2: "Module", 3: "Namespace", 4: "Package",
|
|
||||||
5: "Class", 6: "Method", 7: "Property", 8: "Field",
|
|
||||||
9: "Constructor", 10: "Enum", 11: "Interface", 12: "Function",
|
|
||||||
13: "Variable", 14: "Constant", 15: "String", 16: "Number",
|
|
||||||
17: "Boolean", 18: "Array", 19: "Object", 20: "Key",
|
|
||||||
21: "Null", 22: "EnumMember", 23: "Struct", 24: "Event",
|
|
||||||
25: "Operator", 26: "TypeParameter",
|
|
||||||
}
|
|
||||||
if name, ok := kinds[k]; ok {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("Kind(%d)", k)
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"description": "Fetch an HTTP(S) page and render its HTML as Markdown.",
|
|
||||||
"prompt": "## web_fetch\n\nFetch an HTTP(S) page and render its HTML as Markdown.\n\n**Args**: `[url]`\n\n```\nweb_fetch(url=\"https://example.com\")\n```",
|
|
||||||
"args": {
|
|
||||||
"type": "object",
|
|
||||||
"required": ["url"],
|
|
||||||
"properties": {
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Absolute HTTP or HTTPS URL"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scope": "read"
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue