Function: tmm-prompt
tmm-prompt is an autoloaded and byte-compiled function defined in
tmm.el.gz.
Signature
(tmm-prompt MENU &optional IN-POPUP DEFAULT-ITEM NO-EXECUTE PATH)
Documentation
Text-mode emulation of calling the bindings in keymap.
Creates a text-mode menu of possible choices. You can access the elements
in the menu in two ways:
*) via history mechanism from minibuffer;
*) Or via completion-buffer that is automatically shown.
The last alternative is currently a hack, you cannot use mouse reliably.
MENU is like the MENU argument to x-popup-menu: either a
keymap or an alist of alists.
DEFAULT-ITEM, if non-nil, specifies an initial default choice.
Its value should be an event that has a binding in MENU.
NO-EXECUTE, if non-nil, means to return the command the user selects
instead of executing it.
PATH is a stack that keeps track of your path through sub-menus. It
is used to go back through those sub-menus.
Source Code
;; Defined in /usr/src/emacs/lisp/tmm.el.gz
;;;###autoload
(defun tmm-prompt (menu &optional in-popup default-item no-execute path)
"Text-mode emulation of calling the bindings in keymap.
Creates a text-mode menu of possible choices. You can access the elements
in the menu in two ways:
*) via history mechanism from minibuffer;
*) Or via completion-buffer that is automatically shown.
The last alternative is currently a hack, you cannot use mouse reliably.
MENU is like the MENU argument to `x-popup-menu': either a
keymap or an alist of alists.
DEFAULT-ITEM, if non-nil, specifies an initial default choice.
Its value should be an event that has a binding in MENU.
NO-EXECUTE, if non-nil, means to return the command the user selects
instead of executing it.
PATH is a stack that keeps track of your path through sub-menus. It
is used to go back through those sub-menus."
;; If the optional argument IN-POPUP is t,
;; then MENU is an alist of elements of the form (STRING . VALUE).
;; That is used for recursive calls only.
(let ((gl-str "Menu bar") ;; The menu bar itself is not a menu keymap
; so it doesn't have a name.
tmm-km-list out history-len tmm-table-undef tmm-c-prompt
tmm-old-mb-map tmm-short-cuts
chosen-string choice
(not-menu (not (keymapp menu))))
(run-hooks 'activate-menubar-hook)
;; Compute tmm-km-list from MENU.
;; tmm-km-list is an alist of (STRING . MEANING).
;; It has no other elements.
;; The order of elements in tmm-km-list is the order of the menu bar.
(if (not not-menu)
(map-keymap (lambda (k v) (tmm-get-keymap (cons k v))) menu)
(dolist (elt menu)
(cond
((stringp elt) (setq gl-str elt))
((listp elt) (tmm-get-keymap elt not-menu))
((vectorp elt)
(dotimes (i (length elt))
(tmm-get-keymap (cons i (aref elt i)) not-menu))))))
;; Choose an element of tmm-km-list; put it in choice.
(if (and not-menu (= 1 (length tmm-km-list)))
;; If this is the top-level of an x-popup-menu menu,
;; and there is just one pane, choose that one silently.
;; This way we only ask the user one question,
;; for which element of that pane.
(setq choice (cdr (car tmm-km-list)))
(unless tmm-km-list
(error "Empty menu reached"))
(and tmm-km-list
(let ((index-of-default 0))
(setq tmm-km-list
(if tmm-mid-prompt
(tmm-add-shortcuts tmm-km-list)
;; tmm-add-shortcuts reverses tmm-km-list internally.
(reverse tmm-km-list)))
;; Find the default item's index within the menu bar.
;; We use this to decide the initial minibuffer contents
;; and initial history position.
(if default-item
(let ((tail menu) visible)
(while (and tail
(not (eq (car-safe (car tail)) default-item)))
;; Be careful to count only the elements of MENU
;; that actually constitute menu bar items.
(if (and (consp (car tail))
(or (stringp (car-safe (cdr (car tail))))
(and
(eq (car-safe (cdr (car tail))) 'menu-item)
(progn
(setq visible
(plist-get
(nthcdr 4 (car tail)) :visible))
(or (not visible) (eval visible))))))
(setq index-of-default (1+ index-of-default)))
(setq tail (cdr tail)))))
(let ((prompt
(concat "^"
(if (and (stringp tmm-mid-prompt)
(not tmm-shortcut-inside-entry))
(concat "."
(regexp-quote tmm-mid-prompt))))))
(setq tmm--history
(reverse (delq nil
(mapcar
(lambda (elt)
(if (string-match prompt (car elt))
(car elt)))
tmm-km-list)))))
(setq history-len (length tmm--history))
(setq tmm-c-prompt (nth (- history-len 1 index-of-default)
tmm--history))
(setq out
(if default-item
(car (nth index-of-default tmm-km-list))
(minibuffer-with-setup-hook
(lambda ()
(setq tmm-old-mb-map (tmm-define-keys t))
(add-hook 'completion-setup-hook
#'tmm--completion-setup-hook 'append 'local))
;; tmm-km-list is reversed, because history
;; needs it in LIFO order. But default list
;; needs it in non-reverse order, so that the
;; menu items are displayed by M-n as default
;; values in the order they are shown on
;; the menu bar. So pass the DEFAULT arg the
;; reversed copy of the list.
(completing-read-default
(concat gl-str
" (up/down to change, PgUp to menu): ")
(completion-table-with-metadata
tmm-km-list '((category . tmm)
(eager-display . t)
(display-sort-function . identity)
(cycle-sort-function . identity)))
nil t nil
'tmm--history (reverse tmm--history)))))))
(if (and (stringp out) (string= "^" out))
;; A fake choice to please the destructuring later.
(setq choice (cons out out))
(setq choice (cdr (assoc out tmm-km-list)))
(and (null choice)
(string-prefix-p tmm-c-prompt out)
(setq out (substring out (length tmm-c-prompt))
choice (cdr (assoc out tmm-km-list))))
(and (null choice) out
(setq out (try-completion out tmm-km-list)
choice (cdr (assoc out tmm-km-list))))))
;; CHOICE is now (STRING . MEANING). Separate the two parts.
(setq chosen-string (car choice))
(setq choice (cdr choice))
(cond ((and (stringp choice) (string= "^" choice))
;; User wants to go up: do it first.
(if path (tmm-prompt (pop path) in-popup nil nil path)))
(in-popup
;; We just did the inner level of a -popup menu.
choice)
;; We just did the outer level. Do the inner level now.
(not-menu (tmm-prompt choice t nil no-execute (cons menu path)))
;; We just handled a menu keymap and found another keymap.
((keymapp choice)
(if (symbolp choice)
(setq choice (indirect-function choice)))
(condition-case nil
(require 'mouse)
(error nil))
(tmm-prompt choice nil nil no-execute (cons menu path)))
;; We just handled a menu keymap and found a command.
(choice
(if chosen-string
(if no-execute choice
(setq last-command-event chosen-string)
(call-interactively choice))
choice)))))