diff options
| author | Stefan Monnier | 2000-07-05 15:40:03 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2000-07-05 15:40:03 +0000 |
| commit | d0acce1e29485a348138d33a24584694e229ce20 (patch) | |
| tree | 37eca116d321287b16eca23ae61e3f4ee20286ad | |
| parent | 5e03eb84a161f32cd7c656b7b93508891bd36ec1 (diff) | |
| download | emacs-d0acce1e29485a348138d33a24584694e229ce20.tar.gz emacs-d0acce1e29485a348138d33a24584694e229ce20.zip | |
(easy-menu-define): Docstring fix.
(easy-menu-do-define): Use `menu-item' format.
Handle case where easy-menu-create-menu returns a symbol.
Manually call the potential top-level filter in the function binding.
(easy-menu-filter-return): New arg NAME.
Convert to a keymap if MENU is an XEmacs menu.
(easy-menu-convert-item-1): New. Extracted from easy-menu-do-add-item.
(easy-menu-converted-items-table, easy-menu-convert-item): New.
(easy-menu-do-add-item): Use it.
(easy-menu-create-menu): Use easy-menu-convert-item.
Wrap easy-menu-filter-return around any :filter specification.
Don't convert the menu if a filter was specified.
Tell easy-menu-make-symbol not to check for MENU being an expression.
(easy-menu-make-symbol): New arg NOEXP.
| -rw-r--r-- | lisp/emacs-lisp/easymenu.el | 103 |
1 files changed, 74 insertions, 29 deletions
diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el index ae3af3cc644..664bc4825ad 100644 --- a/lisp/emacs-lisp/easymenu.el +++ b/lisp/emacs-lisp/easymenu.el | |||
| @@ -92,9 +92,9 @@ KEYS is expanded with `substitute-command-keys' before it is used. | |||
| 92 | 92 | ||
| 93 | :key-sequence KEYS | 93 | :key-sequence KEYS |
| 94 | 94 | ||
| 95 | KEYS is nil a string or a vector; nil or a keyboard equivalent to this | 95 | KEYS is nil, a string or a vector; nil or a keyboard equivalent to this |
| 96 | menu item. | 96 | menu item. |
| 97 | This is a hint that will considerably speed up Emacs first display of | 97 | This is a hint that will considerably speed up Emacs' first display of |
| 98 | a menu. Use `:key-sequence nil' when you know that this menu item has no | 98 | a menu. Use `:key-sequence nil' when you know that this menu item has no |
| 99 | keyboard equivalent. | 99 | keyboard equivalent. |
| 100 | 100 | ||
| @@ -108,9 +108,10 @@ whenever this expression's value is non-nil. | |||
| 108 | INCLUDE is an expression; this item is only visible if this | 108 | INCLUDE is an expression; this item is only visible if this |
| 109 | expression has a non-nil value. | 109 | expression has a non-nil value. |
| 110 | 110 | ||
| 111 | :suffix NAME | 111 | :suffix FORM |
| 112 | 112 | ||
| 113 | NAME is a string; the name of an argument to CALLBACK. | 113 | FORM is an expression that will be dynamically evaluated and whose |
| 114 | value will be concatenated to the menu entry's NAME. | ||
| 114 | 115 | ||
| 115 | :style STYLE | 116 | :style STYLE |
| 116 | 117 | ||
| @@ -149,21 +150,42 @@ A menu item can be a list with the same format as MENU. This is a submenu." | |||
| 149 | ;; `easy-menu-define' in order to make byte compiled files | 150 | ;; `easy-menu-define' in order to make byte compiled files |
| 150 | ;; compatible. Therefore everything interesting is done in this | 151 | ;; compatible. Therefore everything interesting is done in this |
| 151 | ;; function. | 152 | ;; function. |
| 152 | (set symbol (easy-menu-create-menu (car menu) (cdr menu))) | 153 | (let ((keymap (easy-menu-create-menu (car menu) (cdr menu)))) |
| 153 | (fset symbol `(lambda (event) ,doc (interactive "@e") | 154 | (set symbol keymap) |
| 154 | (x-popup-menu event ,symbol))) | 155 | (fset symbol |
| 155 | (mapcar (function (lambda (map) | 156 | `(lambda (event) ,doc (interactive "@e") |
| 156 | (define-key map (vector 'menu-bar (intern (car menu))) | 157 | ;; FIXME: XEmacs uses popup-menu which calls the binding |
| 157 | (cons (car menu) (symbol-value symbol))))) | 158 | ;; while x-popup-menu only returns the selection. |
| 158 | (if (keymapp maps) (list maps) maps))) | 159 | (x-popup-menu event |
| 159 | 160 | (or (and (symbolp ,symbol) | |
| 160 | (defun easy-menu-filter-return (menu) | 161 | (funcall |
| 162 | (or (plist-get (get ,symbol 'menu-prop) | ||
| 163 | :filter) | ||
| 164 | 'identity) | ||
| 165 | (symbol-function ,symbol))) | ||
| 166 | ,symbol)))) | ||
| 167 | (mapcar (lambda (map) | ||
| 168 | (define-key map (vector 'menu-bar (intern (car menu))) | ||
| 169 | (cons 'menu-item | ||
| 170 | (cons (car menu) | ||
| 171 | (if (not (symbolp keymap)) | ||
| 172 | (list keymap) | ||
| 173 | (cons (symbol-function keymap) | ||
| 174 | (get keymap 'menu-prop))))))) | ||
| 175 | (if (keymapp maps) (list maps) maps)))) | ||
| 176 | |||
| 177 | (defun easy-menu-filter-return (menu &optional name) | ||
| 161 | "Convert MENU to the right thing to return from a menu filter. | 178 | "Convert MENU to the right thing to return from a menu filter. |
| 162 | MENU is a menu as computed by `easy-menu-define' or `easy-menu-create-menu' or | 179 | MENU is a menu as computed by `easy-menu-define' or `easy-menu-create-menu' or |
| 163 | a symbol whose value is such a menu. | 180 | a symbol whose value is such a menu. |
| 164 | In Emacs a menu filter must return a menu (a keymap), in XEmacs a filter must | 181 | In Emacs a menu filter must return a menu (a keymap), in XEmacs a filter must |
| 165 | return a menu items list (without menu name and keywords). | 182 | return a menu items list (without menu name and keywords). |
| 166 | This function returns the right thing in the two cases." | 183 | This function returns the right thing in the two cases. |
| 184 | If NAME is provided, it is used for the keymap." | ||
| 185 | (when (and (not (keymapp menu)) (consp menu)) | ||
| 186 | ;; If it's a cons but not a keymap, then it can't be right | ||
| 187 | ;; unless it's an XEmacs menu. | ||
| 188 | (setq menu (easy-menu-create-menu (or name "") menu))) | ||
| 167 | (easy-menu-get-map menu nil)) ; Get past indirections. | 189 | (easy-menu-get-map menu nil)) ; Get past indirections. |
| 168 | 190 | ||
| 169 | ;;;###autoload | 191 | ;;;###autoload |
| @@ -180,7 +202,9 @@ possibly preceded by keyword pairs as described in `easy-menu-define'." | |||
| 180 | (setq arg (cadr menu-items)) | 202 | (setq arg (cadr menu-items)) |
| 181 | (setq menu-items (cddr menu-items)) | 203 | (setq menu-items (cddr menu-items)) |
| 182 | (cond | 204 | (cond |
| 183 | ((eq keyword :filter) (setq filter arg)) | 205 | ((eq keyword :filter) |
| 206 | (setq filter `(lambda (menu) | ||
| 207 | (easy-menu-filter-return (,arg menu) ,menu-name)))) | ||
| 184 | ((eq keyword :active) (setq enable (or arg ''nil))) | 208 | ((eq keyword :active) (setq enable (or arg ''nil))) |
| 185 | ((eq keyword :label) (setq label arg)) | 209 | ((eq keyword :label) (setq label arg)) |
| 186 | ((eq keyword :help) (setq help arg)) | 210 | ((eq keyword :help) (setq help arg)) |
| @@ -194,11 +218,15 @@ possibly preceded by keyword pairs as described in `easy-menu-define'." | |||
| 194 | (if filter (setq prop (cons :filter (cons filter prop)))) | 218 | (if filter (setq prop (cons :filter (cons filter prop)))) |
| 195 | (if help (setq prop (cons :help (cons help prop)))) | 219 | (if help (setq prop (cons :help (cons help prop)))) |
| 196 | (if label (setq prop (cons nil (cons label prop)))) | 220 | (if label (setq prop (cons nil (cons label prop)))) |
| 197 | (while menu-items | 221 | (if filter |
| 198 | (easy-menu-do-add-item menu (car menu-items)) | 222 | ;; The filter expects the menu in its XEmacs form and the pre-filter |
| 199 | (setq menu-items (cdr menu-items))) | 223 | ;; form will only be passed to the filter anyway, so we'd better |
| 224 | ;; not convert it at all (it will be converted on the fly by | ||
| 225 | ;; easy-menu-filter-return). | ||
| 226 | (setq menu menu-items) | ||
| 227 | (setq menu (append menu (mapcar 'easy-menu-convert-item menu-items)))) | ||
| 200 | (when prop | 228 | (when prop |
| 201 | (setq menu (easy-menu-make-symbol menu)) | 229 | (setq menu (easy-menu-make-symbol menu 'noexp)) |
| 202 | (put menu 'menu-prop prop)) | 230 | (put menu 'menu-prop prop)) |
| 203 | menu))) | 231 | menu))) |
| 204 | 232 | ||
| @@ -208,6 +236,23 @@ possibly preceded by keyword pairs as described in `easy-menu-define'." | |||
| 208 | '((radio . :radio) (toggle . :toggle))) | 236 | '((radio . :radio) (toggle . :toggle))) |
| 209 | 237 | ||
| 210 | (defun easy-menu-do-add-item (menu item &optional before) | 238 | (defun easy-menu-do-add-item (menu item &optional before) |
| 239 | (setq item (easy-menu-convert-item item)) | ||
| 240 | (easy-menu-define-key-intern menu (car item) (cdr item) before)) | ||
| 241 | |||
| 242 | (defvar easy-menu-converted-items-table (make-hash-table :test 'equal)) | ||
| 243 | |||
| 244 | (defun easy-menu-convert-item (item) | ||
| 245 | ;; Memoize easy-menu-convert-item-1. | ||
| 246 | ;; This makes key-shortcut-caching work a *lot* better when this | ||
| 247 | ;; conversion is done from within a filter. | ||
| 248 | ;; This also helps when the NAME of the entry is recreated each time: | ||
| 249 | ;; since the menu is built and traversed separately, the lookup | ||
| 250 | ;; would always fail because the key is `equal' but not `eq'. | ||
| 251 | (or (gethash item easy-menu-converted-items-table) | ||
| 252 | (puthash item (easy-menu-convert-item-1 item) | ||
| 253 | easy-menu-converted-items-table))) | ||
| 254 | |||
| 255 | (defun easy-menu-convert-item-1 (item) | ||
| 211 | ;; Parse an item description and add the item to a keymap. This is | 256 | ;; Parse an item description and add the item to a keymap. This is |
| 212 | ;; the function that is used for item definition by the other easy-menu | 257 | ;; the function that is used for item definition by the other easy-menu |
| 213 | ;; functions. | 258 | ;; functions. |
| @@ -305,13 +350,11 @@ possibly preceded by keyword pairs as described in `easy-menu-define'." | |||
| 305 | (or (null cache) (stringp cache) (vectorp cache))) | 350 | (or (null cache) (stringp cache) (vectorp cache))) |
| 306 | (setq prop (cons :key-sequence (cons cache prop)))))) | 351 | (setq prop (cons :key-sequence (cons cache prop)))))) |
| 307 | (t (error "Invalid menu item in easymenu"))) | 352 | (t (error "Invalid menu item in easymenu"))) |
| 308 | (easy-menu-define-key-intern menu name | 353 | (cons name (and (not remove) |
| 309 | (and (not remove) | 354 | (cons 'menu-item |
| 310 | (cons 'menu-item | 355 | (cons label |
| 311 | (cons label | 356 | (and name |
| 312 | (and name | 357 | (cons command prop)))))))) |
| 313 | (cons command prop))))) | ||
| 314 | before))) | ||
| 315 | 358 | ||
| 316 | (defun easy-menu-define-key-intern (menu key item &optional before) | 359 | (defun easy-menu-define-key-intern (menu key item &optional before) |
| 317 | ;; This is the same as easy-menu-define-key, but it interns KEY and | 360 | ;; This is the same as easy-menu-define-key, but it interns KEY and |
| @@ -362,13 +405,15 @@ possibly preceded by keyword pairs as described in `easy-menu-define'." | |||
| 362 | 405 | ||
| 363 | (defvar easy-menu-item-count 0) | 406 | (defvar easy-menu-item-count 0) |
| 364 | 407 | ||
| 365 | (defun easy-menu-make-symbol (callback) | 408 | (defun easy-menu-make-symbol (callback &optional noexp) |
| 366 | ;; Return a unique symbol with CALLBACK as function value. | 409 | "Return a unique symbol with CALLBACK as function value. |
| 410 | When non-nil, NOEXP indicates that CALLBACK cannot be an expression | ||
| 411 | \(i.e. does not need to be turned into a function)." | ||
| 367 | (let ((command | 412 | (let ((command |
| 368 | (make-symbol (format "menu-function-%d" easy-menu-item-count)))) | 413 | (make-symbol (format "menu-function-%d" easy-menu-item-count)))) |
| 369 | (setq easy-menu-item-count (1+ easy-menu-item-count)) | 414 | (setq easy-menu-item-count (1+ easy-menu-item-count)) |
| 370 | (fset command | 415 | (fset command |
| 371 | (if (keymapp callback) callback | 416 | (if (or (keymapp callback) noexp) callback |
| 372 | `(lambda () (interactive) ,callback))) | 417 | `(lambda () (interactive) ,callback))) |
| 373 | command)) | 418 | command)) |
| 374 | 419 | ||