Subject: bug#62700: 29.0.60; minibuffer-{previous,next,choose}-completion behave unintuitively when point is not at end of buffer

From: Spencer Baugh <[email-masked]>
Date: Fri, 02 Jun 2023 20:58:52 -0400

It turns out my patch doesn't fully fix the issue, when doing completion
at the end of a file path.  For example:

1. C-x C-f ~/src/emacs/emacs-29/lisp/.el
2. TAB to trigger completion, moving point to before .el
3. M-<down>
4. The filenames are inserted before the .el, so one gets for example
   ~/src/emacs/emacs-29/lisp/abbrev.el.el

The attached patch for the Emacs 29 branch fixes this remaining case.

>From 33f9cfa6afb7ae232ed6d5bbc4692a463f57a7a8 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Fri, 2 Jun 2023 20:57:32 -0400
Subject: [PATCH] Handle point in last file path component in minibuffer
 completion

This is a followup to commit e338a8ac41d4a9fd798dda90275abe75ac071335
(Handle point not at EOB in minibuffer-choose-completion).

That added a heuristic, but the heuristic was insufficient: It still
had the original wrong behavior when completing the last file path
component (i.e., the completion category is 'file and there's no /
after point).  This patch makes the heuristic cover that case too.

* lisp/minibuffer.el (minibuffer-next-completion)
(minibuffer-choose-completion): If in file completion and there's no /
after point, clear what's after point when we complete.  (Bug#62700)
---
 lisp/minibuffer.el | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 298f3f8728d..a873e5f9747 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -4498,8 +4498,9 @@ minibuffer-next-completion
                (base-suffix
                 (if (eq (alist-get 'category (cdr md)) 'file)
                     (with-current-buffer buf
-                      (buffer-substring (save-excursion (search-forward "/" nil t) (point))
-                                        (point-max)))
+                      (buffer-substring
+                       (save-excursion (or (search-forward "/" nil t) (point-max)))
+                       (point-max)))
                   ""))
               (completion-base-affixes (list (car completion-base-affixes) base-suffix)))
           (choose-completion nil t t))))))
@@ -4524,8 +4525,9 @@ minibuffer-choose-completion
   (let* ((md (completion--field-metadata (minibuffer--completion-prompt-end)))
          (base-suffix
           (if (eq (alist-get 'category (cdr md)) 'file)
-              (buffer-substring (save-excursion (search-forward "/" nil t) (point))
-                                (point-max))
+              (buffer-substring
+               (save-excursion (or (search-forward "/" nil t) (point-max)))
+               (point-max))
             "")))
     (with-minibuffer-completions-window
       (let ((completion-use-base-affixes t)
-- 
2.39.3