ollie/tools/lsp/internal/cmdutil/cmdutil.go

86 lines
2.0 KiB
Go

// Package cmdutil provides shared boilerplate for LSP tool command binaries.
package cmdutil
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strconv"
"ollie/tools/lsp/internal/lsp"
)
// PositionArgs are the common args for position-based LSP commands.
type PositionArgs struct {
Path string `json:"path"`
Line string `json:"line"`
Col string `json:"col"`
}
// ResolvePosition converts the string fields to absolute path and 0-indexed ints.
func (a PositionArgs) ResolvePosition() (file string, line, col int) {
file, _ = filepath.Abs(a.Path)
l, _ := strconv.Atoi(a.Line)
c, _ := strconv.Atoi(a.Col)
return file, l - 1, c - 1
}
// Run is the common entry point for position-based LSP commands.
// It handles --bridge, reads PositionArgs from stdin, dispatches the request,
// and passes the result to format. If format is nil, raw JSON is printed.
func Run(method string, format func(json.RawMessage)) {
if len(os.Args) > 1 && os.Args[1] == "--bridge" {
if err := lsp.RunBridge(); err != nil {
fmt.Fprintf(os.Stderr, "bridge: %v\n", err)
os.Exit(1)
}
return
}
var args PositionArgs
if err := json.NewDecoder(os.Stdin).Decode(&args); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
file, line, col := args.ResolvePosition()
result, err := lsp.ClientRequest(&lsp.BridgeRequest{
Method: method,
File: file,
Line: line,
Col: col,
})
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if result == nil || string(result) == "null" {
fmt.Printf("(no %s found)\n", method)
return
}
if format != nil {
format(result)
} else {
os.Stdout.Write(result)
fmt.Println()
}
}
// RunCustom handles --bridge and then calls fn for custom argument handling.
// Use for commands that don't follow the simple position-args pattern
// (e.g. diagnostics, rename, symbols).
func RunCustom(fn func()) {
if len(os.Args) > 1 && os.Args[1] == "--bridge" {
if err := lsp.RunBridge(); err != nil {
fmt.Fprintf(os.Stderr, "bridge: %v\n", err)
os.Exit(1)
}
return
}
fn()
}