Create a Leader Key for macOS with Emacs

A Leader Key popup for the OS, using emacs.

commander.el demo

Leader Key is a great concept in Emacs and Vim. There's an awesome project simply called LeaderKey for macOS. It is very useful and powerful, I use it every day since I found it. Well, it's time to replace it with Emacs.

I created commander.el, not published yet, just an experiment, using the package transient (can you still call it a package if it's already built into Emacs?). With the help of M-x.app, we can create something similar but more Emacsy. I will just put the code here, before it's package-worthy. I would love to hear some good ideas about this. Please send me an email and tell me about it.

(defun launch-app (name)
  "Launch macOS applicatjkjion NAME."
  (call-process "open" nil nil nil "-a" name))
 
(transient-define-prefix my/transient ()
  "My Commander"
  [["Commands"
    ("m" "Music Play/Pause" my/music-play-pause)]
   ["Apps"
    ("b" "Chrome"  (lambda () (interactive) (launch-app "Google Chrome")))
    ("e" "Emacs"   (lambda () (interactive) (launch-app "Emacs")))
    ("t" "Ghostty" (lambda () (interactive) (launch-app "Ghostty")))
    ("f" "Finder"  (lambda () (interactive) (launch-app "Finder")))]
   [("q" "quit" transient-quit-all)]])
 
(defun my/music-play-pause ()
  "Toggle Apple Music playback state."
  (interactive)
  (let ((exit-code
         (call-process
          "osascript" nil nil nil
          "-e" "tell application \"Music\" to playpause")))
    (unless (eq exit-code 0)
      (message "Failed to toggle Music playback (exit %s)" exit-code))))
 
(defun my/transient-display-buffer-focus (buffer alist)
  "Display transient BUFFER and force focus to its popup frame."
  (let ((win (display-buffer-pop-up-frame buffer alist)))
    (when (window-live-p win)
      (let ((frame (window-frame win)))
        ;; Pin popup to bottom-left of the monitor workarea.
        (let* ((attrs (frame-monitor-attributes frame))
               (work (alist-get 'workarea attrs))
               (wx (or (nth 0 work) 0))
               (wy (or (nth 1 work) 0))
               (wh (or (nth 3 work) (display-pixel-height)))
               (fh (if (fboundp 'frame-outer-height)
                       (frame-outer-height frame)
                     (frame-pixel-height frame))))
          (set-frame-position frame wx (max wy (- (+ wy wh) fh))))
        (when (and (eq system-type 'darwin) (fboundp 'ns-do-applescript))
          (ignore-errors
            (ns-do-applescript "tell application \"Emacs\" to activate")))
        (select-frame-set-input-focus frame)
        (raise-frame frame)))
    win))
 
(defun my/transient-launch ()
  (interactive)
  (let ((transient-display-buffer-action
         '(my/transient-display-buffer-focus
           (pop-up-frame-parameters
            (name . "transient")
            (width . 80)
            (height . 20)
            (minibuffer . nil)
            (tool-bar-lines . 0)
            (menu-bar-lines . 0)))))
    (my/transient)))
← Back to Writing