Display ivy-posframe at the bottom center of a frame

What I want to “fix”

I recently switched from helm to ivy as my completion framework.

I am quite frankly pretty happy and now understand, why a bunch of people take this step as well. The switch was reasonably painless and since the Emacs community seams to favor ivy, one gets more help in most forums and help sites. At least that was my experience.

That is not to say, that I did find the solution to all of my issues though. I had to figure out the problem at hand by myself and I am happy with my solution as a non(-lisp)-developer.

Enough of the ramble. Now to the issue. I use ivy-posframe to be able to position the minibuffer with ivy where I want. Therein lies the problem. By default using the variable ivy-posframe-display-functions-alist, the ivy-posframe buffer can be positioned at top-center, center and bottom-left of the frame, but not at the bottom-center. Why the hell not!

Well some of you guys would be saying that ivy is at the bottom of the frame anyways, so why bother. I ll tell you why. I like the way it looks, and part of the reason why I am using Emacs is because of its ability to be changed to everyone’s liking – even if it is a seemingly minute detail like this.

Now that this has been cleared up. To the solution…

How I “fixed” it

Ivy-posframe is build “on top” of the package posframe and uses its “position handler” functions. Example:

;; value, that positions the `ivy-posframe' buffer at the top center of the frame.
;; this is a default definition in the package.
(defun ivy-posframe-display-at-frame-top-center (str)
  (ivy-posframe--display str #'posframe-poshandler-frame-top-center))

Note: posframe-poshandler-frame-top-center is defined in the parent package posframe.

… and with that:

;; with the above I can set the value.
(setq ivy-posframe-display-functions-alist
      '((t . ivy-posframe-display-at-frame-top-center)))

Now knowing all that I checked for a position handler in posframe for bottom-center. And luckily found it.

;; from the `posframe' package
(defun posframe-poshandler-frame-bottom-center (info)
  "Posframe's position handler.

Get a position which let posframe stay onto its parent-frame's
bottom center.  The structure of INFO can be found in docstring of
`posframe-show'."
  (cons (/ (- (plist-get info :parent-frame-width)
              (plist-get info :posframe-width))
           2)
        (- (plist-get info :parent-frame-height)
           (plist-get info :posframe-height)
           (plist-get info :mode-line-height)
           (plist-get info :minibuffer-height))))

From here, all I really need to do is define my own ivy-posframe display-function and then set it as the value for the ivy-posframe-display-functions-alist variable in my Emacs config.

Display function:

(defun my/ivy-posframe-display-at-frame-bottom-center (str)
  (ivy-posframe--display str #'posframe-poshandler-frame-bottom-center))

Set the value in the alist variable:

(setq ivy-posframe-display-functions-alist
      '((t . my/ivy-posframe-display-at-frame-bottom-center)))

Et voilà!