Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mini-frame-mode only displays a cut-off first candidate before typing #169

Closed
terlar opened this issue Aug 8, 2020 · 51 comments
Closed

Comments

@terlar
Copy link

terlar commented Aug 8, 2020

Thank you for the kind help @clemera with your latest changes at least the thing pops up. Here are the issues I am seeing. Before typing anything it will only show a cut-off version of the default candidate. The frame does not seem to resize when there is only one single candidate (not sure if it should). I haven't used either of these packages before, just trying them out.

Nothing typed:
Screenshot from 2020-08-08 21-32-33
One character typed:
Screenshot from 2020-08-08 21-33-11
Only completion:
Screenshot from 2020-08-08 21-33-46

Every other time the menu is invoked you don't see any candidates:
Screenshot from 2020-08-08 21-39-56

PS.
I am applying the config suggested in the Wiki.

(setf (alist-get
       'height mini-frame-show-parameters)
      (1+ selectrum-num-candidates-displayed))

As well as:

(custom-set-variables
 '(mini-frame-show-parameters
   '((top . 10)
     (width . 0.7)
     (left . 0.5))))
@terlar
Copy link
Author

terlar commented Aug 8, 2020

I see that this behavior happens with fido/ivy/icomplete as well, so guess the issue mostly lies with mini-frame. Feel free to close.

@clemera
Copy link
Collaborator

clemera commented Aug 8, 2020

Hm, maybe it's something else on your side I can't reproduce this.

@terlar
Copy link
Author

terlar commented Aug 8, 2020

It almost works correct with (setq resize-mini-frames t). Then all issues disappear except that it works every other time.

It might be my Emacs version:

GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.21, cairo version 1.16.0)

@clemera
Copy link
Collaborator

clemera commented Aug 8, 2020

Ah, then mini-frame might not work correctly with Emacs 28, yet.

@terlar
Copy link
Author

terlar commented Aug 8, 2020

Yeah, seems so, thank you once again!

@muffinmad
Copy link

Ah, then mini-frame might not work correctly with Emacs 28, yet.

Why? I'm using mini-frame-mode with Emacs 28 and see no issues. But I'm using icomplete-mode.

Actually I'm surprised that mini-frame doesn't work for you. Sorry :) muffinmad/emacs-mini-frame#17 brings me here. I'll take a look on how to make mini-frame work nicely with selectrum.

@clemera
Copy link
Collaborator

clemera commented Aug 28, 2020

Why? I'm using mini-frame-mode with Emacs 28 and see no issues. But I'm using icomplete-mode.

I thought that to be the case since with my quick tests in Emacs 27 I did not see the issues @terlar desribed. I'm happy to help if you find anything that would improve the support of emacs-mini-frame in selectrum.

@muffinmad
Copy link

muffinmad commented Aug 28, 2020

@clemera

Here is receipt to reproduce the issue with mini frame without emacs-mini-frame package:

  1. emacs -Q --eval "(setq default-frame-alist '((minibuffer . nil)))"
  2. M-x package-initialize
  3. M-x selectrum-mode
  4. M-: (setq resize-mini-frames t)
  5. M-x

The mini frame doesn't show completion list unless some input is provided.

Maybe you can find solution much quicker than me.

@clemera
Copy link
Collaborator

clemera commented Aug 28, 2020

Thank you, I can reproduce that. I'm currently clueless why it doesn't display the candidates initially.

@gcv
Copy link

gcv commented Oct 3, 2020

Any new ideas about this problem?

@clemera
Copy link
Collaborator

clemera commented Oct 4, 2020

Unfortunately not, someone would have to determine the problem that causes this. I'm not using this myself but I would be happy to help with the fix as soon we know what to fix.

@david-vicente
Copy link

The issue also happens with C-x b, but for some reason C-x C-f works correctly.

@muffinmad
Copy link

muffinmad commented Oct 16, 2020 via email

@clemera
Copy link
Collaborator

clemera commented Oct 16, 2020

I just tried to investigate this a bit more and discovered you get the same display problems with icomplete-vertical. I suspect there is some display bug at play. A workaround could be to use before-string instead of after-string and display the input line below the candidates instead of above, a quick test on my side indicated this could work.

@clemera
Copy link
Collaborator

clemera commented Oct 16, 2020

@muffinmad Would it be possible to specify another buffer whose contents should be used for display in the frame?

@clemera
Copy link
Collaborator

clemera commented Oct 16, 2020

I just tried maple-minibuffer which seems to work fine without any additional setup. I haven't looked at the differences to mini-frame-mode, though.

@muffinmad
Copy link

I just tried maple-minibuffer which seems to work fine without any additional setup. I haven't looked at the differences to mini-frame-mode, though.

Because maple-minibuffer uses fixed frame height by default. It is possible (with additional setup) to make mini-frame to show fixed-height frame too.

My point was to make selectrum work in this scenario: #169 (comment). If there is some Emacs bug that leads to such behavior, let's spot it and fix on the Emacs side.

Btw, with ivy the candidates list is visible even if there are no input. Just replace step 3 with M-x ivy-mode in that receipt.

@muffinmad Would it be possible to specify another buffer whose contents should be used for display in the frame?

Sounds like a job for the posframe package :)

@clemera
Copy link
Collaborator

clemera commented Oct 19, 2020

Because maple-minibuffer uses fixed frame height by default. It is possible (with additional setup) to make mini-frame to show fixed-height frame too.

My point was to make selectrum work in this scenario: #169 (comment). If there is some Emacs bug that leads to such behavior, let's spot it and fix on the Emacs side.

Btw, with ivy the candidates list is visible even if there are no input. Just replace step 3 with M-x ivy-mode in that receipt.

If there is no minibuffer input or the last input character in the buffer is white space the after-string overlay does not display (when it begins with a newline) in the mini frame. It seems this is the case regardless if the frame height is set to static or not. The frames spawned by maple minibuffer don't seem to have this problem, I don't know the reason for that. Ivy doesn't use an overlay to display its candidates so it isn't affected by this. Icomplete also uses an overlay so with icomplete-vertical you get the same display problem.

Sounds like a job for the posframe package :)

I agree, so to fix the problem for the mini-frame case we need to figure out the reason for not displaying the after-string overlay in the case described above.

@muffinmad
Copy link

If there is no minibuffer input or the last input character in the buffer is white space the after-string overlay does not display (when it begins with a newline) in the mini frame. It seems this is the case regardless if the frame height is set to static or not. The frames spawned by maple minibuffer don't seem to have this problem, I don't know the reason for that.

To make mini-frame show selectrum candidates with empty input (like maple-minibuffer):

(setq mini-frame-show-parameters
      '((left . 0.5)
        (top . 0)
        (width . 1.0)
        ;; set height
        (height . 10)))
;; disable mini-frame-resize
(setq mini-frame-resize nil)

To make maple-minibufer not show selectrum candidates:

(setq maple-minibuffer:height 1)

and turn maple-minibuffer-mode off and on.

Ivy doesn't use an overlay to display its candidates so it isn't affected by this. Icomplete also uses an overlay so with icomplete-vertical you get the same display problem.

I agree, so to fix the problem for the mini-frame case we need to figure out the reason for not displaying the after-string overlay in the case described above.

Can you provide more compact receipt to reproduce the bug, please? By "more compact" I mean without the need to install additional packages.

Also can you report the bug to the Emacs developers?

@clemera
Copy link
Collaborator

clemera commented Oct 19, 2020

I'm not dealing with frames usually so I'm not very experienced with their behaviour/settings. I can indeed see the candidates when setting mini-frame-resize to nil. Now I'm wondering what this setting usually achieves. I don't see any behaviour change when setting it to t with ivy, should the frame dynamically resize during input or something like that? This doesn't seem to happen even with resize-mini-frames (which was mentioned earlier) set to t (with Emacs 27.1). When I filter down to fewer candidates the frame keeps its initial size.

Can you provide more compact receipt to reproduce the bug, please? By "more compact" I mean without the need to install additional packages.

I will try to come up with a minimal example which demonstrates the display problem.

@clemera
Copy link
Collaborator

clemera commented Oct 19, 2020

Here is a minimal example, thanks for your previous recipe which helped me creating it:

  1. emacs -Q --eval "(setq default-frame-alist '((minibuffer . nil)))"
  2. eval-buffer with following code.
(setq resize-mini-frames t)

(defvar ov (make-overlay (point-min) (point-min) nil t t))

(minibuffer-with-setup-hook
    (lambda ()
      (move-overlay ov
		    (point-max)
		    (point-max)
		    (current-buffer))
      (overlay-put ov 'after-string "\nHey there, I'm hidden initially and will hide again after any space in the input"))
  (read-string "Hi? "))
  1. Start typing

Initially and after any space the overlay text is hidden.

@clemera
Copy link
Collaborator

clemera commented Oct 19, 2020

Also can you report the bug to the Emacs developers?

Done

@muffinmad
Copy link

I'm not dealing with frames usually so I'm not very experienced with their behaviour/settings. I can indeed see the candidates when setting mini-frame-resize to nil. Now I'm wondering what this setting usually achieves. I don't see any behaviour change when setting it to t with ivy, should the frame dynamically resize during input or something like that? This doesn't seem to happen even with resize-mini-frames (which was mentioned earlier) set to t (with Emacs 27.1). When I filter down to fewer candidates the frame keeps its initial size.

The resize-mini-frames option is overriden with the mini-frame-resize option when mini-frame is showed. By default mini-frame-resize is t, which means to resize mini-frame. And I see that frame is properly resized with ivy on Emacs 27 and 28:

  1. emacs -Q
  2. M-x package-initialize
  3. M-x ivy-mode
  4. M-x mini-frame-mode
  5. M-x mini-

At this point the height of the mini-frame is 2 lines: prompt and mini-frame-mode completion item.

Also can you report the bug to the Emacs developers?

Done

Thank you!

@clemera
Copy link
Collaborator

clemera commented Oct 19, 2020

At this point the height of the mini-frame is 2 lines: prompt and mini-frame-mode completion item.

This isn't the case for me. My guess is that this is gnomes fault, I remembered to stumble across dynamic resize problems with posframe in the past, see here.

For anyone scrolling this thread for a solution: To work around the problem configure (setq mini-frame-resize nil).

@clemera
Copy link
Collaborator

clemera commented Oct 20, 2020

After discussion on the mailing list I have another workaround that can be used until an official solution gets released:

(define-advice fit-frame-to-buffer (:around (f &rest args) dont-skip-ws-for-mini-frame)
  (cl-letf* ((orig (symbol-function #'window-text-pixel-size))
            ((symbol-function #'window-text-pixel-size)
             (lambda (win from to &rest args)
               (apply orig
                      (append (list win from 
                                    (if (and (window-minibuffer-p win)
                                             (frame-root-window-p win)
                                             (eq t to))
                                        nil
                                      to))
                              args)))))
    (apply f args)))

With this you should be able to get it working with mini-frame-resize set to t, as well. If no problem is left I will update the wiki accordingly and we can close the issue.

@clemera
Copy link
Collaborator

clemera commented Oct 21, 2020

@terlar Does the above workaround solve your issue? Looking back your report seems to describe a slightly different behaviour than what I have seen.

@terlar
Copy link
Author

terlar commented Oct 21, 2020

I will have another look.

@nuance
Copy link

nuance commented Oct 24, 2020

@clemera Adding that advice seems to fix the size of the mini-frame to ~25 rows or so for me, meaning it doesn't shrink as the candidate set is narrowed.

My mini-frame usage is configured like:

(use-package mini-frame
  :straight t
  :custom
  ((mini-frame-ignore-commands '(eval-expression "edebug-eval-expression" debugger-eval-expression "^phi-"))
   (mini-frame-show-parameters '((top . 10) (width . 0.7) (left . 0.5))))
  :config (mini-frame-mode))

(see https://github.com/nuance/dotfiles/blob/master/emacs.d/init.org for my emacs config / https://github.com/nuance/dotfiles/blob/master/straight-package-versions.el for package versions)

@clemera
Copy link
Collaborator

clemera commented Oct 24, 2020

@nuance Thanks, I can't easily test this because as mentioned earlier dynamic resize of child frames does not work for me under gnome at all. But if I don't specify a height I experience something similar to what @terlar described in that every other time it shows only a single line frame. This sounds like there is an additional issue which is different from the one fixed by the advice. @muffinmad do you have the same problem?

There seems to be no issue if you specify a height, though as I said I can't test if the dynamic shrinking is working with the child frames mini-frame-mode uses.

@clemera
Copy link
Collaborator

clemera commented Oct 24, 2020

@nuance Do you still have issues if you specify a height in mini-frame-show-parameters?

@nuance
Copy link

nuance commented Oct 24, 2020

@clemera different problem. with the following snippet, I only ever see the input line of the minibuffer (eg "18 Switch to buffer: " if there are 18 buffers, typing input just reduces the match count number but doesn't display candidates)

     (use-package mini-frame
       :straight t
       :custom
       ((mini-frame-ignore-commands '(eval-expression "edebug-eval-expression" debugger-eval-expression "^phi-"))
        (mini-frame-show-parameters '((top . 10) (width . 0.7) (left . 0.5) (height . 1))))
       :init
       (define-advice fit-frame-to-buffer (:around (f &rest args) dont-skip-ws-for-mini-frame)
         (cl-letf (((symbol-function #'window-text-pixel-size)
                    (lambda (win from to &rest args)
                      (apply #'window-text-pixel-size
                             (append (list win from (if (window-minibuffer-p win) nil to) args))))))
           (apply f args)))
       :config (mini-frame-mode))

@clemera
Copy link
Collaborator

clemera commented Oct 24, 2020

@nuance I think you misinterpreted the meaning of the height parameter which is the number of lines. A value of 1 giving you a single line is correct in this case.

@nuance
Copy link

nuance commented Oct 24, 2020

@clemera Ahh, good catch. Setting it to 25 yields the behavior from before (eg same as if height is unset) - the mini-frame is fixed size regardless of number of candidates; eg, it doesn't seem to respect mini-frame-resize.

@clemera
Copy link
Collaborator

clemera commented Oct 24, 2020

Okay, that is the behaviour I get, too. I thought it was Gnomes fault, do you use it?

@nuance
Copy link

nuance commented Oct 24, 2020

Nope, this is on macOS. I'm running something close to the tip of the native-comp branch, fwiw (I think the sha is 3be93390fb6680d1e0c3256af72c86635a9eb327)

@clemera
Copy link
Collaborator

clemera commented Oct 24, 2020

Okay, thanks. I don't know if this is related to selectrum maybe @muffinmad has some more clues.

@muffinmad
Copy link

@nuance Thanks, I can't easily test this because as mentioned earlier dynamic resize of child frames does not work for me under gnome at all. But if I don't specify a height I experience something similar to what @terlar described in that every other time it shows only a single line frame. This sounds like there is an additional issue which is different from the one fixed by the advice. @muffinmad do you have the same problem?

No. In emacs -Q:

  1. Add advice from mini-frame-mode only displays a cut-off first candidate before typing #169 (comment)
  2. (setq mini-frame-show-parameters '((top . 10) (width . 0.7) (left . 0.5)))
  3. M-x mini-frame-mode
  4. M-x selectrum-mode
  5. M-x

Miniframe shows 10 candidates and changes the size once the candidates list changed.

@nuance Your advice (#169 (comment)) is slightly different. Can you please test it with the #169 (comment)? Also please test it on master branch of Emacs.

@nuance
Copy link

nuance commented Oct 25, 2020

@muffinmad Appears to work now! Not sure how I ended up with a different set of advice. For reference, my mini-frame use-package now looks like:

     (use-package mini-frame
       :straight t
       :custom
       ((mini-frame-ignore-commands '(eval-expression "edebug-eval-expression" debugger-eval-expression "^phi-"))
        (mini-frame-show-parameters '((top . 10) (width . 0.7) (left . 0.5) (height . 25))))
       :init
       (define-advice fit-frame-to-buffer (:around (f &rest args) dont-skip-ws-for-mini-frame)
         (cl-letf* ((orig (symbol-function #'window-text-pixel-size))
                    ((symbol-function #'window-text-pixel-size)
                     (lambda (win from to &rest args)
                       (apply orig
                              (append (list win from
                                            (if (and (window-minibuffer-p win)
                                                     (frame-root-window-p win)
                                                     (eq t to))
                                                nil
                                              to))
                                      args)))))
           (apply f args)))
       :config (mini-frame-mode))

@clemera
Copy link
Collaborator

clemera commented Oct 25, 2020

@muffinmad Thanks for catching that, I missed that the advice was different! Great, that it works!

@clemera
Copy link
Collaborator

clemera commented Oct 26, 2020

To summarize the insights in this thread:

  • mini-frame-mode dynamic resize doesn't work with gnome
  • you need to specify a height in mini-frame-show-parameters
  • until bug#44080 is fixed in Emacs the following advice works around the problem:
(define-advice fit-frame-to-buffer (:around (f &rest args) dont-skip-ws-for-mini-frame)
  (cl-letf* ((orig (symbol-function #'window-text-pixel-size))
            ((symbol-function #'window-text-pixel-size)
             (lambda (win from to &rest args)
               (apply orig
                      (append (list win from 
                                    (if (and (window-minibuffer-p win)
                                             (frame-root-window-p win)
                                             (eq t to))
                                        nil
                                      to))
                              args)))))
    (apply f args)))

@terlar Taking these into account the issue seems to be fixed as far as selectrum is concerned, can you confirm?

@clemera clemera added the waiting on response Needs more info or follow-up, will be closed after 90 days if no response label Oct 26, 2020
@terlar
Copy link
Author

terlar commented Oct 27, 2020

@clemera Yes, I can confirm. With the advice it works (with no height every other execution). However also setting the height in mini-frame-show-parameters makes it work every time (I'm using gnome).

@clemera
Copy link
Collaborator

clemera commented Oct 27, 2020

However also setting the height in mini-frame-show-parameters makes it work every time (I'm using gnome).

Thanks! Does the frame also dynamically shrink when you filter down to fewer candidates? What gnome version are you using?

@terlar
Copy link
Author

terlar commented Oct 27, 2020

I'm on GNOME Shell 3.36.5.

On some further tries it does not shrink and when not using a fixed height it stays at the height when the frame was initiated.
Also if you start typing quickly the height will be affected and it might be less than 10 items (if that is the default). If I start typing before the height is set it can get stuck in very small sizes (this is without the height configuration).

@clemera
Copy link
Collaborator

clemera commented Oct 27, 2020

On some further tries it does not shrink and when not using a fixed height it stays at the height when the frame was initiated.
Also if you start typing quickly the height will be affected and it might be less than 10 items (if that is the default). If I start typing before the height is set it can get stuck in very small sizes (this is without the height configuration).

Okay, thanks this is because of the Gnome issue I was talking about, so maybe this should be noted in the mini-frame-mode README (@muffinmad)?. Thank you all for your helping tracking these things down! I have updated the wiki accordingly. Is anything else left?

@muffinmad
Copy link

Okay, thanks this is because of the Gnome issue I was talking about, so maybe this should be noted in the mini-frame-mode README (@muffinmad)?.

Absolutely.

@muffinmad
Copy link

To summarize the insights in this thread:

  • mini-frame-mode dynamic resize doesn't work with gnome

Adding (setq x-gtk-resize-child-frames 'resize-mode) to init file will solve child frame resize issue.

@clemera
Copy link
Collaborator

clemera commented Nov 1, 2020

Nice! Thanks for discovering that option, I can confirm that it works!

@nuance
Copy link

nuance commented Nov 1, 2020 via email

@muffinmad
Copy link

Nice! Thanks for discovering that option, I can confirm that it works!

Thanks to @dgutov for pointing out to that option!

@muffinmad
Copy link

@nuance

Is it meant to be a maximum height or minimum height?

It is the initial height. Doesn't make much sense if the mini-frame-resize is set though may reduce frame "flickering" due to resize.

Is there any chance the requirement to set a height could be removed if auto resize is true?

Yes.

@clemera
Copy link
Collaborator

clemera commented Nov 2, 2020

Very good! I have updated the wiki, too. Thank you all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

7 participants