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)
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.
Source Code
;; Defined in /usr/src/emacs/lisp/tmm.el.gz
;;;###autoload
(defun tmm-prompt (menu &optional in-popup default-item no-execute)
"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."
;; 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 (stringp tmm-mid-prompt)
(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 #'tmm-add-prompt
;; 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): ")
(tmm--completion-table tmm-km-list) nil t nil
'tmm--history (reverse tmm--history)))))))
(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 (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))
;; 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))
;; 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)))))