Subject: bug#78926: 30.1; find-file-read-only require-match inconsistency

From: Thierry Volpiatto <[email-masked]>
Date: Tue, 01 Jul 2025 12:38:12 +0000

Eli Zaretskii <[email-masked]> writes:

>> From: Thierry Volpiatto <[email-masked]>
>> Date: Mon, 30 Jun 2025 10:36:29 +0000
>> 
>> find-file-read-only is allowing confirmation to exit with a non existing
>> file with `confirm-nonexistent-file-or-buffer`, but when the
>> filename is selected it calls `find-file--read-only` which itself prevent
>> exiting with a non existing file.
>> 
>> Did I miss something or is it a bug?
>
> Sorry, could you please elaborate?  What exactly did you do and what
> did you see?
>
> I tried:
>
>   emacs -Q
>   M-x set-variable RET confirm-nonexistent-file-or-buffer RET nil RET
>   M-x find-file-read-only RET foobar RET

> and Emacs signaled an error saying that the file does not exist.

I meant with the default value of confirm-nonexistent-file-or-buffer.
It's surprizing that after pressing RET I have a minibuffer-message
saying [confirm] and then when I hit RET again I have the error you
mentioned.
It would be better to use a [no match] message preventing exiting
minibuffer in such case, however if you do this (i.e. require-match ==
t) you prevent exiting with a wildcard. I tried this patch that work as
I expect (which is maybe not what you or others expect):

    index 04a212b9bca..8cb93c90351 100644
    --- a/lisp/files.el
    +++ b/lisp/files.el
    @@ -2072,23 +2072,28 @@ file names with wildcards."
          (current-buffer)))
     
     (defun find-file--read-only (fun filename wildcards)
    -  (unless (or (and wildcards find-file-wildcards
    -		   (not (file-name-quoted-p filename))
    -		   (string-match "[[*?]" filename))
    -	      (file-exists-p filename))
    -    (error "%s does not exist" filename))
    +  ;; On interactive calls WILDCARDS is always non nil. 
    +  (let ((find-file-wildcards (and wildcards find-file-wildcards)))
    +    (unless (find-file--read-only-require-match filename)
    +      (error "%s does not exist" filename)))
       (let ((value (funcall fun filename wildcards)))
         (mapc (lambda (b) (with-current-buffer b (read-only-mode 1)))
     	  (if (listp value) value (list value)))
         value))
     
    +(defun find-file--read-only-require-match (input)
    +  (or (and find-file-wildcards
    +           (not (file-name-quoted-p input))
    +	   (string-match "[[*?]" input))
    +      (file-exists-p input)))
    +
     (defun find-file-read-only (filename &optional wildcards)
       "Edit file FILENAME but don't allow changes.
     Like \\[find-file], but marks buffer as read-only.
     Use \\[read-only-mode] to permit editing."
       (interactive
        (find-file-read-args "Find file read-only: "
    -                        (confirm-nonexistent-file-or-buffer)))
    +                        #'find-file--read-only-require-match))
       (find-file--read-only #'find-file filename wildcards))
     
     (defun find-file-read-only-other-window (filename &optional wildcards)

The problem is that this patch doesn't ask anymore for confirmation when
input is a wildcard, perhaps a new feature would be to enhance the
behavior of require-match used as a function.  Currently the function
can either return nil or t, it could return in addition 'confirm and
in this case send a minibuffer message [confirm], on next RET hit it
would exit.

-- 
Thierry