From: Dmitry Gutov Date: Thu, 9 May 2024 02:30:32 +0000 (+0300) Subject: choose-completion: Retain the suffix after completion boundary X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=b0589b180b590e659b18225e34b45cfe2e36dc79;p=emacs.git choose-completion: Retain the suffix after completion boundary * 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) --- diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index c07117ef07f..ddda14376c4 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -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. diff --git a/lisp/simple.el b/lisp/simple.el index 7169ad57b78..3eb3874f116 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -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)))))