branch: externals/drepl
commit 00da350c03025e6fb094977a612214c05bcc97a8
Author: Augusto Stoffel <arstof...@gmail.com>
Commit: Augusto Stoffel <arstof...@gmail.com>

    Adjust completion prefixes
    
    This is necessary when Emacs and the REPL disagree about the
    completion bounds.
---
 README.org               |  5 +++--
 drepl-usql/drepl-usql.go | 19 ++++++++-----------
 drepl.el                 | 30 +++++++++++++++++++++++++-----
 3 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/README.org b/README.org
index 7908ea81ea..983869aa99 100644
--- a/README.org
+++ b/README.org
@@ -119,8 +119,9 @@ Parameters:
   completion.
 
 Response:
-- =candidates= (optional): A list of objects, each containing the
-  following attributes.
+- =prefix= (optional): The portion of code that is being completed.
+- =candidates= (optional): A list of completion candidates, either
+  strings or objects containing the following attributes:
   - =text=: The completed text, including the existing prefix.
   - =annot=: Annotation text to be displayed next to the candidate
     in the completion UI.
diff --git a/drepl-usql/drepl-usql.go b/drepl-usql/drepl-usql.go
index cae1bac715..e0671495a8 100644
--- a/drepl-usql/drepl-usql.go
+++ b/drepl-usql/drepl-usql.go
@@ -133,27 +133,23 @@ func (l *Dline) CheckInput(code string) (status string, 
prompt string) {
        return status, prompt
 }
 
-type Candidate struct {
-       Text string `json:"text"`
-}
-
-func (l *Dline) Complete(code string, pos int) []Candidate {
+func (l *Dline) Complete(code string, pos int) (string, []string) {
        if l.completer == nil || len(code) < pos {
-               return nil
+               return "", nil
        }
        coder := []rune(code)
        candr, i := l.completer.Do(coder, pos)
        start := pos - i
        if start < 0 {
-               return nil
+               return "", nil
        }
        prefix := coder[start:pos]
-       cands := make([]Candidate, 0, len(candr))
+       cands := make([]string, 0, len(candr))
        for _, c := range candr {
                c = append(prefix, c...)
-               cands = append(cands, Candidate{string(c)})
+               cands = append(cands, string(c))
        }
-       return cands
+       return string(prefix), cands
 }
 
 // Next returns the next line of runes (excluding '\n') from the input.
@@ -180,9 +176,10 @@ func (l *Dline) Next() ([]rune, error) {
                                "prompt": prompt,
                        })
                case "complete":
-                       cands := l.Complete(msg.Code, msg.Pos)
+                       prefix, cands := l.Complete(msg.Code, msg.Pos)
                        l.SendMsg(map[string]any{
                                "id":         msg.Id,
+                               "prefix":     prefix,
                                "candidates": cands,
                        })
                default:
diff --git a/drepl.el b/drepl.el
index e32e10a8f7..9c05ef332b 100644
--- a/drepl.el
+++ b/drepl.el
@@ -353,10 +353,26 @@ interactively."
                                         :code code
                                         :pos pos))))
     (when (listp response)
-      (mapcar (lambda (c)
-                (let-alist c
-                  (propertize .text 'drepl--annot .annot)))
-              (alist-get 'candidates response)))))
+      (cons
+       (alist-get 'prefix response)
+       (mapcar (lambda (c)
+                 (or (and (stringp c) c)
+                     (let-alist c
+                       (propertize .text 'drepl--annot .annot))))
+               (alist-get 'candidates response))))))
+
+(defun drepl--adjust-candidates (ours theirs cands)
+  "Adjust completion candidate prefixes.
+OURS is the completion prefix computed by Emacs.
+THEIRS is the completion prefix computed by the REPL.
+CANDS is the candidate list computed by the REPL."
+  (let ((d (- (length theirs) (length ours))))
+    (cond ((or (not theirs) (zerop d)) cands)
+          ((cl-plusp d)
+           (mapcar (lambda (s) (substring s d)) cands))
+          ((cl-minusp d)
+           (let ((p (substring ours 0 (abs d))))
+             (mapcar (lambda (s) (concat p s)) cands))))))
 
 (defun drepl--complete ()
   "Function intended for use as a member of `completion-at-point-functions'."
@@ -367,8 +383,12 @@ interactively."
                     (cdr comint-last-prompt)
                     (point-max)))
              (pos (- (point) (cdr comint-last-prompt)))
-             (cands (when (>= pos 0)
+             (reply (when (>= pos 0)
                       (drepl--completion-cadidates repl code pos)))
+             (cands (drepl--adjust-candidates
+                     (buffer-substring-no-properties (car bounds) (cdr bounds))
+                     (car reply)
+                     (cdr reply)))
              (metadata '(metadata
                          (category . drepl)
                          (annotation-function . drepl--capf-annotate)))

Reply via email to