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)))))