comparison lisp/emacs-lisp/easymenu.el @ 20801:8aeddd528f57

(easy-menu-add-item); The BEFORE argument works now. Done by letting `easy-menu-do-add-item' handle it. (easy-menu-do-add-item): Take argument BEFORE instead of PREV. Inserts directly in keymap, instead of calling `define-key-after'. (easy-menu-create-menu): Don't reverse items as `easy-menu-do-add-item' now puts things at the end of keymaps.
author Richard M. Stallman <rms@gnu.org>
date Fri, 30 Jan 1998 02:15:13 +0000
parents 0c51c56d0a4f
children 517de9005275
comparison
equal deleted inserted replaced
20800:43c77517a76c 20801:8aeddd528f57
138 (while (and menu-items (cdr menu-items) 138 (while (and menu-items (cdr menu-items)
139 (symbolp (setq keyword (car menu-items))) 139 (symbolp (setq keyword (car menu-items)))
140 (= ?: (aref (symbol-name keyword) 0))) 140 (= ?: (aref (symbol-name keyword) 0)))
141 (if (eq keyword ':filter) (setq filter (cadr menu-items))) 141 (if (eq keyword ':filter) (setq filter (cadr menu-items)))
142 (setq menu-items (cddr menu-items))) 142 (setq menu-items (cddr menu-items)))
143 ;; Process items in reverse order,
144 ;; since the define-key loop reverses them again.
145 (setq menu-items (reverse menu-items))
146 (while menu-items 143 (while menu-items
147 (setq have-buttons 144 (setq have-buttons
148 (easy-menu-do-add-item menu (car menu-items) have-buttons)) 145 (easy-menu-do-add-item menu (car menu-items) have-buttons))
149 (setq menu-items (cdr menu-items))) 146 (setq menu-items (cdr menu-items)))
150 (when filter 147 (when filter
151 (setq menu (easy-menu-make-symbol menu nil)) 148 (setq menu (easy-menu-make-symbol menu))
152 (put menu 'menu-enable 149 (put menu 'menu-enable
153 `(easy-menu-filter (quote ,menu) (quote ,filter)))) 150 `(easy-menu-filter (quote ,menu) (quote ,filter))))
154 menu)) 151 menu))
155 152
156 153
157 ;; Button prefixes. 154 ;; Button prefixes.
158 (defvar easy-menu-button-prefix 155 (defvar easy-menu-button-prefix
159 '((radio ?* . "( ) ") (toggle ?X . "[ ] "))) 156 '((radio ?* . "( ) ") (toggle ?X . "[ ] ")))
160 157
161 (defun easy-menu-do-add-item (menu item have-buttons &optional prev top) 158 (defun easy-menu-do-add-item (menu item have-buttons &optional before top)
162 ;; Parse an item description and add the item to a keymap. This is 159 ;; Parse an item description and add the item to a keymap. This is
163 ;; the function that is used for item definition by the other easy-menu 160 ;; the function that is used for item definition by the other easy-menu
164 ;; functions. 161 ;; functions.
165 ;; MENU is a sparse keymap. 162 ;; MENU is a sparse keymap i.e. a list starting with the symbol `keymap'.
166 ;; ITEM defines an item as in `easy-menu-define'. 163 ;; ITEM defines an item as in `easy-menu-define'.
167 ;; HAVE-BUTTONS is a string or nil. If not nil, use as item prefix for 164 ;; HAVE-BUTTONS is a string or nil. If not nil, use as item prefix for
168 ;; items that are not toggle or radio buttons to compensate for the 165 ;; items that are not toggle or radio buttons to compensate for the
169 ;; button prefix. 166 ;; button prefix.
170 ;; PREV is nil or a tail in MENU. If PREV is not nil put item after 167 ;; Optional argument BEFORE is nil or a symbol used as a key in MENU. If
171 ;; PREV in MENU, otherwise put it first in MENU. 168 ;; BEFORE is not nil put item before BEFORE in MENU, otherwise if item is
172 ;; If TOP is true, this is an item in the menu bar itself so 169 ;; already present in MENU, just change it, otherwise put it last in MENU.
170 ;; If optional TOP is true, this is an item in the menu bar itself so
173 ;; don't use prefix. In this case HAVE-BUTTONS will be nil. 171 ;; don't use prefix. In this case HAVE-BUTTONS will be nil.
174 (let (command name item-string is-button) 172 (let (command name item-string is-button done inserted)
175 (cond 173 (cond
176 ((stringp item) 174 ((stringp item)
177 (setq item 175 (setq item-string
178 (if (string-match ; If an XEmacs separator 176 (if (string-match ; If an XEmacs separator
179 "^\\(-+\\|\ 177 "^\\(-+\\|\
180 --:\\(\\(no\\|\\(sing\\|doub\\)le\\(Dashed\\)?\\)Line\\|\ 178 --:\\(\\(no\\|\\(sing\\|doub\\)le\\(Dashed\\)?\\)Line\\|\
181 shadow\\(Double\\)?Etched\\(In\\|Out\\)\\(Dash\\)?\\)\\)$" 179 shadow\\(Double\\)?Etched\\(In\\|Out\\)\\(Dash\\)?\\)\\)$"
182 item) "" ; use a single line separator. 180 item) "" ; use a single line separator.
183 (concat have-buttons item))) 181 (concat have-buttons item))))
184 ;; Handle inactive strings specially,
185 ;; allow any number of identical ones.
186 (cond
187 (prev (setq menu prev))
188 ((and (consp (cdr menu)) (stringp (cadr menu))) (setq menu (cdr menu))))
189 (setcdr menu (cons (list nil item) (cdr menu))))
190 ((consp item) 182 ((consp item)
191 (setq name (setq item-string (car item))) 183 (setq name (setq item-string (car item)))
192 (setq command (if (keymapp (setq item (cdr item))) item 184 (setq command (if (keymapp (setq item (cdr item))) item
193 (easy-menu-create-menu name item)))) 185 (easy-menu-create-menu name item))))
194 ((vectorp item) 186 ((vectorp item)
205 (setq arg (aref item (1+ count))) 197 (setq arg (aref item (1+ count)))
206 (setq count (+ 2 count)) 198 (setq count (+ 2 count))
207 (cond 199 (cond
208 ((eq keyword ':keys) (setq keys arg)) 200 ((eq keyword ':keys) (setq keys arg))
209 ((eq keyword ':active) (setq active arg)) 201 ((eq keyword ':active) (setq active arg))
210 ((eq keyword ':suffix) (setq suffix arg)) 202 ((eq keyword ':suffix) (setq suffix (concat " " arg)))
211 ((eq keyword ':style) (setq style arg)) 203 ((eq keyword ':style) (setq style arg))
212 ((eq keyword ':selected) (setq selected arg)))) 204 ((eq keyword ':selected) (setq selected arg))))
205 (if keys (setq suffix (concat suffix " (" keys ")")))
213 (if suffix (setq item-string (concat item-string " " suffix))) 206 (if suffix (setq item-string (concat item-string " " suffix)))
214 (if keys
215 (setq item-string (concat item-string " (" keys ")")))
216 (when (and selected 207 (when (and selected
217 (setq style (assq style easy-menu-button-prefix))) 208 (setq style (assq style easy-menu-button-prefix)))
218 ;; Simulate checkboxes and radio buttons. 209 ;; Simulate checkboxes and radio buttons.
219 (setq item-string (concat (cddr style) item-string)) 210 (setq item-string (concat (cddr style) item-string))
220 (put command 'menu-enable 211 (put command 'menu-enable
226 (setq active nil) ; Already taken care of active. 217 (setq active nil) ; Already taken care of active.
227 (when (not (or have-buttons top)) 218 (when (not (or have-buttons top))
228 (setq have-buttons " ") 219 (setq have-buttons " ")
229 ;; Add prefix to menu items defined so far. 220 ;; Add prefix to menu items defined so far.
230 (easy-menu-change-prefix menu t))))) 221 (easy-menu-change-prefix menu t)))))
231 (if active (put command 'menu-enable active))))) 222 (if active (put command 'menu-enable active))))
223 (t "Illegal menu item in easy menu."))
232 (when name 224 (when name
233 (and (not is-button) have-buttons 225 (and (not is-button) have-buttons
234 (setq item-string (concat have-buttons item-string))) 226 (setq item-string (concat have-buttons item-string)))
235 (setq item (cons item-string command)) 227 (setq name (intern name)))
236 (setq name (vector (intern name))) 228 (setq item (cons item-string command))
237 (if prev (define-key-after menu name item (vector (caar prev))) 229 (if before (setq before (intern before)))
238 (define-key menu name item))) 230 ;; The following loop is simlar to `define-key-after'. It
231 ;; inserts (name . item) in keymap menu.
232 ;; If name is not nil then delete any duplications.
233 ;; If before is not nil, insert before before. Otherwise
234 ;; if name is not nil and it is found in menu, insert there, else
235 ;; insert at end.
236 (while (not done)
237 (cond
238 ((or (setq done (or (null (cdr menu)) (keymapp (cdr menu))))
239 (and before (eq (car-safe (cadr menu)) before)))
240 ;; If name is nil, stop here, otherwise keep going past the
241 ;; inserted element so we can delete any duplications that come
242 ;; later.
243 (if (null name) (setq done t))
244 (unless inserted ; Don't insert more than once.
245 (setcdr menu (cons (cons name item) (cdr menu)))
246 (setq inserted t)
247 (setq menu (cdr menu))))
248 ((and name (eq (car-safe (cadr menu)) name))
249 (if (and before ; Wanted elsewere and
250 (not (setq done ; not the last in this keymap.
251 (or (null (cddr menu)) (keymapp (cddr menu))))))
252 (setcdr menu (cddr menu))
253 (setcdr (cadr menu) item) ; Change item.
254 (setq inserted t))))
255 (setq menu (cdr menu)))
239 have-buttons)) 256 have-buttons))
240 257
241 (defvar easy-menu-item-count 0) 258 (defvar easy-menu-item-count 0)
242 259
243 (defun easy-menu-make-symbol (callback call) 260 (defun easy-menu-make-symbol (callback &optional call)
244 ;; Return a unique symbol with CALLBACK as function value. 261 ;; Return a unique symbol with CALLBACK as function value.
245 ;; If CALL is false then this is a keymap, not a function. 262 ;; If CALL is false then this is a keymap, not a function.
246 ;; Else if CALLBACK is a symbol, avoid the indirection when looking for 263 ;; Else if CALLBACK is a symbol, avoid the indirection when looking for
247 ;; key-bindings in menu. 264 ;; key-bindings in menu.
248 ;; Else make a lambda expression of CALLBACK. 265 ;; Else make a lambda expression of CALLBACK.
326 added. If PATH is nil, MENU itself is used. Otherwise, the first 343 added. If PATH is nil, MENU itself is used. Otherwise, the first
327 element should be the name of a submenu directly under MENU. This 344 element should be the name of a submenu directly under MENU. This
328 submenu is then traversed recursively with the remaining elements of PATH. 345 submenu is then traversed recursively with the remaining elements of PATH.
329 ITEM is either defined as in `easy-menu-define' or a menu defined earlier 346 ITEM is either defined as in `easy-menu-define' or a menu defined earlier
330 by `easy-menu-define' or `easy-menu-create-menu'." 347 by `easy-menu-define' or `easy-menu-create-menu'."
331 (let ((top (not (or menu path))) 348 (let ((top (not (or menu path))))
332 tmp prev next)
333 (setq menu (easy-menu-get-map menu path)) 349 (setq menu (easy-menu-get-map menu path))
334 (or (lookup-key menu (vector (intern (elt item 0)))) 350 (if (or (keymapp item)
335 (and menu (keymapp (cdr menu))) 351 (and (symbolp item) (keymapp (symbol-value item))))
336 (setq tmp (cdr menu))) 352 ;; Item is a keymap, find the prompt string and use as item name.
337 (while (and tmp (not (keymapp tmp)) 353 (let ((tail (easy-menu-get-map item nil)) name)
338 (not (and (consp (car tmp)) (symbolp (caar tmp))))) 354 (if (not (keymapp item)) (setq item tail))
339 (setq tmp (cdr tmp))) 355 (while (and (null name) (consp (setq tail (cdr tail)))
340 (and before (setq before (intern before))) 356 (not (keymapp tail)))
341 (if (or (null tmp) (keymapp tmp) (eq (setq prev (caar tmp)) before)) 357 (if (stringp (car tail)) (setq name (car tail)) ; Got a name.
342 (setq prev nil) 358 (setq tail (cdr tail))))
343 (while (and tmp (not (keymapp tmp)) 359 (setq item (cons name item))))
344 (not (and (consp (car tmp))
345 (eq (caar (setq next tmp)) before))))
346 (if next (setq prev next))
347 (setq next nil)
348 (setq tmp (cdr tmp))))
349 (when (or (keymapp item)
350 (and (symbolp item) (keymapp (symbol-value item))))
351 ;; Item is a keymap, find the prompt string and use as item name.
352 (setq next (easy-menu-get-map item nil))
353 (if (not (keymapp item)) (setq item next))
354 (setq tmp nil) ; No item name yet.
355 (while (and (null tmp) (consp (setq next (cdr next)))
356 (not (keymapp next)))
357 (if (stringp (car next)) (setq tmp (car next)) ; Got a name.
358 (setq next (cdr next))))
359 (setq item (cons tmp item)))
360 (easy-menu-do-add-item menu item 360 (easy-menu-do-add-item menu item
361 (and (not top) (easy-menu-have-button menu) " ") 361 (and (not top) (easy-menu-have-button menu)
362 prev top))) 362 " ")
363 before top)))
363 364
364 (defun easy-menu-item-present-p (menu path name) 365 (defun easy-menu-item-present-p (menu path name)
365 "In submenu of MENU with path PATH, return true iff item NAME is present. 366 "In submenu of MENU with path PATH, return true iff item NAME is present.
366 MENU and PATH are defined as in `easy-menu-add-item'. 367 MENU and PATH are defined as in `easy-menu-add-item'.
367 NAME should be a string, the name of the element to be looked for." 368 NAME should be a string, the name of the element to be looked for."