]> git.eshelyaron.com Git - emacs.git/commitdiff
choose-completion: Retain the suffix after completion boundary
authorDmitry Gutov <dmitry@gutov.dev>
Thu, 9 May 2024 02:30:32 +0000 (05:30 +0300)
committerEshel Yaron <me@eshelyaron.com>
Fri, 10 May 2024 13:26:23 +0000 (15:26 +0200)
* lisp/minibuffer.el (completion-base-suffix):
Remove as not optimal after all (bug#48356).
(completion--replace): Use insert-before-markers-and-inherit.
(minibuffer-completion-help): Don't set completion-base-affixes,
implement the same logic more optimally by local search and
querying for field boundaries.  Also fix the problem with
completion table, predicate and extra-props being looked up in the
wrong buffer.
(minibuffer-next-completion, minibuffer-choose-completion):
Don't bind completion-use-base-affixes anymore.

* lisp/simple.el (completion-base-affixes)
(completion-use-base-affixes): Remove.
(completion-list-insert-choice-function):
Don't pass them through anymore.

(cherry picked from commit ff3f17ca3cdd9e82355942f577e7807acc76ddcd)

lisp/minibuffer.el
lisp/simple.el

index c07117ef07f6d69435fc5e21ceab436f6424011f..ddda14376c400be2610199e28fd47293da742f98 100644 (file)
@@ -92,20 +92,6 @@ the closest directory separators."
     (cons (or (cadr boundaries) 0)
           (or (cddr boundaries) (length suffix)))))
 
-(defun completion-base-suffix (start end collection predicate)
-  "Return suffix of completion of buffer text between START and END.
-COLLECTION and PREDICATE are, respectively, the completion's
-completion table and predicate, as in `completion-boundaries' (which see).
-Value is a substring of buffer text between point and END.  It is
-the completion suffix that follows the completion boundary."
-  (let ((suffix (buffer-substring (point) end)))
-    (substring
-     suffix
-     (cdr (completion-boundaries (buffer-substring start (point))
-                                 collection
-                                 predicate
-                                 suffix)))))
-
 (defun completion-metadata (string table pred)
   "Return the metadata of elements to complete at the end of STRING.
 This metadata is an alist.  Currently understood keys are:
@@ -1472,7 +1458,7 @@ Moves point to the end of the new text."
       (setq newtext (substring newtext 0 (- suffix-len))))
     (goto-char beg)
     (let ((length (- end beg)))         ;Read `end' before we insert the text.
-      (insert-and-inherit newtext)
+      (insert-before-markers-and-inherit newtext)
       (delete-region (point) (+ (point) length)))
     (forward-char suffix-len)))
 
@@ -2327,6 +2313,7 @@ completions."
   :type 'boolean
   :version "28.1")
 
+(defvar-local completions-base-prefix nil)
 (defvar-local completions-candidates nil)
 (defvar-local completions-group-function nil)
 (defvar-local completions-category nil)
@@ -3008,10 +2995,15 @@ completions list."
              (full-base (substring string 0 base-size))
              (base-prefix (buffer-substring (minibuffer--completion-prompt-end)
                                             (+ start base-size)))
-             (base-suffix (concat (completion-base-suffix start end
-                                                          minibuffer-completion-table
-                                                          minibuffer-completion-predicate)
-                                  (buffer-substring end (point-max))))
+             (field-end
+              (save-excursion
+                (forward-char
+                 (cdr (completion-boundaries (buffer-substring start (point))
+                                             minibuffer-completion-table
+                                             minibuffer-completion-predicate
+                                             (buffer-substring (point) end))))
+                (point-marker)))
+             (field-char (and (< field-end end) (char-after field-end)))
              (style completion--matching-style)
              (exceptional-candidates
               (or (not completions-exclude-exceptional-candidates)
@@ -3132,31 +3124,34 @@ completions list."
                  :predicate cpred
                  :exceptional-candidates exceptional-candidates
                  :action action
-                 :base-position (list (+ start base-size) end)
-                 :base-affixes (list base-prefix base-suffix)
+                 :base-position (list (+ start base-size) field-end)
+                 :base-prefix base-prefix
                  :ignore-case completion-ignore-case
                  :insert-choice-function
                  (let ((cprops completion-extra-properties))
                    (lambda (start end choice)
-                     (if (and (stringp start) (stringp end))
-                         (progn
-                           (delete-minibuffer-contents)
-                           (insert start choice)
-                           ;; Keep point after completion before suffix
-                           (save-excursion (insert
-                                            (completion--merge-suffix
-                                             choice
-                                             (1- (length choice))
-                                             end))))
-                       (unless (or (zerop (length prefix))
-                                   (equal prefix
-                                          (buffer-substring-no-properties
-                                           (max (point-min)
-                                                (- start (length prefix)))
-                                           start)))
-                         (message "*Completions* out of date"))
-                       ;; FIXME: Use `md' to do quoting&terminator here.
-                       (completion--replace start end choice))
+                     (unless (or (zerop (length prefix))
+                                 (equal prefix
+                                        (buffer-substring-no-properties
+                                         (max (point-min)
+                                              (- start (length prefix)))
+                                         start)))
+                       (message "*Completions* out of date"))
+                     (when (> (point) end)
+                       ;; Completion suffix has changed, have to adapt.
+                       (setq end (+ end
+                                    (cdr (completion-boundaries
+                                          (concat prefix choice) ctable cpred
+                                          (buffer-substring end (point))))))
+                       ;; Stopped before some field boundary.
+                       (when (> (point) end)
+                         (setq field-char (char-after end))))
+                     (when (and field-char
+                                (= (aref choice (1- (length choice)))
+                                   field-char))
+                       (setq end (1+ end)))
+                     ;; FIXME: Use `md' to do quoting&terminator here.
+                     (completion--replace start end choice)
                      (let* ((minibuffer-completion-table ctable)
                             (minibuffer-completion-predicate cpred)
                             (completion-extra-properties cprops)
@@ -3232,7 +3227,7 @@ PLIST is a property list with optional extra information about COMPLETIONS."
        completions-group-function group-fun
        completions-style (plist-get plist :style)
        completion-base-position (plist-get plist :base-position)
-       completion-base-affixes (plist-get plist :base-affixes)
+       completions-base-prefix (plist-get plist :base-prefix)
        completion-list-insert-choice-function (plist-get plist :insert-choice-function)
        completions-category (plist-get plist :category)
        completions-sort-function (plist-get plist :sort-function)
@@ -5550,8 +5545,7 @@ after executing BODY."
          (setq-local cursor-face-highlight-nonselected-window t))
        ,@body
        (when auto-choose
-         (let ((completion-use-base-affixes t))
-           (choose-completion nil t t))))))
+         (choose-completion nil t t)))))
 
 (defun minibuffer-first-completion ()
   "Move to the first item in the completions window from the minibuffer.
@@ -5625,8 +5619,7 @@ If NO-QUIT is non-nil, insert the completion candidate at point to the
 minibuffer, but don't quit the completions window."
   (interactive "P")
   (with-minibuffer-completions-window
-    (let ((completion-use-base-affixes t))
-      (choose-completion nil no-exit no-quit))))
+    (choose-completion nil no-exit no-quit)))
 
 (defun minibuffer-complete-history ()
   "Complete the minibuffer history as far as possible.
index 7169ad57b78a7dd82e8679e80f4637bb0d23e4c6..3eb3874f1165e04d7d432ceac9c156e6bf65b8ca 100644 (file)
@@ -9855,7 +9855,7 @@ makes it easier to edit it."
   (interactive "e")
   (with-current-buffer (window-buffer (posn-window (event-end e)))
     (let ((str (get-text-property (posn-point (event-start e)) 'completion--string))
-          (prf (car completion-base-affixes))
+          (prf completions-base-prefix)
           (act (car completions-action)))
       (with-current-buffer completion-reference-buffer
         (when-let ((adjust-fn (alist-get 'adjust-base-function
@@ -9907,16 +9907,6 @@ Its value is a list of the form (START END) where START is the place
 where the completion should be inserted and END (if non-nil) is the end
 of the text to replace.  If END is nil, point is used instead.")
 
-(defvar completion-base-affixes nil
-  "Base context of the text corresponding to the shown completions.
-This variable is used in the *Completions* buffer.
-Its value is a list of the form (PREFIX SUFFIX) where PREFIX is the text
-before the place where completion should be inserted, and SUFFIX is the text
-after the completion.")
-
-(defvar completion-use-base-affixes nil
-  "Non-nil means to restore original prefix and suffix in the minibuffer.")
-
 (defvar completion-list-insert-choice-function #'completion--replace
   "Function to use to insert the text chosen in *Completions*.
 Called with three arguments (BEG END TEXT), it should replace the text
@@ -10162,7 +10152,6 @@ minibuffer, but don't quit the completions window."
   (with-current-buffer (window-buffer (posn-window (event-start event)))
     (let ((buffer completion-reference-buffer)
           (base-position completion-base-position)
-          (base-affixes completion-base-affixes)
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
@@ -10191,13 +10180,7 @@ minibuffer, but don't quit the completions window."
       (with-current-buffer buffer
         (choose-completion-string
          choice buffer
-         ;; Don't allow affixes to replace the whole buffer when not
-         ;; in the minibuffer.  Thus check for `completion-in-region-mode'
-         ;; to ignore non-nil value of `completion-use-base-affixes' set by
-         ;; `minibuffer-choose-completion'.
-         (or (and (not completion-in-region-mode)
-                  completion-use-base-affixes base-affixes)
-             base-position
+         (or base-position
              ;; If all else fails, just guess.
              (list (choose-completion-guess-base-position choice)))
          insert-function)))))