muffinmad / emacs-mini-frame

Show minibuffer in child frame on read-from-minibuffer
GNU General Public License v3.0
322 stars 20 forks source link

Compare with ivy-posframe #44

Open seagle0128 opened 3 years ago

seagle0128 commented 3 years ago

Hi, I tried this great package, but I am still wondering what's the difference between mini-frame and ivy-posframe. What's the advantage of mini-frame?

Thanks!

muffinmad commented 3 years ago

Hi! AFAIK ivy-posframe is targeted to show minibuffer in child frame for only ivy-based commands. mini-frame is targeted to show the minibuffer in child frame for all commands that reads from minibuffer, e.g. read-string.

Also mini-frame supports mouse clicks :)

BooAA commented 3 years ago

Under the hood, ivy-posframe use child frame only as a mirror to the original contents in minibuffer, which means your input focus still stays in the minibuffer of current frame. This method works will if you don't need any interaction with the child frame (no mouse clicks, no drags, no C-x 5 o to jump to other frame when you're doing completions, etc).

In contrast, mini-frame indeed creates another minibuffer-only frame to run commands inside. This will be a little slow (due to emacs internal display engine I think) but in my experience good enough as daily use. Also, now you get a flexible and general system to work with any completion framework. You can also use child frame to accept input for occur or yes-or-no if you like.

seagle0128 commented 3 years ago

Thanks for the reply, both!

So mini-frame has more features. I'd like use mini-frame instead of ivy-posframe according you described above. Then I tried and got some issues and questions. I hope it's more stable and faster.

I am planning to provide better experience with child frame in Centaur Emacs. Thanks for you patients!

e.g.

  1. It's slow to display with white flashing at the first startup. I think it's too slow to set background if using dark theme?
  2. Always blinking in swiper. This is annoying. (Update: set min-height to address this issue)
  3. Incompatible with shackle.
  4. No content displayed in child frame some times on Linux. I am suspecting it's related to other posframe packages.
  5. The width and height are fixed, while they are dynamic in ivy-posframe. I know this is not an issue, just difference.
  6. Is it possible display transient in mini-frame? I am using transient-posframe.
  7. Also, how to integrate which-key, hydra, org-agenda, etc.?

My configure is Centaur Emacs. Sorry for so many questions 😂 Appreciate to your patience in advance! Some screenshots are below.

emacs

emacs

BooAA commented 3 years ago

Try to answer some questions I can help:

It's slow to display with white flashing at the first startup. I think it's too slow to set background if using dark theme?

Try disable mini-frame-create-lazy, so that child frame will be created when Emacs boots. I use mini-frame-color-shift-step to get a slightly different background to help distinguishing contents in different frames.

Always blinking in swiper. This is annoying. (Update: set min-height to address this issue)

Setting the height frame parameter to number of displayed candidates + 1 should avoid some blinking.

The width and height are fixed, while they are dynamic in ivy-posframe.

I think mini-frame by default can be resized automatically. Check out mini-frame-resize.

Also, how to integrate which-key, hydra, org-agenda, etc.?

I don't use those packages so my comment may not be right. For compatibility issue with other packages, since different package assumes different use cases, timing and even windows layout when invoking minibuffer, you may have to put some of their APIs into mini-frame-ignore-commands or mini-frame-ignore-functions so that they can be executed correctly.

Currently I'm using selectrum (for vertical completion UI), marginalia (for annotation similar to ivy-rich) and consult (counsel equivalent), those packages works normally in mini-frame. For ivy, maybe ivy-posframe is still the first choice since the author has already put many efforts for integration with other packages.

seagle0128 commented 3 years ago

@BooAA Thanks for your answers! They are useful to me. I am trying to integrate and improve.

muffinmad commented 3 years ago

Alongside with great @BooAA answers, my few comments.

So mini-frame has more features. I'd like use mini-frame instead of ivy-posframe according you described above.

At the time I made mini-frame, I was an icomplete user. So ivy users had the ivy-posframe, but there were no posframe-based solution for vanilla minubuffer users. But then it turned out that mini-frame also works for ivy and other completions frameworks that uses minibuffer to show completion candidates.

posframe has the postition handlers, so one can set the child frame position by selection one of predefined options. mini-frame has no predefined options for frame positioning. You can configure mini-frame position by using frame parameters. I think it's more flexible.

Don't know what is "more features" is mean here.

  1. Always blinking in swiper. This is annoying. (Update: set min-height to address this issue)

Can confirm. I'll take a look into this.

  1. Incompatible with shackle.

Can you please provide more info on this?

  1. No content displayed in child frame some times on Linux. I am suspecting it's related to other posframe packages.

See https://github.com/muffinmad/emacs-mini-frame/issues/43

  1. The width and height are fixed, while they are dynamic in ivy-posframe. I know this is not an issue, just difference.

By default the mini-frame has fixed width but dynamical height.

  1. Is it possible display transient in mini-frame? I am using transient-posframe.
  2. Also, how to integrate which-key, hydra, org-agenda, etc.?

Those packages does not use minibuffer, so I dont know what mini-frame can do here.

About anzu-query-replace. This is related to anzu. It's not working with separate minibuffer frame by itself:

  1. emacs -Q --execute "(push '(minibuffer) default-frame-alist)"
  2. M-x package-initialize
  3. M-x anzu-query-replace
  4. Type q. You'll see the Error running timer: (wrong-type-argument window-live-p nil) error
seagle0128 commented 3 years ago

@muffinmad Thank you so much for your detailed answers! Now I completely understand the differences.

Regarding the shackle and anzu, I think they are the same issue, and your answer has covered.

seagle0128 commented 3 years ago

I made a recording today. It seems a little bit blinking on Ubunutu (Emacs 28, not gccemacs).

emacs

seagle0128 commented 3 years ago

I think the blinking issue is related to the background color and cleaning the contents. Similar issue as https://github.com/tumashu/ivy-posframe/pull/30 .

Another issue is the background color impacts the internal border color. If I set background-color in show-parameters, the internal-border-color doesn't work any more. Please take a look.

muffinmad commented 3 years ago

Well, the (setq mini-frame-resize 'grow-only) must solve the issue with swiper. But it doesn't works as expected and I'm currently investigate it. E.g.

  1. emacs -Q
  2. M-x package-initialize
  3. M-: (setq mini-frame-resize 'grow-only)
  4. M-x mini-frame-mode
  5. M-x swiper

I see one line height mini frame. But after M-x load-file <path-to-mini-frame-el> the M-x swiper works as expected.

seagle0128 commented 3 years ago

@muffinmad You may need to load a dark theme to test? I have the same issue on Windows. Actually (setq mini-frame-resize 'grow-only) doesn't help.

My configuration is :

(use-package mini-frame
    :preface
    (defun my-mini-frame-show-parameters ()
      `((left . 0.5)
        (top . ,(/ (frame-pixel-height) 2))
        (background-color . ,(face-foreground 'shadow nil t))
        (min-width . 80)
        (min-height . ,(if (member this-command
                                   '(swiper
                                     swiper-backward swiper-all
                                     swiper-isearch swiper-isearch-backward
                                     counsel-grep-or-swiper counsel-grep-or-swiper-backward))
                           16
                         1))
        (width . 0.8)
        (height . 1))))
    :init
    (setq mini-frame-create-lazy nil
          mini-frame-show-parameters #'my-mini-frame-show-parameters
          mini-frame-ignore-commands '("edebug-eval-expression" debugger-eval-expression))

    (mini-frame-mode 1))
bestlem commented 3 years ago

@muffinmad You say above "posframe has the postition handlers, so one can set the child frame position by selection one of predefined options. mini-frame has no predefined options for frame positioning. You can configure mini-frame position by using frame parameters. I think it's more flexible. " In ivy-posframe there is an easy set up by setting ivy-posframe-display-functions-alist (setq ivy-posframe-display-functions-alist '((swiper . ivy-display-function-fallback) (swiper-isearch . ivy-display-function-fallback) (complete-symbol . ivy-posframe-display-at-point) (t . ivy-posframe-display) ;; (t . ivy-display-function-fallback) ))

What is the way to make different commands have different behaving frames in mini-frame (I can manage with just at the top of frame and centre of frame but top of window would be useful as well.)

muffinmad commented 3 years ago

@bestlem Take a look at the mini-frame-show-parameters variable. It can be function, so you can create your own functions to return frame parameters based on e.g. this-command.

bestlem commented 3 years ago

Yes I have looked at that variable - I have set it and I put a message in my function and altered the left hand edge but what appears on the screen does not chnage - is there a working example anywhere?

muffinmad commented 3 years ago

@bestlem This changes mini-frame appearance for execute-extended-command (M-x) only:

(defun my/mini-frame-parameters ()
  "Set mini frame parameters based on `this-command'."
  (if (eq this-command 'execute-extended-command)
      '((top . .5)
        (left . .5)
        (width . .8))
    '((top . 0)
      (left . .5)
      (width . 1.0))))

(setq mini-frame-show-parameters 'my/mini-frame-parameters)