minad / vertico

:dizzy: vertico.el - VERTical Interactive COmpletion
GNU General Public License v3.0
1.48k stars 60 forks source link

Weird minibuffer issue in macos #250

Closed actondev closed 2 years ago

actondev commented 2 years ago

I think this is a more general macos issue, but since you know exactly what vertico does, I think it's a good place to start to figure out what is going on. In linux I never had this issue.

I have the issue when creating a second frame & have a shell open (or I think happens with any comint mode or term etc), the minibuffer might lose focus after it opens.

I attach a gif demonstrating the problem & all the instructions to replicate it minibuffer-bug

Emacs installation

brew tap railwaycat/emacsmacport
brew install emacs-mac --with-native-comp --with-imagemagick

emacs --version # GNU Emacs 28.1

To replicate the bug

;; emacs-minibuffer-bug.el

(package-initialize)

(require 'vertico)
(vertico-mode)
/opt/homebrew/opt/emacs-mac/Emacs.app/Contents/MacOS/Emacs -q --load ./emacs-minibuffer-bug.el

And then

minad commented 2 years ago

Interesting bug. Can you reproduce the issue without Vertico? For example try icomplete-vertical-mode instead. Maybe the bug even occurs with the plain minibuffer and default completion (if you don't enable any mode)?

I suggest you report this upstream to the maintainer of the particular Mac build you are using. Given that the bug is Mac-specific it is unlikely that this is due to Vertico.

Also Vertico doesn't really mess with the window or frame focus (just grep for window or frame in vertico.el). The only function which performs window manipulation is vertico--resize-window. You could try to comment out that function to see if the window resizing is the problem. But even if that would be the case, it would be an upstream bug.

Please let me know if these pointers are helpful to narrow this down further or if there is a need for further assistance. I cannot try to reproduce this myself. I don't use Mac.

hmelman commented 2 years ago

I can reproduce this on the macport using the railwaycat build. If I just do M-x shell, M-x make-frame and then M-x, the cursor is in the minibuffer. If I first load and enable vertico-mode (I didn't do package-install, I went to the veritco directory and loaded vertico.elc) I see the behavior described, the cursor is in the shell buffer not the minibuffer. I tried with icomplete-vertico-mode and it worked fine, I could not reproduce the problem with it.

minad commented 2 years ago

@hmelman Then we have to narrow down what part of Vertico causes the issue. The only part of Vertico which could cause this seems to be the minibuffer resizing in vertico--resize-window. Did you try commenting out this function (or advise override it with ignore)?

minad commented 2 years ago

I have found another discrepancy with Icomplete in the handling of pending input events. Icomplete has the line while-no-input-ignore-events and doesn't call input-pending-p. It is likely that this causes the issue. Can you please try this patch:

diff --git a/vertico.el b/vertico.el
index 878de3e..8c1b7b3 100644
--- a/vertico.el
+++ b/vertico.el
@@ -414,7 +414,8 @@ The function is configured by BY, BSIZE, BINDEX, BPRED and PRED."
                                        minibuffer-completion-table
                                        minibuffer-completion-predicate)))
     (pcase
-        (let ((vertico--metadata metadata))
+        (let ((vertico--metadata metadata)
+              (while-no-input-ignore-events '(selection-request)))
           ;; If Tramp is used, do not compute the candidates in an interruptible fashion,
           ;; since this will break the Tramp password and user name prompts (See #23).
           (if (and (eq 'file (vertico--metadata-get 'category))
@@ -600,7 +601,7 @@ The function is configured by BY, BSIZE, BINDEX, BPRED and PRED."
   (let* ((buffer-undo-list t) ;; Overlays affect point position and undo list!
          (pt (max 0 (- (point) (minibuffer-prompt-end))))
          (content (minibuffer-contents-no-properties)))
-    (unless (or (input-pending-p) (equal vertico--input (cons content pt)))
+    (unless (equal vertico--input (cons content pt))
       (vertico--update-candidates pt content))
     (vertico--prompt-selection)
     (vertico--display-count)

For background, the while-no-input-ignore-events line was removed in #150. See also the discussion in #115. The line has also been removed in Emacs 29, so maybe you can reproduce this with Icomplete on Emacs 29?

hmelman commented 2 years ago

Commenting out the one call to vertico--resize-window in vertico--display-candidates solves the problem.

The patch above does NOT solve the problem.

hmelman commented 2 years ago

FYI, in the recipe I've been calling M-x make-frame as instructed. But C-x 5 2 is bound to make-frame-command and if I use that instead there is no problem. I don't have time to dive into it now but it does look like make-frame-command just calls make-frame so I'm not sure what the difference is.

actondev commented 2 years ago

An update about this, I can actually replicate the issue with icomplete-mode, would be nice if @hmelman can replicate. At the last step, indeed with icomplete-mode when calling M-x the cursor is in the minibuffer, but when you start typing & the completion appears, the cursor jumps to the shell buffer.

Personally for now I've gotten around it by installing emacs-plus@29, which seems to work fine (& luckily no conflicts with my config)

Will post a gif as a reference in a bit

hmelman commented 2 years ago

I can NOT replicate with icomplete-mode. @actondev can you confirm it works fine with C-x 5 2 instead of make-frame?

FWIW, I prefer the macport over the ns port. If this looks like a macport issue I'd report it via M-x report-emacs-bug (it will go to Yamamoto-san).

actondev commented 2 years ago

And here is the gif. @hmelman with C-x 5 2 the same happens as well. What is the difference between the macport and the ns port? I'm at loss, I'm fairly new with macos.

Also thanks for the suggestion about report-emacs-bug, just sent my first emacs bug report! :)

minibuffer-bug2

hmelman commented 2 years ago

(Vanilla) GnuEmacs is ported to a variety of platforms, linux, windows, etc. One is a port to the mac but it's really to GNUstep, the GNU reimplementation of some mac libraries (based on NEXTStep the origins of macos). It's ok and it runs, but the integration with modern macos is limited in a few ways, both because macos isn't open source and the current emacs developers don't have a lot of macos experience.

Years ago there was a port of GnuEmacs to carbon, a compatibility library from apple. That has evolved into the macport. I think all the old carbon is gone and it uses relatively modern cocoa APIs. It has better integration with macos services and display, dictionary, and a few other things. The port is by Mitsuharu Yamamoto and is well maintained and kept up with current GnuEmacs code, but there are some licensing issues about folding it into vanilla GnuEmacs so that seems unlikely. Yamamoto-san just releases the source of the macport, railwaycat releases builds of it (and the source of some build scripts).

If you do report-emacs-bug from the macport it will go to Yamamoto-san and should be macport specific. If you want to file a bug with emacs, you should recreate the issue on the vanilla ns port and submit via that and the email address will send to the GnuEmacs maintainers.

hmelman commented 2 years ago

@hmelman with C-x 5 2 the same happens as well.

Interesting. So I tried again with vertico-mode and C-x 5 2 and it fails for me too (again, just loading vertico.elc not doing package-install which could load other things). If instead I use icomplete-vertical-mode and either C-x 5 2 or M-x make-frame it works fine.

macOS 12.4, GNU Emacs 28.1 (build 1, x86_64-apple-darwin20.6.0, Carbon Version 164 AppKit 2022.6) of 2022-05-03

minad commented 2 years ago

Btw there is some discussion on the emacs bug tracker about minibuffer selection and frames, see https://lists.gnu.org/archive/html/bug-gnu-emacs/2022-07/msg00128.html. So minibuffer selection in the presence of multiple frames generally seems brittle. Maybe that's related to what you are observing here?

hmelman commented 2 years ago

I think that discussion is more about having a separate minibuffer-only frame (a separate frame which is only the minibuffer which is shared for all other frames) which is a configuration option we're not using here. Certainly the issues there could overlap, but it seems unlikely to me.