diff --git a/cmd/L/main.go b/cmd/L/main.go index aa3be57..a8d2b49 100644 --- a/cmd/L/main.go +++ b/cmd/L/main.go @@ -11,8 +11,10 @@ import ( "os" "path/filepath" "strconv" + "strings" p9client "github.com/fhs/9fans-go/plan9/client" + "github.com/fhs/acme-lsp/internal/acme" "github.com/fhs/acme-lsp/internal/golang_org_x_tools/jsonrpc2" "github.com/fhs/acme-lsp/internal/lsp" "github.com/fhs/acme-lsp/internal/lsp/acmelsp" @@ -185,12 +187,12 @@ func run(cfg *config.Config, args []string) error { return fmt.Errorf("unknown assist command %q", args[0]) } - winid, err := getWinID() + winid, offset, err := getWinID() if err != nil { return err } - rc := acmelsp.NewRemoteCmd(server, winid) + rc := acmelsp.NewRemoteCmd(server, winid, offset) // In case the window has unsaved changes (it's dirty), sync changes with LSP server. err = rc.DidChange(ctx) @@ -230,16 +232,50 @@ func run(cfg *config.Config, args []string) error { return fmt.Errorf("unknown command %q", args[0]) } -func getWinID() (int, error) { +func parseAddress(addr string) (file string, offset int, err error) { + split := strings.Split(addr, ":") + file = split[0] + if len(split) > 1 { + split = strings.Split(split[1], ",") + offsetstring := split[len(split)-1] + offsettrim := strings.TrimPrefix(offsetstring, "#") + offset, err = strconv.Atoi(offsettrim) + } + return file, offset, err +} + +func getWinID() (id int, offset int, err error) { winid, err := getFocusedWinID(filepath.Join(p9client.Namespace(), "acmefocused")) if err != nil { - return 0, fmt.Errorf("could not get focused window ID: %v", err) + return 0, -1, fmt.Errorf("could not get focused window ID: %v", err) } n, err := strconv.Atoi(winid) if err != nil { - return 0, fmt.Errorf("failed to parse $winid: %v", err) + return 0, -1, fmt.Errorf("failed to parse $winid: %v", err) + } + // Now check for a chord command + acmeaddr := os.Getenv("acmeaddr") + if acmeaddr != "" { + if err != nil { + return 0, -1, fmt.Errorf("failed to to parse chord %v: %v", n, err) + } + file, offset, err := parseAddress(string(acmeaddr)) + if err != nil { + return n, -1, nil + } + // Find the file in the index + windows, err := acme.Windows() + if err != nil { + return n, -1, nil + } + for _, w := range windows { + if w.Name == file { + return w.ID, offset, nil + } + } + fmt.Println(file, offset) } - return n, nil + return n, -1, nil } func dirsOrCurrentDir(dirs []string) ([]protocol.WorkspaceFolder, error) { diff --git a/internal/lsp/acmelsp/acmelsp.go b/internal/lsp/acmelsp/acmelsp.go index 82a32c7..dface2f 100644 --- a/internal/lsp/acmelsp/acmelsp.go +++ b/internal/lsp/acmelsp/acmelsp.go @@ -55,7 +55,7 @@ func WindowRemoteCmd(ss *ServerSet, fm *FileManager, winid int) (*RemoteCmd, err return nil, fmt.Errorf("DidChange failed: %v", err) } - return NewRemoteCmd(srv.Client, winid), nil + return NewRemoteCmd(srv.Client, winid, -1), nil } func getLine(p string, l int) string { diff --git a/internal/lsp/acmelsp/assist.go b/internal/lsp/acmelsp/assist.go index 8fdfa97..ae09346 100644 --- a/internal/lsp/acmelsp/assist.go +++ b/internal/lsp/acmelsp/assist.go @@ -205,7 +205,7 @@ func (w *outputWin) Update(fw *focusWin, server proxy.Server, cmd string) { } } - rc := NewRemoteCmd(server, fw.id) + rc := NewRemoteCmd(server, fw.id, -1) rc.Stdout = w.body rc.Stderr = w.body ctx := context.Background() diff --git a/internal/lsp/acmelsp/remote.go b/internal/lsp/acmelsp/remote.go index 5560578..11529f8 100644 --- a/internal/lsp/acmelsp/remote.go +++ b/internal/lsp/acmelsp/remote.go @@ -18,14 +18,16 @@ import ( type RemoteCmd struct { server proxy.Server winid int + offset int Stdout io.Writer Stderr io.Writer } -func NewRemoteCmd(server proxy.Server, winid int) *RemoteCmd { +func NewRemoteCmd(server proxy.Server, winid int, offset int) *RemoteCmd { return &RemoteCmd{ server: server, winid: winid, + offset: offset, Stdout: os.Stdout, Stderr: os.Stderr, } @@ -37,7 +39,9 @@ func (rc *RemoteCmd) getPosition() (pos *protocol.TextDocumentPositionParams, fi return nil, "", fmt.Errorf("failed to to open window %v: %v", rc.winid, err) } defer w.CloseFiles() - + if rc.offset != -1 { + return text.PositionQ0(w, rc.offset) + } return text.Position(w) } diff --git a/internal/lsp/text/edit.go b/internal/lsp/text/edit.go index 5c491aa..ff4e30f 100644 --- a/internal/lsp/text/edit.go +++ b/internal/lsp/text/edit.go @@ -33,7 +33,7 @@ func Edit(f File, edits []protocol.TextEdit) error { if err != nil { return err } - off, err := getNewlineOffsets(reader) + off, err := GetNewlineOffsets(reader) if err != nil { return fmt.Errorf("failed to obtain newline offsets: %v", err) } @@ -72,21 +72,16 @@ func DocumentURI(f AddressableFile) (uri protocol.DocumentURI, filename string, return ToURI(name), name, nil } -// Position returns the current position within a file being edited. -func Position(f AddressableFile) (pos *protocol.TextDocumentPositionParams, filename string, err error) { +func PositionQ0(f AddressableFile, q0 int) (pos *protocol.TextDocumentPositionParams, filename string, err error) { name, err := f.Filename() if err != nil { return nil, "", fmt.Errorf("could not get window filename: %v", err) } - q0, _, err := f.CurrentAddr() - if err != nil { - return nil, "", fmt.Errorf("could not get current address: %v", err) - } reader, err := f.Reader() if err != nil { return nil, "", fmt.Errorf("could not get window body reader: %v", err) } - off, err := getNewlineOffsets(reader) + off, err := GetNewlineOffsets(reader) if err != nil { return nil, "", fmt.Errorf("failed to get newline offset: %v", err) } @@ -102,6 +97,15 @@ func Position(f AddressableFile) (pos *protocol.TextDocumentPositionParams, file }, name, nil } +// Position returns the current position within a file being edited. +func Position(f AddressableFile) (pos *protocol.TextDocumentPositionParams, filename string, err error) { + q0, _, err := f.CurrentAddr() + if err != nil { + return nil, "", fmt.Errorf("could not get current address: %v", err) + } + return PositionQ0(f, q0) +} + // ToURI converts filename to URI. func ToURI(filename string) protocol.DocumentURI { return protocol.DocumentURI(span.NewURI(filename)) diff --git a/internal/lsp/text/line.go b/internal/lsp/text/line.go index ad10cfd..8dec867 100644 --- a/internal/lsp/text/line.go +++ b/internal/lsp/text/line.go @@ -15,7 +15,7 @@ type nlOffsets struct { leftover int // runes leftover after last '\n' } -func getNewlineOffsets(r io.Reader) (*nlOffsets, error) { +func GetNewlineOffsets(r io.Reader) (*nlOffsets, error) { br := bufio.NewReader(r) o := 0 nl := []int{0}