GNU-devel ELPA - frog-menu


Quickly pick items from ad hoc menus
frog-menu- (.sig), 2024-Mar-31, 120 KiB
Clemens Radermacher <>
Atom feed
Browse ELPA's repository
CGit or Gitweb

To install this package from Emacs, use package-install or list-packages.

Full description

<p> <a href=""><img alt="GNU ELPA" src="></a> <a href=""><img alt="Travis CI" src="></a> </p>

1. Description

This package lets you quickly pick strings from ad hoc menus. Just like a frog would catch a fly. The menu is built "on the fly" from a collection of strings. It's presented to the user to choose one of them by pressing a single key. One example where this kind of menu is useful are spelling correction suggestions:


The user can specify a prompt and additional action keys as you can see in the bottom of the menu. Usage in the terminal is also supported:


Inspired by ace-popup-menu.

2. Example

To invoke the menu users can call frog-menu-read. How items are displayed and choosen depends on frog-menu-type. For graphical displays the type avy-posframe uses avy and posframe. In terminals the type avy-side-window is used. The implemented handler functions can be used as reference if you want to define your own frog-menu-type.

Here is an example how you would invoke a frog menu:

(frog-menu-read "Choose a string"
		'("a" "list" "of strings"))

It is also possible to define additional action keys (as shown in the screenshot). Here is an example how you could use frog-menu-read to implement a flyspell-correct-interface:

(require 'flyspell-correct)

(defun frog-menu-flyspell-correct (candidates word)
  "Run `frog-menu-read' for the given CANDIDATES.

List of CANDIDATES is given by flyspell for the WORD.

Return selected word to use as a replacement or a tuple
of (command . word) to be used by `flyspell-do-correct'."
  (let* ((corrects (if flyspell-sort-corrections
		       (sort candidates 'string<)
	 (actions `(("C-s" "Save word"         (save    . ,word))
		    ("C-a" "Accept (session)"  (session . ,word))
		    ("C-b" "Accept (buffer)"   (buffer  . ,word))
		    ("C-c" "Skip"              (skip    . ,word))))
	 (prompt   (format "Dictionary: [%s]"  (or ispell-local-dictionary
	 (res      (frog-menu-read prompt corrects actions)))
    (unless res
      (error "Quit"))

(setq flyspell-correct-interface #'frog-menu-flyspell-correct)

Afterwards calling M-x flyspell-correct-wrapper will prompt you with a frog-menu.

And here is yet another example I use to navigate the menubar:

(require 'tmm)

(defun tmm-init-km-list+ (menu)
  (setq tmm-km-list nil)
  (map-keymap (lambda (k v) (tmm-get-keymap (cons k v))) menu)
  (setq tmm-km-list (nreverse tmm-km-list))
  ;; filter unenabled items
  (setq tmm-km-list
	 (lambda (item)
	   (eq (cddr item) 'ignore)) tmm-km-list)))

(defun frog-tmm-prompt (menu &optional entry)
  "Adapted from `counsel-tmm-prompt'."
  (let (out
    (setq tmm-km-list (tmm-init-km-list+ menu))
    (setq out (or entry (frog-menu-read "Menu: " (mapcar #'car tmm-km-list))))
    (setq choice (cdr (assoc out tmm-km-list)))
    (setq chosen-string (car choice))
    (setq choice (cdr choice))
    (cond ((keymapp choice)
	   (frog-tmm-prompt choice))
	  ((and choice chosen-string)
	   (setq last-command-event chosen-string)
	   (call-interactively choice)))))

(defun frog-tmm (&optional entry)
  "Adapted from `counsel-tmm'."
  (run-hooks 'menu-bar-update-hook)
  (setq tmm-table-undef nil)
  (frog-tmm-prompt (tmm-get-keybind [menu-bar]) entry))

(defun frog-tmm-mode ()
  "Adapted from `counsel-tmm'."
  (frog-tmm mode-name))

Old versions

frog-menu- KiB