diff --git a/cmd/L/main.go b/cmd/L/main.go index 50d4dcd..b590701 100644 --- a/cmd/L/main.go +++ b/cmd/L/main.go @@ -40,10 +40,13 @@ attempt to find the focused window ID by connecting to acmefocused List of sub-commands: - comp [-e] + comp [-e] [-E] Print candidate completions at the cursor position. If -e (edit) flag is given and there is only one candidate, - the completion is applied instead of being printed. + the completion is applied instead of being printed. If + -E (Edit) flag is given, the first matching candidate is + applied, and all matches will be displayed in a dedicated + Acme window named /LSP/Completions. def [-p] Find where the symbol at the cursor position is defined @@ -206,7 +209,18 @@ func run(cfg *config.Config, args []string) error { switch args[0] { case "comp": args = args[1:] - return rc.Completion(ctx, len(args) > 0 && args[0] == "-e") + + var kind acmelsp.CompletionKind + if len(args) > 0 { + switch args[0] { + case "-e": + kind = acmelsp.CompleteInsertOnlyMatch + case "-E": + kind = acmelsp.CompleteInsertFirstMatch + } + } + + return rc.Completion(ctx, kind) case "def": args = args[1:] return rc.Definition(ctx, len(args) > 0 && args[0] == "-p") diff --git a/cmd/Lone/main.go b/cmd/Lone/main.go index 0d87707..9452c66 100644 --- a/cmd/Lone/main.go +++ b/cmd/Lone/main.go @@ -142,7 +142,7 @@ func run(cfg *config.Config, args []string) error { switch args[0] { case "comp": - err = rc.Completion(ctx, false) + err = rc.Completion(ctx, acmelsp.CompleteNoEdit) case "def": err = rc.Definition(ctx, false) case "fmt": diff --git a/internal/lsp/acmelsp/assist.go b/internal/lsp/acmelsp/assist.go index 5c38ea9..106fad6 100644 --- a/internal/lsp/acmelsp/assist.go +++ b/internal/lsp/acmelsp/assist.go @@ -220,7 +220,7 @@ func (w *outputWin) Update(fw *focusWin, server proxy.Server, cmd string) { w.Clear() switch cmd { case "comp": - err := rc.Completion(ctx, false) + err := rc.Completion(ctx, CompleteNoEdit) if err != nil { dprintf("Completion failed: %v\n", err) } diff --git a/internal/lsp/acmelsp/remote.go b/internal/lsp/acmelsp/remote.go index e0dc300..b81456b 100644 --- a/internal/lsp/acmelsp/remote.go +++ b/internal/lsp/acmelsp/remote.go @@ -73,7 +73,15 @@ func (rc *RemoteCmd) DidChange(ctx context.Context) error { }) } -func (rc *RemoteCmd) Completion(ctx context.Context, edit bool) error { +type CompletionKind int + +const ( + CompleteNoEdit CompletionKind = iota + CompleteInsertOnlyMatch + CompleteInsertFirstMatch +) + +func (rc *RemoteCmd) Completion(ctx context.Context, kind CompletionKind) error { w, err := acmeutil.OpenWin(rc.winid) if err != nil { return err @@ -90,7 +98,8 @@ func (rc *RemoteCmd) Completion(ctx context.Context, edit bool) error { if err != nil { return err } - if edit && len(result.Items) == 1 { + + if (kind == CompleteInsertFirstMatch && len(result.Items) >= 1) || (kind == CompleteInsertOnlyMatch && len(result.Items) == 1) { textEdit := result.Items[0].TextEdit if textEdit == nil { // TODO(fhs): Use insertText or label instead. @@ -99,14 +108,41 @@ func (rc *RemoteCmd) Completion(ctx context.Context, edit bool) error { if err := text.Edit(w, []protocol.TextEdit{*textEdit}); err != nil { return fmt.Errorf("failed to apply completion edit: %v", err) } - return nil + + if len(result.Items) == 1 { + return nil + } } + + var sb strings.Builder + if len(result.Items) == 0 { - fmt.Fprintf(rc.Stderr, "no completion\n") + fmt.Fprintf(&sb, "no completion\n") } + for _, item := range result.Items { - fmt.Fprintf(rc.Stdout, "%v %v\n", item.Label, item.Detail) + fmt.Fprintf(&sb, "%v\t%v\n", item.Label, item.Detail) } + + if kind == CompleteInsertFirstMatch { + cw, err := acmeutil.Hijack("/LSP/Completions") + if err != nil { + cw, err = acmeutil.NewWin() + if err != nil { + return err + } + + cw.Name("/LSP/Completions") + } + + defer cw.Win.Ctl("clean") + + cw.Clear() + cw.PrintTabbed(sb.String()) + } else { + fmt.Println(sb.String()) + } + return nil } diff --git a/internal/lsp/text/edit.go b/internal/lsp/text/edit.go index 8d98517..3848358 100644 --- a/internal/lsp/text/edit.go +++ b/internal/lsp/text/edit.go @@ -65,6 +65,7 @@ func Edit(f File, edits []protocol.TextEdit) error { q1 := off.LineToOffset(int(e.Range.End.Line), int(e.Range.End.Character)) f.WriteAt(q0, q1, []byte(e.NewText)) } + return nil }