diff options
| author | Richard M. Stallman | 1995-10-30 16:33:49 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-10-30 16:33:49 +0000 |
| commit | fc225f66911f60792e893250e38caab0274c4404 (patch) | |
| tree | 47855dcf1b42d84d674fd65e8e0b64318f3b6c27 | |
| parent | 97af0368107351ab3c4f069978fba8dd2cae8f30 (diff) | |
| download | emacs-fc225f66911f60792e893250e38caab0274c4404.tar.gz emacs-fc225f66911f60792e893250e38caab0274c4404.zip | |
(tmm-old-mb-map): Initialize to nil.
(tmm-delete-map): Don't use tmm-old-mb-map if nil.
(tmm-add-prompt): Bind C-n and C-p.
Put only the shortcuts into the completion buffer's map.
Produce the completion list by hand so as not to sort it.
(tmm-prompt): Start at the first item in the menu.
Don't reverse tmm-km-list; reverse compl-list instead.
Use try-completion in last-ditch attempt to find a match.
Rename compl-list to history.
(tmm-get-keybind): Put more local bindings last in a menu.
Major rewrite.
(tmm-menubar): Handle menu-bar-final-items.
(tmm-remove-shortcuts): Function deleted.
(tmm-add-shortcuts): If we can't find a letter shortcut,
use a numeric shortcut.
| -rw-r--r-- | lisp/tmm.el | 219 |
1 files changed, 125 insertions, 94 deletions
diff --git a/lisp/tmm.el b/lisp/tmm.el index 17dbedc39c0..51fc76bdb4a 100644 --- a/lisp/tmm.el +++ b/lisp/tmm.el | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Ilya Zakharevich <ilya@math.mps.ohio-state.edu> | 5 | ;; Author: Ilya Zakharevich <ilya@math.mps.ohio-state.edu> |
| 6 | ;; Maintainer: FSF | ||
| 6 | 7 | ||
| 7 | ;; This file is part of GNU Emacs. | 8 | ;; This file is part of GNU Emacs. |
| 8 | 9 | ||
| @@ -32,13 +33,10 @@ | |||
| 32 | ;;; tmm-menubar. | 33 | ;;; tmm-menubar. |
| 33 | 34 | ||
| 34 | (require 'electric) | 35 | (require 'electric) |
| 35 | ;(define-key minibuffer-local-must-match-map [pageup] 'tmm-goto-completions) | ||
| 36 | ;(define-key minibuffer-local-must-match-map [prior] 'tmm-goto-completions) | ||
| 37 | ;(define-key minibuffer-local-must-match-map "\ev" 'tmm-goto-completions) | ||
| 38 | 36 | ||
| 39 | ;;; The following will be localized, added only to pacify the compiler. | 37 | ;;; The following will be localized, added only to pacify the compiler. |
| 40 | (defvar tmm-short-cuts) | 38 | (defvar tmm-short-cuts) |
| 41 | (defvar tmm-old-mb-map) | 39 | (defvar tmm-old-mb-map nil) |
| 42 | (defvar tmm-old-comp-map) | 40 | (defvar tmm-old-comp-map) |
| 43 | (defvar tmm-c-prompt) | 41 | (defvar tmm-c-prompt) |
| 44 | (defvar tmm-km-list) | 42 | (defvar tmm-km-list) |
| @@ -52,7 +50,18 @@ | |||
| 52 | See the documentation for `tmm-prompt'." | 50 | See the documentation for `tmm-prompt'." |
| 53 | (interactive) | 51 | (interactive) |
| 54 | (run-hooks 'menu-bar-update-hook) | 52 | (run-hooks 'menu-bar-update-hook) |
| 55 | (tmm-prompt (tmm-get-keybind [menu-bar]))) | 53 | ;; Obey menu-bar-final-items; put those items last. |
| 54 | (let ((menu-bar (tmm-get-keybind [menu-bar]))) | ||
| 55 | (let ((list menu-bar-final-items)) | ||
| 56 | (while list | ||
| 57 | (let ((item (car list))) | ||
| 58 | ;; ITEM is the name of an item that we want to put last. | ||
| 59 | ;; Find it in MENU-BAR and move it to the end. | ||
| 60 | (let ((this-one (assq item menu-bar))) | ||
| 61 | (setq menu-bar (append (delq this-one menu-bar) | ||
| 62 | (list this-one))))) | ||
| 63 | (setq list (cdr list)))) | ||
| 64 | (tmm-prompt menu-bar))) | ||
| 56 | 65 | ||
| 57 | (defvar tmm-mid-prompt "==>" | 66 | (defvar tmm-mid-prompt "==>" |
| 58 | "String to insert between shortcut and menu item or nil.") | 67 | "String to insert between shortcut and menu item or nil.") |
| @@ -79,44 +88,44 @@ The last alternative is currently a hack, you cannot use mouse reliably. | |||
| 79 | If the optional argument IN-POPUP is set, is argument-compatible with | 88 | If the optional argument IN-POPUP is set, is argument-compatible with |
| 80 | `x-popup-menu', otherwise the argument BIND should be a cdr of sparse keymap." | 89 | `x-popup-menu', otherwise the argument BIND should be a cdr of sparse keymap." |
| 81 | (if in-popup (if bind (setq bind in-popup) (x-popup-menu nil in-popup))) | 90 | (if in-popup (if bind (setq bind in-popup) (x-popup-menu nil in-popup))) |
| 82 | (let (gl-str tmm-km-list out compl-list compl-list-l tmm-table-undef tmm-c-prompt | 91 | (let (gl-str tmm-km-list out history history-len tmm-table-undef tmm-c-prompt |
| 83 | tmm-old-mb-map tmm-old-comp-map tmm-short-cuts) | 92 | tmm-old-mb-map tmm-old-comp-map tmm-short-cuts) |
| 84 | (run-hooks 'activate-menubar-hook) | 93 | (run-hooks 'activate-menubar-hook) |
| 85 | (mapcar (function (lambda (elt) | 94 | (mapcar (function (lambda (elt) |
| 86 | (if (stringp elt) | 95 | (if (stringp elt) |
| 87 | (setq gl-str elt) | 96 | (setq gl-str elt) |
| 88 | (and (listp elt) (tmm-get-keymap elt in-popup))) | 97 | (and (listp elt) (tmm-get-keymap elt in-popup))))) |
| 89 | )) bind) | 98 | bind) |
| 90 | (and tmm-km-list | 99 | (and tmm-km-list |
| 91 | (if tmm-mid-prompt | 100 | (progn |
| 92 | (setq tmm-km-list (reverse (tmm-add-shortcuts tmm-km-list))) | 101 | (if tmm-mid-prompt |
| 93 | t) | 102 | (setq tmm-km-list (tmm-add-shortcuts tmm-km-list)) |
| 94 | (setq compl-list (mapcar 'car tmm-km-list)) | 103 | t) |
| 95 | (setq compl-list-l (length compl-list)) | 104 | (setq history (reverse (mapcar 'car tmm-km-list))) |
| 96 | (setq compl-list (append compl-list compl-list compl-list compl-list)) | 105 | (setq history-len (length history)) |
| 97 | (setq tmm-c-prompt (nth (1- compl-list-l) compl-list)) | 106 | (setq history (append history history history history)) |
| 98 | (add-hook 'minibuffer-setup-hook 'tmm-add-prompt) | 107 | (setq tmm-c-prompt (nth (1- history-len) history)) |
| 99 | (unwind-protect | 108 | (add-hook 'minibuffer-setup-hook 'tmm-add-prompt) |
| 100 | (setq out | 109 | (unwind-protect |
| 101 | (completing-read | 110 | (setq out |
| 102 | (concat gl-str " (up/down to change, PgUp to menu): ") | 111 | (completing-read |
| 103 | tmm-km-list nil t nil | 112 | (concat gl-str " (up/down to change, PgUp to menu): ") |
| 104 | (cons 'compl-list (* 2 compl-list-l)))) | 113 | tmm-km-list nil t nil |
| 105 | ;;(add-hook 'minibuffer-setup-hook 'tmm-remove-shortcuts) | 114 | (cons 'history (* 2 history-len)))) |
| 106 | ;;(save-excursion | 115 | (save-excursion |
| 107 | ;; (set-buffer "*Completions*") | 116 | (set-buffer "*Completions*") |
| 108 | ;; (use-local-map tmm-old-mb-map)) | 117 | (use-local-map tmm-old-comp-map) |
| 109 | (save-excursion | 118 | (bury-buffer (current-buffer))) |
| 110 | (set-buffer "*Completions*") | 119 | ))) |
| 111 | (use-local-map tmm-old-comp-map) | ||
| 112 | (bury-buffer (current-buffer))) | ||
| 113 | )) | ||
| 114 | (setq bind (cdr (assoc out tmm-km-list))) | 120 | (setq bind (cdr (assoc out tmm-km-list))) |
| 115 | (and (null bind) | 121 | (and (null bind) |
| 116 | (> (length out) (length tmm-c-prompt)) | 122 | (> (length out) (length tmm-c-prompt)) |
| 117 | (string= (substring out 0 (length tmm-c-prompt)) tmm-c-prompt) | 123 | (string= (substring out 0 (length tmm-c-prompt)) tmm-c-prompt) |
| 118 | (setq out (substring out (length tmm-c-prompt)) | 124 | (setq out (substring out (length tmm-c-prompt)) |
| 119 | bind (cdr (assoc out tmm-km-list)))) | 125 | bind (cdr (assoc out tmm-km-list)))) |
| 126 | (and (null bind) | ||
| 127 | (setq out (try-completion out tmm-km-list) | ||
| 128 | bind (cdr (assoc out tmm-km-list)))) | ||
| 120 | (setq last-command-event (car bind)) | 129 | (setq last-command-event (car bind)) |
| 121 | (setq bind (cdr bind)) | 130 | (setq bind (cdr bind)) |
| 122 | (if bind | 131 | (if bind |
| @@ -138,28 +147,34 @@ If the optional argument IN-POPUP is set, is argument-compatible with | |||
| 138 | bind))) | 147 | bind))) |
| 139 | gl-str))) | 148 | gl-str))) |
| 140 | 149 | ||
| 141 | (defun tmm-remove-shortcuts () | ||
| 142 | (use-local-map tmm-mb-map)) | ||
| 143 | 150 | ||
| 144 | (defun tmm-add-shortcuts (list) | 151 | (defun tmm-add-shortcuts (list) |
| 145 | "Adds shortcuts to cars of elements of the list. | 152 | "Adds shortcuts to cars of elements of the list. |
| 146 | Takes a list of lists with a string as car, returns list with | 153 | Takes a list of lists with a string as car, returns list with |
| 147 | shortcuts added to these cars. Adds the shortcuts to a free variable | 154 | shortcuts added to these cars. |
| 148 | `tmm-short-cuts'." | 155 | Stores a list of all the shortcuts in the free variable `tmm-short-cuts'." |
| 149 | (mapcar (lambda (elt) | 156 | (let ((next-shortcut-number 0)) |
| 150 | (let ((str (car elt)) f b) | 157 | (mapcar (lambda (elt) |
| 151 | (setq f (upcase (substring str 0 1))) | 158 | (let ((str (car elt)) f b) |
| 152 | ;; If does not work, try beginning of the other word | 159 | (setq f (upcase (substring str 0 1))) |
| 153 | (if (and (member f tmm-short-cuts) | 160 | ;; If does not work, try beginning of the other word |
| 154 | (string-match " \\([^ ]\\)" str)) | 161 | (if (and (member f tmm-short-cuts) |
| 155 | (setq f (upcase (substring | 162 | (string-match " \\([^ ]\\)" str)) |
| 156 | str | 163 | (setq f (upcase (substring |
| 157 | (setq b (match-beginning 1)) (1+ b))))) | 164 | str |
| 158 | (if (member f tmm-short-cuts) | 165 | (setq b (match-beginning 1)) (1+ b))))) |
| 159 | elt | 166 | ;; If we don't have an unique letter shortcut, |
| 160 | (setq tmm-short-cuts (cons f tmm-short-cuts)) | 167 | ;; pick a digit as a shortcut instead. |
| 161 | (cons (concat f tmm-mid-prompt str) (cdr elt))))) | 168 | (if (member f tmm-short-cuts) |
| 162 | (reverse list))) | 169 | (if (< next-shortcut-number 10) |
| 170 | (setq f (format "%d" next-shortcut-number) | ||
| 171 | next-shortcut-number (1+ next-shortcut-number)) | ||
| 172 | (setq f nil))) | ||
| 173 | (if (null f) | ||
| 174 | elt | ||
| 175 | (setq tmm-short-cuts (cons f tmm-short-cuts)) | ||
| 176 | (cons (concat f tmm-mid-prompt str) (cdr elt))))) | ||
| 177 | (reverse list)))) | ||
| 163 | 178 | ||
| 164 | (defun tmm-add-prompt () | 179 | (defun tmm-add-prompt () |
| 165 | (remove-hook 'minibuffer-setup-hook 'tmm-add-prompt) | 180 | (remove-hook 'minibuffer-setup-hook 'tmm-add-prompt) |
| @@ -170,15 +185,20 @@ shortcuts added to these cars. Adds the shortcuts to a free variable | |||
| 170 | (define-key map str 'tmm-shortcut) | 185 | (define-key map str 'tmm-shortcut) |
| 171 | (define-key map (downcase str) 'tmm-shortcut)) | 186 | (define-key map (downcase str) 'tmm-shortcut)) |
| 172 | tmm-short-cuts) | 187 | tmm-short-cuts) |
| 173 | (define-key map [pageup] 'tmm-goto-completions) | ||
| 174 | (define-key map [prior] 'tmm-goto-completions) | ||
| 175 | (define-key map "\ev" 'tmm-goto-completions) | ||
| 176 | (define-key map "\e\e" 'abort-recursive-edit) | ||
| 177 | (setq tmm-old-mb-map (current-local-map)) | 188 | (setq tmm-old-mb-map (current-local-map)) |
| 178 | (use-local-map (append map (cdr tmm-old-mb-map))) | 189 | (use-local-map (append map (cdr tmm-old-mb-map))) |
| 190 | (define-key (current-local-map) [pageup] 'tmm-goto-completions) | ||
| 191 | (define-key (current-local-map) [prior] 'tmm-goto-completions) | ||
| 192 | (define-key (current-local-map) "\ev" 'tmm-goto-completions) | ||
| 193 | (define-key (current-local-map) "\e\e" 'abort-recursive-edit) | ||
| 194 | (define-key (current-local-map) "\C-n" 'next-history-element) | ||
| 195 | (define-key (current-local-map) "\C-p" 'previous-history-element) | ||
| 179 | ;; Get window and hide it for electric mode to get correct size | 196 | ;; Get window and hide it for electric mode to get correct size |
| 180 | (save-window-excursion | 197 | (save-window-excursion |
| 181 | (minibuffer-completion-help) | 198 | (let ((completions |
| 199 | (mapcar 'car minibuffer-completion-table))) | ||
| 200 | (with-output-to-temp-buffer "*Completions*" | ||
| 201 | (display-completion-list completions))) | ||
| 182 | (set-buffer "*Completions*") | 202 | (set-buffer "*Completions*") |
| 183 | (goto-char 1) | 203 | (goto-char 1) |
| 184 | (insert tmm-completion-prompt) | 204 | (insert tmm-completion-prompt) |
| @@ -197,36 +217,37 @@ shortcuts added to these cars. Adds the shortcuts to a free variable | |||
| 197 | 217 | ||
| 198 | (defun tmm-delete-map () | 218 | (defun tmm-delete-map () |
| 199 | (remove-hook 'minibuffer-exit-hook 'tmm-delete-map t) | 219 | (remove-hook 'minibuffer-exit-hook 'tmm-delete-map t) |
| 200 | (use-local-map tmm-old-mb-map)) | 220 | (if tmm-old-mb-map |
| 221 | (use-local-map tmm-old-mb-map))) | ||
| 201 | 222 | ||
| 202 | (defun tmm-shortcut () | 223 | (defun tmm-shortcut () |
| 224 | "Choose the shortcut that the user typed." | ||
| 203 | (interactive) | 225 | (interactive) |
| 204 | (let ((c (upcase (char-to-string last-command-char))) s) | 226 | (let ((c (upcase (char-to-string last-command-char))) s) |
| 205 | (if (member c tmm-short-cuts) | 227 | (if (member c tmm-short-cuts) |
| 206 | (if (equal (buffer-name) "*Completions*") | 228 | (if (equal (buffer-name) "*Completions*") |
| 207 | (progn | 229 | (progn |
| 208 | (beginning-of-buffer) | 230 | (beginning-of-buffer) |
| 209 | (re-search-forward | 231 | (re-search-forward |
| 210 | (concat "\\(^\\|[ \t]\\)" c tmm-mid-prompt)) | 232 | (concat "\\(^\\|[ \t]\\)" c tmm-mid-prompt)) |
| 211 | (choose-completion)) | 233 | (choose-completion)) |
| 212 | (erase-buffer) ; In minibuffer | 234 | (erase-buffer) ; In minibuffer |
| 213 | (mapcar (lambda (elt) | 235 | (mapcar (lambda (elt) |
| 214 | (if (string= | 236 | (if (string= |
| 215 | (substring (car elt) 0 | 237 | (substring (car elt) 0 |
| 216 | (min (1+ (length tmm-mid-prompt)) | 238 | (min (1+ (length tmm-mid-prompt)) |
| 217 | (length (car elt)))) | 239 | (length (car elt)))) |
| 218 | (concat c tmm-mid-prompt)) | 240 | (concat c tmm-mid-prompt)) |
| 219 | (setq s (car elt)))) | 241 | (setq s (car elt)))) |
| 220 | tmm-km-list) | 242 | tmm-km-list) |
| 221 | (insert s) | 243 | (insert s) |
| 222 | (exit-minibuffer))))) | 244 | (exit-minibuffer))))) |
| 223 | 245 | ||
| 224 | (defun tmm-goto-completions () | 246 | (defun tmm-goto-completions () |
| 225 | (interactive) | 247 | (interactive) |
| 226 | (setq tmm-c-prompt (buffer-string)) | 248 | (setq tmm-c-prompt (buffer-string)) |
| 227 | (erase-buffer) | 249 | (erase-buffer) |
| 228 | (switch-to-buffer-other-window | 250 | (switch-to-buffer-other-window "*Completions*") |
| 229 | "*Completions*") | ||
| 230 | (search-forward tmm-c-prompt) | 251 | (search-forward tmm-c-prompt) |
| 231 | (search-backward tmm-c-prompt)) | 252 | (search-backward tmm-c-prompt)) |
| 232 | 253 | ||
| @@ -234,7 +255,7 @@ shortcuts added to these cars. Adds the shortcuts to a free variable | |||
| 234 | (defun tmm-get-keymap (elt &optional in-x-menu) | 255 | (defun tmm-get-keymap (elt &optional in-x-menu) |
| 235 | "Prepends (DOCSTRING EVENT BINDING) to free variable `tmm-km-list'. | 256 | "Prepends (DOCSTRING EVENT BINDING) to free variable `tmm-km-list'. |
| 236 | The values are deduced from the argument ELT, that should be an | 257 | The values are deduced from the argument ELT, that should be an |
| 237 | element of keymap, on `x-popup-menu' argument, or an element of | 258 | element of keymap, an `x-popup-menu' argument, or an element of |
| 238 | `x-popup-menu' argument (when IN-X-MENU is not-nil). | 259 | `x-popup-menu' argument (when IN-X-MENU is not-nil). |
| 239 | Does it only if it is not already there. Uses free variable | 260 | Does it only if it is not already there. Uses free variable |
| 240 | `tmm-table-undef' to keep undefined keys." | 261 | `tmm-table-undef' to keep undefined keys." |
| @@ -287,26 +308,36 @@ Does it only if it is not already there. Uses free variable | |||
| 287 | 308 | ||
| 288 | 309 | ||
| 289 | (defun tmm-get-keybind (keyseq) | 310 | (defun tmm-get-keybind (keyseq) |
| 290 | "Gets binding from all the tables, can have some junk inside." | 311 | "Return the current binding of KEYSEQ, merging prefix definitions. |
| 312 | If KEYSEQ is a prefix key that has local and gloibal bindings, | ||
| 313 | we merge them into a single keymap which shows the proper order of the menu. | ||
| 314 | However, for the menu bar itself, the value does not take account | ||
| 315 | of `menu-bar-final-items'." | ||
| 291 | (let (allbind bind) | 316 | (let (allbind bind) |
| 292 | (setq allbind (mapcar 'cdr (minor-mode-key-binding keyseq))) | 317 | (setq bind (key-binding keyseq)) |
| 293 | (setq allbind (append allbind (list (local-key-binding keyseq)))) | 318 | ;; If KEYSEQ is a prefix key, then BIND is either nil |
| 294 | (setq allbind (append allbind (list (global-key-binding keyseq)))) | 319 | ;; or a symbol defined as a keymap (which satisfies keymapp). |
| 295 | ; list of bindings | 320 | (if (keymapp bind) |
| 296 | (mapcar (lambda (in) | 321 | (setq bind nil)) |
| 297 | (if (and (symbolp in) (keymapp in)) | 322 | ;; If we have a non-keymap definition, return that. |
| 298 | (setq in (symbol-value in))) | 323 | (or bind |
| 299 | (and in | 324 | (progn |
| 300 | (or (eq bind 'undefined) (not bind) | 325 | ;; Otherwise, it is a prefix, so make a list of the subcommands. |
| 301 | (and (keymapp bind) (keymapp in))) | 326 | ;; Make a list of all the bindings in all the keymaps. |
| 302 | (if (keymapp bind) | 327 | (setq allbind (mapcar 'cdr (minor-mode-key-binding keyseq))) |
| 303 | (setq bind (append bind (cdr in))) | 328 | (setq allbind (cons (local-key-binding keyseq) allbind)) |
| 304 | (setq bind in) | 329 | (setq allbind (cons (global-key-binding keyseq) allbind)) |
| 305 | ) | 330 | ;; Merge all the elements of ALLBIND into one keymap. |
| 306 | ) | 331 | (mapcar (lambda (in) |
| 307 | ) | 332 | (if (and (symbolp in) (keymapp in)) |
| 308 | allbind) | 333 | (setq in (symbol-function in))) |
| 309 | bind)) | 334 | (and in (keymapp in) |
| 335 | (if (keymapp bind) | ||
| 336 | (setq bind (nconc bind (copy-sequence (cdr in)))) | ||
| 337 | (setq bind (copy-sequence in))))) | ||
| 338 | allbind) | ||
| 339 | ;; Return that keymap. | ||
| 340 | bind)))) | ||
| 310 | 341 | ||
| 311 | (add-hook 'calendar-load-hook (lambda () (require 'cal-menu))) | 342 | (add-hook 'calendar-load-hook (lambda () (require 'cal-menu))) |
| 312 | 343 | ||