Subject: Re: bug#38992: 27.0.60; when enabled, fido-mode seems to break vc-git-grep

From: Dmitry Gutov <[email-masked]>
Date: Fri, 24 Jan 2020 01:07:15 +0300

On 23.01.2020 19:28, Stefan Monnier wrote:
> We could introduce a new `minibuffer-require-match` variable (and mark
> `minibuffer-completion-confirm` obsolete).

Why don't we just co-opt the older variable. A rename can come later. 
See patch 1.

Here's another issue related to the previous proposed fix: why *would* 
M-j exit minibuffer in all cases? It currently doesn't honor 
REQUIRE-MATCH=t (or the confirm- values, but I don't care about that). 
The default completing-read, as well as icomplete-mode, both honor it. 
The patch 2 fixes that.

Please take a look, y'all.
>From 73728a7928568c883650cc403194c3b95348a08b Mon Sep 17 00:00:00 2001
From: Dmitry Gutov <[email-masked]>
Date: Fri, 24 Jan 2020 00:51:06 +0300
Subject: [PATCH 1/2] Honor require-match=nil in icomplete-fido-ret

---
 doc/lispref/minibuf.texi | 8 +++++---
 lisp/emacs-lisp/crm.el   | 3 +--
 lisp/icomplete.el        | 2 +-
 lisp/minibuffer.el       | 8 +++++---
 src/minibuf.c            | 3 ++-
 5 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index ab806a9055..c881deeaf4 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -1127,11 +1127,13 @@ Completion Commands
 @end defvar
 
 @defvar minibuffer-completion-confirm
-This variable determines whether Emacs asks for confirmation before
-exiting the minibuffer; @code{completing-read} binds this variable,
+This variable determines whether Emacs requires matching input or asks
+for confirmation before exiting the minibuffer;
+@code{completing-read} binds this variable,
 and the function @code{minibuffer-complete-and-exit} checks the value
 before exiting.  If the value is @code{nil}, confirmation is not
-required.  If the value is @code{confirm}, the user may exit with an
+required.  If the value is @code{t}, a match is required.
+If the value is @code{confirm}, the user may exit with an
 input that is not a valid completion alternative, but Emacs asks for
 confirmation.  If the value is @code{confirm-after-completion}, the
 user may exit with an input that is not a valid completion
diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el
index 65483d0813..e8ab558a19 100644
--- a/lisp/emacs-lisp/crm.el
+++ b/lisp/emacs-lisp/crm.el
@@ -252,8 +252,7 @@ completing-read-multiple
 	(let* ((minibuffer-completion-table #'crm--collection-fn)
 	       (minibuffer-completion-predicate predicate)
 	       ;; see completing_read in src/minibuf.c
-	       (minibuffer-completion-confirm
-		(unless (eq require-match t) require-match))
+	       (minibuffer-completion-confirm require-match)
 	       (crm-completion-table table)
 	       (map (if require-match
 			crm-local-must-match-map
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index a1a67e2330..52429fdf37 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -541,7 +541,7 @@ icomplete-exhibit
                           (icomplete--completion-table)
                           (icomplete--completion-predicate)
                           (if (window-minibuffer-p)
-                              (not minibuffer-completion-confirm)))))
+                              (eq minibuffer-completion-confirm t)))))
                  (buffer-undo-list t)
                  deactivate-mark)
             ;; Do nothing if while-no-input was aborted.
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 0589211877..56d3b259b4 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1386,7 +1386,10 @@ minibuffer-force-complete-and-exit
    (minibuffer-prompt-end) (point-max) #'exit-minibuffer
    ;; If the previous completion completed to an element which fails
    ;; test-completion, then we shouldn't exit, but that should be rare.
-   (lambda () (minibuffer-message "Incomplete"))))
+   (lambda ()
+     (if minibuffer-completion-predicate
+         (minibuffer-message "Incomplete")
+       (exit-minibuffer)))))
 
 (defun minibuffer-force-complete (&optional start end dont-cycle)
   "Complete the minibuffer to an exact match.
@@ -3734,8 +3737,7 @@ completing-read-default
 
   (let* ((minibuffer-completion-table collection)
          (minibuffer-completion-predicate predicate)
-         (minibuffer-completion-confirm (unless (eq require-match t)
-                                          require-match))
+         (minibuffer-completion-confirm require-match)
          (base-keymap (if require-match
                          minibuffer-local-must-match-map
                         minibuffer-local-completion-map))
diff --git a/src/minibuf.c b/src/minibuf.c
index c5f6145690..84e94c0627 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -2028,8 +2028,9 @@ syms_of_minibuf (void)
   Vminibuffer_completion_predicate = Qnil;
 
   DEFVAR_LISP ("minibuffer-completion-confirm", Vminibuffer_completion_confirm,
-	       doc: /* Whether to demand confirmation of completion before exiting minibuffer.
+	       doc: /* Whether matching completion or confirmation is required.
 If nil, confirmation is not required.
+If t, match is strictly required, can't finish input otherwise.
 If the value is `confirm', the user may exit with an input that is not
  a valid completion alternative, but Emacs asks for confirmation.
 If the value is `confirm-after-completion', the user may exit with an
-- 
2.20.1

>From c4130a620f913422c520c2ccf648eb409035e1d9 Mon Sep 17 00:00:00 2001
From: Dmitry Gutov <[email-masked]>
Date: Fri, 24 Jan 2020 01:06:17 +0300
Subject: [PATCH 2/2] Make M-j in fido-mode honor REQUIRE-MATCH=t

---
 lisp/icomplete.el | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 52429fdf37..5e674b769d 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -284,6 +284,13 @@ icomplete-fido-ret
           (t
            (icomplete-force-complete-and-exit)))))
 
+(defun icomplete-fido-exit ()
+  "Exit minibuffer properly honoring `minibuffer-completion-confirm'."
+  (interactive)
+  (if minibuffer-completion-confirm
+      (minibuffer-complete-and-exit)
+    (exit-minibuffer)))
+
 (defun icomplete-fido-backward-updir ()
   "Delete char before or go up directory, like `ido-mode'."
   (interactive)
@@ -299,7 +306,7 @@ icomplete-fido-mode-map
     (define-key map (kbd "RET") 'icomplete-fido-ret)
     (define-key map (kbd "C-m") 'icomplete-fido-ret)
     (define-key map (kbd "DEL") 'icomplete-fido-backward-updir)
-    (define-key map (kbd "M-j") 'exit-minibuffer)
+    (define-key map (kbd "M-j") 'icomplete-fido-exit)
     (define-key map (kbd "C-s") 'icomplete-forward-completions)
     (define-key map (kbd "C-r") 'icomplete-backward-completions)
     (define-key map (kbd "<right>") 'icomplete-forward-completions)
-- 
2.20.1