(apropos, apropos-command): Ignore symbols that have apropos-inhibit property.
[bpt/emacs.git] / lisp / menu-bar.el
CommitLineData
235aa29b
ER
1;;; menu-bar.el --- define a default menu bar.
2
b578f267
EN
3;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
4
235aa29b 5;; Author: RMS
e4874521 6;; Maintainer: FSF
b7f66977 7;; Keywords: internal
235aa29b 8
1db87953
RS
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
1db87953 25
260130bb
KH
26;; Avishai Yacobi suggested some menu rearrangements.
27
b578f267
EN
28;;; Code:
29
d537086b
RS
30;;; User options:
31
30e19aee 32(defcustom buffers-menu-max-size 10
d537086b
RS
33 "*Maximum number of entries which may appear on the Buffers menu.
34If this is 10, then only the ten most-recently-selected buffers are shown.
35If this is nil, then all buffers are shown.
30e19aee
RS
36A large number or nil slows down menu responsiveness."
37 :type '(choice integer
38 (const :tag "All" nil))
39 :group 'mouse)
d537086b 40
b132f2b1
RM
41;; Don't clobber an existing menu-bar keymap, to preserve any menu-bar key
42;; definitions made in loaddefs.el.
43(or (lookup-key global-map [menu-bar])
44 (define-key global-map [menu-bar] (make-sparse-keymap "menu-bar")))
22390f50 45(defvar menu-bar-help-menu (make-sparse-keymap "Help"))
ffbdd83d
RS
46
47;; Force Help item to come last, after the major mode's own items.
0d31efcd
KH
48;; The symbol used to be called `help', but that gets confused with the
49;; help key.
50(setq menu-bar-final-items '(help-menu))
ffbdd83d 51
0d31efcd 52(define-key global-map [menu-bar help-menu] (cons "Help" menu-bar-help-menu))
ffbdd83d
RS
53(defvar menu-bar-search-menu (make-sparse-keymap "Search"))
54(define-key global-map [menu-bar search] (cons "Search" menu-bar-search-menu))
22390f50 55(defvar menu-bar-edit-menu (make-sparse-keymap "Edit"))
40954111 56(define-key global-map [menu-bar edit] (cons "Edit" menu-bar-edit-menu))
ffbdd83d
RS
57(defvar menu-bar-tools-menu (make-sparse-keymap "Tools"))
58(define-key global-map [menu-bar tools] (cons "Tools" menu-bar-tools-menu))
59(defvar menu-bar-files-menu (make-sparse-keymap "Files"))
60(define-key global-map [menu-bar files] (cons "Files" menu-bar-files-menu))
1b009b97
RS
61
62;; This alias is for compatibility with 19.28 and before.
63(defvar menu-bar-file-menu menu-bar-files-menu)
9bb8e471 64\f
9dcdc43d
RS
65(defvar vc-menu-map (make-sparse-keymap "Version Control"))
66
147f1d2a
RS
67(define-key menu-bar-tools-menu [gdb] '("Debugger..." . gdb))
68(define-key menu-bar-tools-menu [compile] '("Compile..." . compile))
69(define-key menu-bar-tools-menu [grep] '("Search Files..." . grep))
70
71(define-key menu-bar-tools-menu [separator-1]
72 '("--"))
73
e1726722 74(define-key menu-bar-tools-menu [calendar] '("Display Calendar" . calendar))
c0965058 75(define-key menu-bar-tools-menu [compose-mail] '("Send Mail" . compose-mail))
ffbdd83d 76(define-key menu-bar-tools-menu [rmail] '("Read Mail" . rmail))
96a699d0 77(define-key menu-bar-tools-menu [gnus] '("Read Net News" . gnus))
ffbdd83d
RS
78
79(define-key menu-bar-tools-menu [separator-vc]
80 '("--"))
81
fe74180c 82(define-key menu-bar-tools-menu [vc]
ffbdd83d 83 (cons "Version Control" vc-menu-map))
9bb8e471 84
ffbdd83d 85(define-key menu-bar-tools-menu [separator-compare]
9bb8e471
RS
86 '("--"))
87
dd824ce4
MK
88(define-key menu-bar-tools-menu [ediff-misc]
89 '("Ediff Miscellanea" . menu-bar-ediff-misc-menu))
ffbdd83d 90(define-key menu-bar-tools-menu [epatch]
080ac1ac 91 '("Apply Patch" . menu-bar-epatch-menu))
ffbdd83d 92(define-key menu-bar-tools-menu [ediff-merge]
5438ecd3 93 '("Merge" . menu-bar-ediff-merge-menu))
57eed34a 94(define-key menu-bar-tools-menu [compare]
40a8cde1 95 '("Compare" . menu-bar-ediff-menu))
9bb8e471 96
ffbdd83d 97(define-key menu-bar-tools-menu [separator-print]
9bb8e471
RS
98 '("--"))
99
ffbdd83d
RS
100(put 'print-region 'menu-enable 'mark-active)
101(put 'ps-print-region-with-faces 'menu-enable 'mark-active)
102
103(define-key menu-bar-tools-menu [ps-print-region]
104 '("Postscript Print Region" . ps-print-region-with-faces))
105(define-key menu-bar-tools-menu [ps-print-buffer]
106 '("Postscript Print Buffer" . ps-print-buffer-with-faces))
107(define-key menu-bar-tools-menu [print-region]
108 '("Print Region" . print-region))
109(define-key menu-bar-tools-menu [print-buffer]
110 '("Print Buffer" . print-buffer))
111\f
112(define-key menu-bar-files-menu [exit-emacs]
113 '("Exit Emacs" . save-buffers-kill-emacs))
114
115(define-key menu-bar-files-menu [separator-exit]
116 '("--"))
117
118(define-key menu-bar-files-menu [one-window]
119 '("One Window" . delete-other-windows))
120
121(define-key menu-bar-files-menu [split-window]
122 '("Split Window" . split-window-vertically))
9bb8e471 123
ca1a9692
RS
124(if (fboundp 'delete-frame)
125 (progn
a4e4b916
RS
126 ;; Don't use delete-frame as event name
127 ;; because that is a special event.
128 (define-key menu-bar-files-menu [delete-this-frame]
ca1a9692 129 '("Delete Frame" . delete-frame))
ffbdd83d
RS
130 (define-key menu-bar-files-menu [make-frame-on-display]
131 '("Open New Display..." . make-frame-on-display))
132 (define-key menu-bar-files-menu [make-frame]
dbe82e01 133 '("Make New Frame" . make-frame-command))))
9bb8e471 134
ffbdd83d 135(define-key menu-bar-files-menu [separator-buffers]
9bb8e471
RS
136 '("--"))
137
ffbdd83d
RS
138(define-key menu-bar-files-menu [kill-buffer]
139 '("Kill Current Buffer" . kill-this-buffer))
140(define-key menu-bar-files-menu [insert-file]
1f50590a 141 '("Insert File..." . insert-file))
ffbdd83d 142(define-key menu-bar-files-menu [revert-buffer]
2f1139a4 143 '("Revert Buffer" . revert-buffer))
ffbdd83d 144(define-key menu-bar-files-menu [write-file]
2f1139a4 145 '("Save Buffer As..." . write-file))
ffbdd83d
RS
146(define-key menu-bar-files-menu [save-buffer] '("Save Buffer" . save-buffer))
147(define-key menu-bar-files-menu [dired] '("Open Directory..." . dired))
148(define-key menu-bar-files-menu [open-file] '("Open File..." . find-file))
40a8cde1 149
9bb8e471 150\f
ffbdd83d
RS
151(defun nonincremental-search-forward (string)
152 "Read a string and search for it nonincrementally."
153 (interactive "sSearch for string: ")
154 (if (equal string "")
155 (search-forward (car search-ring))
156 (isearch-update-ring string nil)
157 (search-forward string)))
158
159(defun nonincremental-search-backward (string)
160 "Read a string and search backward for it nonincrementally."
161 (interactive "sSearch for string: ")
162 (if (equal string "")
163 (search-backward (car search-ring))
164 (isearch-update-ring string nil)
165 (search-backward string)))
166
167(defun nonincremental-re-search-forward (string)
168 "Read a regular expression and search for it nonincrementally."
169 (interactive "sSearch for regexp: ")
170 (if (equal string "")
171 (re-search-forward (car regexp-search-ring))
172 (isearch-update-ring string t)
173 (re-search-forward string)))
174
175(defun nonincremental-re-search-backward (string)
176 "Read a regular expression and search backward for it nonincrementally."
177 (interactive "sSearch for regexp: ")
178 (if (equal string "")
179 (re-search-backward (car regexp-search-ring))
180 (isearch-update-ring string t)
181 (re-search-backward string)))
182
1f50590a 183(defun nonincremental-repeat-search-forward ()
ffbdd83d
RS
184 "Search forward for the previous search string."
185 (interactive)
008c8493
RS
186 (if (null search-ring)
187 (error "No previous search"))
ffbdd83d
RS
188 (search-forward (car search-ring)))
189
1f50590a 190(defun nonincremental-repeat-search-backward ()
ffbdd83d
RS
191 "Search backward for the previous search string."
192 (interactive)
008c8493
RS
193 (if (null search-ring)
194 (error "No previous search"))
ffbdd83d
RS
195 (search-backward (car search-ring)))
196
1f50590a 197(defun nonincremental-repeat-re-search-forward ()
ffbdd83d
RS
198 "Search forward for the previous regular expression."
199 (interactive)
97565dd9 200 (if (null regexp-search-ring)
008c8493 201 (error "No previous search"))
ffbdd83d
RS
202 (re-search-forward (car regexp-search-ring)))
203
1f50590a 204(defun nonincremental-repeat-re-search-backward ()
ffbdd83d
RS
205 "Search backward for the previous regular expression."
206 (interactive)
97565dd9 207 (if (null regexp-search-ring)
008c8493 208 (error "No previous search"))
ffbdd83d
RS
209 (re-search-backward (car regexp-search-ring)))
210
1f50590a
RS
211(define-key menu-bar-search-menu [query-replace-regexp]
212 '("Query Replace Regexp..." . query-replace-regexp))
ffbdd83d 213(define-key menu-bar-search-menu [query-replace]
1f50590a 214 '("Query Replace..." . query-replace))
ffbdd83d 215(define-key menu-bar-search-menu [find-tag]
1f50590a 216 '("Find Tag..." . find-tag))
ffbdd83d
RS
217(define-key menu-bar-search-menu [bookmark]
218 '("Bookmarks" . menu-bar-bookmark-map))
219
220(define-key menu-bar-search-menu [separator-search]
221 '("--"))
222
fe74180c 223(define-key menu-bar-search-menu [repeat-regexp-back]
ffbdd83d 224 '("Repeat Regexp Backwards" . nonincremental-repeat-re-search-backward))
fe74180c 225(define-key menu-bar-search-menu [repeat-search-back]
ffbdd83d 226 '("Repeat Backwards" . nonincremental-repeat-search-backward))
fe74180c 227(define-key menu-bar-search-menu [repeat-regexp-fwd]
ffbdd83d 228 '("Repeat Regexp" . nonincremental-repeat-re-search-forward))
fe74180c 229(define-key menu-bar-search-menu [repeat-search-fwd]
ffbdd83d
RS
230 '("Repeat Search" . nonincremental-repeat-search-forward))
231
232(define-key menu-bar-search-menu [separator-repeat]
9bb8e471
RS
233 '("--"))
234
fe74180c 235(define-key menu-bar-search-menu [re-search-backward]
1f50590a 236 '("Regexp Search Backwards..." . nonincremental-re-search-backward))
fe74180c 237(define-key menu-bar-search-menu [search-backward]
1f50590a 238 '("Search Backwards..." . nonincremental-search-backward))
fe74180c 239(define-key menu-bar-search-menu [re-search-forward]
1f50590a 240 '("Regexp Search..." . nonincremental-re-search-forward))
fe74180c 241(define-key menu-bar-search-menu [search-forward]
1f50590a 242 '("Search..." . nonincremental-search-forward))
ffbdd83d 243\f
5b42ec2b
RS
244(if (fboundp 'start-process)
245 (define-key menu-bar-edit-menu [spell] '("Spell" . ispell-menu-map)))
9bb8e471 246(define-key menu-bar-edit-menu [fill] '("Fill" . fill-region))
6507ffb1 247(define-key menu-bar-edit-menu [props] '("Text Properties" . facemenu-menu))
9bb8e471
RS
248
249(define-key menu-bar-edit-menu [separator-edit]
250 '("--"))
251
252(define-key menu-bar-edit-menu [clear] '("Clear" . delete-region))
3dd92899 253
e1726722 254(define-key menu-bar-edit-menu [paste] '("Paste Most Recent" . yank))
3dd92899
KH
255
256(defvar yank-menu (cons "Select Yank" nil))
257(fset 'yank-menu (cons 'keymap yank-menu))
258(define-key menu-bar-edit-menu [select-paste] '("Select and Paste" . yank-menu))
4c0317b1 259(define-key menu-bar-edit-menu [copy] '("Copy" . menu-bar-kill-ring-save))
057d49d1
RS
260(define-key menu-bar-edit-menu [cut] '("Cut" . kill-region))
261(define-key menu-bar-edit-menu [undo] '("Undo" . undo))
262
4c0317b1
RS
263(defun menu-bar-kill-ring-save (beg end)
264 (interactive "r")
265 (if (mouse-region-match)
266 (message "Select a region with the mouse does `copy' automatically")
267 (kill-ring-save beg end)))
268
25b048ee
RS
269(put 'fill-region 'menu-enable '(and mark-active (not buffer-read-only)))
270(put 'kill-region 'menu-enable '(and mark-active (not buffer-read-only)))
4c0317b1 271(put 'menu-bar-kill-ring-save 'menu-enable 'mark-active)
25b048ee
RS
272(put 'yank 'menu-enable '(and (x-selection-exists-p) (not buffer-read-only)))
273(put 'yank-menu 'menu-enable '(and (cdr yank-menu) (not buffer-read-only)))
4c0317b1 274(put 'delete-region 'menu-enable '(and mark-active
25b048ee 275 (not buffer-read-only)
4c0317b1 276 (not (mouse-region-match))))
25b048ee
RS
277(put 'undo 'menu-enable '(and (not buffer-read-only)
278 (if (eq last-command 'undo)
279 pending-undo-list
280 (consp buffer-undo-list))))
3a841b0b 281(put 'query-replace 'menu-enable '(not buffer-read-only))
25b048ee 282(put 'query-replace-regexp 'menu-enable '(not buffer-read-only))
db774a16 283
9e18f0a0
RS
284(autoload 'ispell-menu-map "ispell" nil t 'keymap)
285
f9cf0be2 286;; These are alternative definitions for the cut, paste and copy
4c0317b1 287;; menu items. Use them if your system expects these to use the clipboard.
f9cf0be2 288
f9cf0be2
RS
289(put 'clipboard-kill-region 'menu-enable 'mark-active)
290(put 'clipboard-kill-ring-save 'menu-enable 'mark-active)
291(put 'clipboard-yank 'menu-enable
292 '(or (x-selection-exists-p) (x-selection-exists-p 'CLIPBOARD)))
293
294(defun clipboard-yank ()
295 "Reinsert the last stretch of killed text, or the clipboard contents."
296 (interactive)
297 (let ((x-select-enable-clipboard t))
298 (yank)))
299
300(defun clipboard-kill-ring-save (beg end)
301 "Copy region to kill ring, and save in the X clipboard."
302 (interactive "r")
303 (let ((x-select-enable-clipboard t))
304 (kill-ring-save beg end)))
305
306(defun clipboard-kill-region (beg end)
307 "Kill the region, and save it in the X clipboard."
308 (interactive "r")
309 (let ((x-select-enable-clipboard t))
310 (kill-region beg end)))
311
312(defun menu-bar-enable-clipboard ()
5cbdeb30
RS
313 "Make CUT, PASTE and COPY (keys and menu bar items) use the clipboard.
314Do the same for the keys of the same name."
f9cf0be2 315 (interactive)
5754d7f2
RS
316 ;; We can't use constant list structure here because it becomes pure,
317 ;; and because it gets modified with cache data.
318 (define-key menu-bar-edit-menu [paste]
319 (cons "Paste" 'clipboard-yank))
320 (define-key menu-bar-edit-menu [copy]
321 (cons "Copy" 'clipboard-kill-ring-save))
322 (define-key menu-bar-edit-menu [cut]
5cbdeb30
RS
323 (cons "Cut" 'clipboard-kill-region))
324
325 (define-key global-map [f20] 'clipboard-kill-region)
326 (define-key global-map [f16] 'clipboard-kill-ring-save)
327 (define-key global-map [f18] 'clipboard-yank)
328 ;; X11R6 versions
329 (define-key global-map [cut] 'clipboard-kill-region)
330 (define-key global-map [copy] 'clipboard-kill-ring-save)
331 (define-key global-map [paste] 'clipboard-yank))
f9cf0be2 332\f
a9f53ffb
RS
333
334;;; Menu support
335
336(defvar menu-bar-custom-menu (make-sparse-keymap "Customize"))
337
b0f661de
RS
338(define-key menu-bar-custom-menu [customize-apropos-groups]
339 '("Apropos Groups..." . customize-apropos-groups))
340(define-key menu-bar-custom-menu [customize-apropos-faces]
341 '("Apropos Faces..." . customize-apropos-faces))
342(define-key menu-bar-custom-menu [customize-apropos-options]
343 '("Apropos Options..." . customize-apropos-options))
a9f53ffb
RS
344(define-key menu-bar-custom-menu [customize-apropos]
345 '("Apropos..." . customize-apropos))
b0f661de
RS
346(define-key menu-bar-custom-menu [separator-2]
347 '("--"))
c9a86e71
RS
348(define-key menu-bar-custom-menu [customize-group]
349 '("Specific Group..." . customize-group))
a9f53ffb 350(define-key menu-bar-custom-menu [customize-face]
c9a86e71 351 '("Specific Face..." . customize-face))
b0f661de
RS
352(define-key menu-bar-custom-menu [customize-option]
353 '("Specific Option..." . customize-option))
354(define-key menu-bar-custom-menu [separator-3]
355 '("--"))
e6354b3e 356(define-key menu-bar-custom-menu [customize-browse]
b0f661de
RS
357 '("Browse Customization Groups" . customize-browse))
358(define-key menu-bar-custom-menu [customize]
359 '("Top-level Customization Group" . customize))
a9f53ffb 360
bacb2d12 361;; Options menu
21efd27b 362(defvar menu-bar-options-menu (make-sparse-keymap "Global Options"))
bacb2d12
RS
363
364(defmacro menu-bar-make-toggle (name variable doc message &rest body)
365 `(progn
366 (defun ,name ()
367 ,(concat doc ".")
368 (interactive)
369 (if ,(if body `(progn . ,body)
370 `(setq ,variable (not ,variable)))
371 (message ,message "enabled")
372 (message ,message "disabled")))
373 '(,doc . ,name)))
374
375(define-key menu-bar-options-menu [debug-on-quit]
376 (menu-bar-make-toggle toggle-debug-on-quit debug-on-quit
377 "Toggle Debug on Quit" "Debug on Quit %s"))
378(define-key menu-bar-options-menu [debug-on-error]
379 (menu-bar-make-toggle toggle-debug-on-error debug-on-error
380 "Toggle Debug on Error" "Debug on Error %s"))
381(define-key menu-bar-options-menu [options-separator]
382 '("--"))
383(define-key menu-bar-options-menu [save-place]
384 (menu-bar-make-toggle toggle-save-place-globally save-place
385 "Toggle Saving Place in Files between Sessions"
386 "Saving place in files %s"
387 (setq-default save-place (not (default-value save-place)))))
388(define-key menu-bar-options-menu [uniquify]
389 (menu-bar-make-toggle toggle-uniquify-buffer-names uniquify-buffer-name-style
390 "Toggle Directory Names in Buffer Names"
391 "Directory name in buffer names (uniquify) %s"
392 (require 'uniquify)
393 (setq uniquify-buffer-name-style
394 (if (not uniquify-buffer-name-style)
395 'forward))))
396(define-key menu-bar-options-menu [transient-mark-mode]
397 (menu-bar-make-toggle toggle-transient-mark-mode transient-mark-mode
398 "Toggle Transient Mark Mode (highlights region)"
399 "Transient Mark mode %s"))
400(define-key menu-bar-options-menu [toggle-auto-compression]
401 '("Toggle Automatic File De/compression" . auto-compression-mode))
402(define-key menu-bar-options-menu [auto-fill-mode]
403 '("Toggle Auto Fill (word wrap) in Text modes"
404 . toggle-text-mode-auto-fill))
8ad97b87
RS
405(define-key menu-bar-options-menu [toggle-global-lazy-font-lock-mode]
406 (menu-bar-make-toggle toggle-global-lazy-font-lock-mode nil
407 "Toggle Global Font Lock (highlights syntax)"
408 "Global Font Lock mode %s"
409 ;; Make sure a support mode is used;
410 ;; otherwise Font Lock will be too slow.
21efd27b 411 (require 'font-lock)
8ad97b87
RS
412 (if (not global-font-lock-mode)
413 (or font-lock-support-mode
414 (setq font-lock-support-mode 'lazy-lock-mode)))
415 (global-font-lock-mode)))
e5683624
RS
416\f
417(defvar menu-bar-describe-menu (make-sparse-keymap "Describe"))
418
419(define-key menu-bar-describe-menu [describe-variable]
420 '("Describe Variable..." . describe-variable))
421(define-key menu-bar-describe-menu [describe-function]
422 '("Describe Function..." . describe-function))
423(define-key menu-bar-describe-menu [describe-key]
424 '("Describe Key..." . describe-key))
425(define-key menu-bar-describe-menu [list-keybindings]
426 '("List Key Bindings" . describe-bindings))
a16f6b16 427(define-key menu-bar-describe-menu [apropos-variables]
e5683624 428 '("Apropos Variables..." . apropos-variable))
a16f6b16
SM
429(define-key menu-bar-describe-menu [apropos-commands]
430 '("Apropos Commands..." . apropos-command))
e5683624
RS
431(define-key menu-bar-describe-menu [describe-mode]
432 '("Describe Buffer Modes" . describe-mode))
433
434(defvar menu-bar-manuals-menu (make-sparse-keymap "Manuals"))
435
436(define-key menu-bar-manuals-menu [man]
437 '("Read Man Page..." . manual-entry))
438(define-key menu-bar-manuals-menu [sep2]
439 '("--"))
440(define-key menu-bar-manuals-menu [key]
441 '("Find Key in Manual" . Info-goto-emacs-key-command-node))
442(define-key menu-bar-manuals-menu [command]
443 '("Find Command in Manual" . Info-goto-emacs-command-node))
444(define-key menu-bar-manuals-menu [info]
445 '("Browse Manuals with Info" . info))
446(define-key menu-bar-manuals-menu [sep1]
447 '("--"))
448(define-key menu-bar-manuals-menu [emacs-faq]
449 '("Emacs FAQ" . view-emacs-FAQ))
450(define-key menu-bar-manuals-menu [emacs-news]
451 '("Emacs News" . view-emacs-news))
bacb2d12 452
efb166ff
RS
453(define-key menu-bar-help-menu [emacs-version]
454 '("Show Version" . emacs-version))
48433a65 455(define-key menu-bar-help-menu [report-emacs-bug]
1c6e18f6 456 '("Send Bug Report..." . report-emacs-bug))
e5683624
RS
457(define-key menu-bar-help-menu [sep2]
458 '("--"))
260130bb 459(define-key menu-bar-help-menu [finder-by-keyword]
e5683624
RS
460 '("Find Emacs Packages..." . finder-by-keyword))
461(define-key menu-bar-help-menu [describe]
462 (cons "Describe" menu-bar-describe-menu))
463(define-key menu-bar-help-menu [manuals]
464 (cons "Manuals" menu-bar-manuals-menu))
ca9b40a1 465(define-key menu-bar-help-menu [emacs-tutorial]
db774a16 466 '("Emacs Tutorial" . help-with-tutorial))
e5683624
RS
467(define-key menu-bar-help-menu [sep1]
468 '("--"))
469(define-key menu-bar-help-menu [options]
bacb2d12 470 (cons "Options" menu-bar-options-menu))
e5683624 471(define-key menu-bar-help-menu [customize]
a0cd87a4 472 (cons "Customize" menu-bar-custom-menu))
889560ed 473
db774a16
RS
474(defun kill-this-buffer () ; for the menubar
475 "Kills the current buffer."
476 (interactive)
477 (kill-buffer (current-buffer)))
478
2f1139a4
RS
479(defun kill-this-buffer-enabled-p ()
480 (let ((count 0)
481 (buffers (buffer-list)))
482 (while buffers
483 (or (string-match "^ " (buffer-name (car buffers)))
484 (setq count (1+ count)))
485 (setq buffers (cdr buffers)))
a6f8cbf1 486 (and (not (window-minibuffer-p (frame-selected-window menu-updating-frame)))
1f50590a
RS
487 (> count 1))))
488
489(put 'kill-this-buffer 'menu-enable '(kill-this-buffer-enabled-p))
490
491(put 'save-buffer 'menu-enable
492 '(and (buffer-modified-p)
a6f8cbf1 493 (not (window-minibuffer-p (frame-selected-window menu-updating-frame)))))
1f50590a
RS
494
495(put 'write-file 'menu-enable
a6f8cbf1 496 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
1f50590a
RS
497
498(put 'find-file 'menu-enable
a6f8cbf1 499 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
1f50590a
RS
500
501(put 'dired 'menu-enable
a6f8cbf1 502 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
1f50590a
RS
503
504(put 'insert-file 'menu-enable
a6f8cbf1 505 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
2f1139a4 506
da183f87
RS
507(put 'revert-buffer 'menu-enable
508 '(or revert-buffer-function revert-buffer-insert-file-contents-function
509 (and (buffer-file-name)
660fa562
RM
510 (or (buffer-modified-p)
511 (not (verify-visited-file-modtime (current-buffer)))))))
82a74107 512
a0213a97
RS
513;; Permit deleting frame if it would leave a visible or iconified frame.
514(put 'delete-frame 'menu-enable
82a74107
KH
515 '(delete-frame-enabled-p))
516
517(defun delete-frame-enabled-p ()
518 "Return non-nil if `delete-frame' should be enabled in the menu bar."
519 (let ((frames (frame-list))
27aa8132
RS
520 (count 0))
521 (while frames
522 (if (frame-visible-p (car frames))
523 (setq count (1+ count)))
524 (setq frames (cdr frames)))
525 (> count 1)))
2f1139a4 526
db774a16
RS
527(put 'advertised-undo 'menu-enable
528 '(and (not (eq t buffer-undo-list))
529 (if (eq last-command 'undo)
2f1139a4
RS
530 (and (boundp 'pending-undo-list)
531 pending-undo-list)
532 buffer-undo-list)))
2877eac2 533
30e19aee
RS
534(defcustom yank-menu-length 20
535 "*Maximum length to display in the yank-menu."
536 :type 'integer
537 :group 'mouse)
3dd92899
KH
538
539(defun menu-bar-update-yank-menu (string old)
540 (let ((front (car (cdr yank-menu)))
541 (menu-string (if (<= (length string) yank-menu-length)
542 string
c3e1d435
RS
543 (concat
544 (substring string 0 (/ yank-menu-length 2))
545 "..."
546 (substring string (- (/ yank-menu-length 2)))))))
7c70a955
RS
547 ;; Don't let the menu string be all dashes
548 ;; because that has a special meaning in a menu.
549 (if (string-match "\\`-+\\'" menu-string)
550 (setq menu-string (concat menu-string " ")))
3dd92899
KH
551 ;; If we're supposed to be extending an existing string, and that
552 ;; string really is at the front of the menu, then update it in place.
553 (if (and old (or (eq old (car front))
554 (string= old (car front))))
dfabc98f 555 (progn
3dd92899
KH
556 (setcar front string)
557 (setcar (cdr front) menu-string))
558 (setcdr yank-menu
559 (cons
560 (cons string (cons menu-string 'menu-bar-select-yank))
561 (cdr yank-menu)))))
562 (if (> (length (cdr yank-menu)) kill-ring-max)
563 (setcdr (nthcdr kill-ring-max yank-menu) nil)))
564
565(defun menu-bar-select-yank ()
566 (interactive "*")
567 (push-mark (point))
568 (insert last-command-event))
40954111 569\f
3f557298
RS
570;; This definition is just to show what this looks like.
571;; It gets overridden below when menu-bar-update-buffers is called.
572(define-key global-map [menu-bar buffer]
573 (cons "Buffers" (make-sparse-keymap "Buffers")))
40954111 574
d0690d12
RS
575(defvar list-buffers-directory nil)
576
08e8171f
RS
577(defvar menu-bar-update-buffers-maxbuf)
578
09642d97
RS
579(defun menu-bar-select-buffer ()
580 (interactive)
581 (switch-to-buffer last-command-event))
582
583(defun menu-bar-select-frame ()
584 (interactive)
585 (make-frame-visible last-command-event)
586 (raise-frame last-command-event)
587 (select-frame last-command-event))
588
c171b42f
RS
589(defun menu-bar-update-buffers-1 (elt)
590 (cons (format
08e8171f 591 (format "%%%ds %%s%%s %%s" menu-bar-update-buffers-maxbuf)
c171b42f
RS
592 (cdr elt)
593 (if (buffer-modified-p (car elt))
594 "*" " ")
595 (save-excursion
596 (set-buffer (car elt))
597 (if buffer-read-only "%" " "))
598 (let ((file
599 (or (buffer-file-name (car elt))
600 (save-excursion
601 (set-buffer (car elt))
602 list-buffers-directory)
603 "")))
604 (setq file (or (file-name-directory file)
605 ""))
606 (if (> (length file) 20)
607 (setq file (concat "..." (substring file -17))))
608 file))
609 (car elt)))
610
06ff7539
RS
611(defvar menu-bar-buffers-menu-list-buffers-entry nil)
612
09642d97 613(defun menu-bar-update-buffers ()
29397c58 614 ;; If user discards the Buffers item, play along.
4d587a6c 615 (and (lookup-key (current-global-map) [menu-bar buffer])
29397c58
RS
616 (frame-or-buffer-changed-p)
617 (let ((buffers (buffer-list))
618 (frames (frame-list))
b3398af1 619 (maxlen 0)
29397c58
RS
620 buffers-menu frames-menu)
621 ;; If requested, list only the N most recently selected buffers.
622 (if (and (integerp buffers-menu-max-size)
623 (> buffers-menu-max-size 1))
624 (if (> (length buffers) buffers-menu-max-size)
625 (setcdr (nthcdr buffers-menu-max-size buffers) nil)))
626
627 ;; Make the menu of buffers proper.
628 (setq buffers-menu
629 (cons "Select Buffer"
c171b42f
RS
630 (let* ((buffer-list
631 (mapcar 'list buffers))
632 tail
08e8171f 633 (menu-bar-update-buffers-maxbuf 0)
c171b42f
RS
634 alist
635 head)
636 ;; Put into each element of buffer-list
637 ;; the name for actual display,
638 ;; perhaps truncated in the middle.
639 (setq tail buffer-list)
640 (while tail
641 (let ((name (buffer-name (car (car tail)))))
642 (setcdr (car tail)
643 (if (> (length name) 27)
644 (concat (substring name 0 12)
645 "..."
646 (substring name -12))
647 name)))
648 (setq tail (cdr tail)))
649 ;; Compute the maximum length of any name.
650 (setq tail buffer-list)
29397c58 651 (while tail
c171b42f 652 (or (eq ?\ (aref (cdr (car tail)) 0))
08e8171f
RS
653 (setq menu-bar-update-buffers-maxbuf
654 (max menu-bar-update-buffers-maxbuf
c171b42f 655 (length (cdr (car tail))))))
29397c58 656 (setq tail (cdr tail)))
c171b42f
RS
657 ;; Set ALIST to an alist of the form
658 ;; ITEM-STRING . BUFFER
659 (setq tail buffer-list)
29397c58
RS
660 (while tail
661 (let ((elt (car tail)))
c171b42f 662 (or (eq ?\ (aref (cdr elt) 0))
29397c58 663 (setq alist (cons
c171b42f 664 (menu-bar-update-buffers-1 elt)
29397c58
RS
665 alist)))
666 (and alist (> (length (car (car alist))) maxlen)
667 (setq maxlen (length (car (car alist))))))
668 (setq tail (cdr tail)))
669 (setq alist (nreverse alist))
06ff7539
RS
670 ;; Make the menu item for list-buffers
671 ;; or reuse the one we already have.
672 ;; The advantage in reusing one
673 ;; is that it already has the keyboard equivalent
674 ;; cached, so we save the time to look that up again.
675 (or menu-bar-buffers-menu-list-buffers-entry
676 (setq menu-bar-buffers-menu-list-buffers-entry
677 (cons
678 'list-buffers
679 (cons
680 ""
681 'list-buffers))))
682 ;; Update the item string for menu's new width.
683 (setcar (cdr menu-bar-buffers-menu-list-buffers-entry)
684 (concat (make-string (max (- (/ maxlen 2) 8) 0)
685 ?\ )
686 "List All Buffers"))
687 ;; Now make the actual list of items,
688 ;; ending with the list-buffers item.
29397c58
RS
689 (nconc (mapcar '(lambda (pair)
690 ;; This is somewhat risque, to use
691 ;; the buffer name itself as the event
692 ;; type to define, but it works.
693 ;; It would not work to use the buffer
694 ;; since a buffer as an event has its
695 ;; own meaning.
696 (nconc (list (buffer-name (cdr pair))
697 (car pair)
698 (cons nil nil))
699 'menu-bar-select-buffer))
700 alist)
06ff7539 701 (list menu-bar-buffers-menu-list-buffers-entry)))))
29397c58
RS
702
703
704 ;; Make a Frames menu if we have more than one frame.
705 (if (cdr frames)
b3398af1
RS
706 (let ((name (concat (make-string (max (- (/ maxlen 2) 3) 0)
707 ?\ )
708 "Frames"))
709 (frames-menu
710 (cons 'keymap
711 (cons "Select Frame"
712 (mapcar '(lambda (frame)
713 (nconc (list frame
714 (cdr (assq 'name
715 (frame-parameters frame)))
716 (cons nil nil))
717 'menu-bar-select-frame))
718 frames)))))
719 ;; Put it underneath the Buffers menu.
720 (setq buffers-menu (cons (cons 'frames (cons name frames-menu))
721 buffers-menu))))
29397c58
RS
722 (if buffers-menu
723 (setq buffers-menu (cons 'keymap buffers-menu)))
4d587a6c 724 (define-key (current-global-map) [menu-bar buffer]
b3398af1 725 (cons "Buffers" buffers-menu)))))
09642d97
RS
726
727(add-hook 'menu-bar-update-hook 'menu-bar-update-buffers)
2f1139a4 728
3f557298
RS
729(menu-bar-update-buffers)
730
40954111
RS
731;; this version is too slow
732;;;(defun format-buffers-menu-line (buffer)
733;;; "Returns a string to represent the given buffer in the Buffer menu.
734;;;nil means the buffer shouldn't be listed. You can redefine this."
735;;; (if (string-match "\\` " (buffer-name buffer))
736;;; nil
737;;; (save-excursion
738;;; (set-buffer buffer)
739;;; (let ((size (buffer-size)))
740;;; (format "%s%s %-19s %6s %-15s %s"
741;;; (if (buffer-modified-p) "*" " ")
742;;; (if buffer-read-only "%" " ")
743;;; (buffer-name)
744;;; size
745;;; mode-name
746;;; (or (buffer-file-name) ""))))))
747\f
25b048ee
RS
748;;; Set up a menu bar menu for the minibuffer.
749
750(mapcar
751 (function
752 (lambda (map)
753 (define-key map [menu-bar minibuf]
754 (cons "Minibuf" (make-sparse-keymap "Minibuf")))))
755 (list minibuffer-local-ns-map
756 minibuffer-local-must-match-map
757 minibuffer-local-isearch-map
758 minibuffer-local-map
759 minibuffer-local-completion-map))
760
761(mapcar
762 (function
763 (lambda (map)
764 (define-key map [menu-bar minibuf ?\?]
765 '("List Completions" . minibuffer-completion-help))
766 (define-key map [menu-bar minibuf space]
767 '("Complete Word" . minibuffer-complete-word))
768 (define-key map [menu-bar minibuf tab]
4e9d1906 769 '("Complete" . minibuffer-complete))
25b048ee
RS
770 ))
771 (list minibuffer-local-must-match-map
772 minibuffer-local-completion-map))
773
774(mapcar
775 (function
776 (lambda (map)
777 (define-key map [menu-bar minibuf quit]
778 '("Quit" . keyboard-escape-quit))
779 (define-key map [menu-bar minibuf return]
780 '("Enter" . exit-minibuffer))
781 ))
782 (list minibuffer-local-ns-map
783 minibuffer-local-must-match-map
784 minibuffer-local-isearch-map
785 minibuffer-local-map
786 minibuffer-local-completion-map))
787\f
7b7d6615
RS
788(defvar menu-bar-mode nil)
789
057d49d1 790(defun menu-bar-mode (flag)
dfd29450 791 "Toggle display of a menu bar on each frame.
057d49d1
RS
792This command applies to all frames that exist and frames to be
793created in the future.
794With a numeric argument, if the argument is negative,
dfd29450 795turn off menu bars; otherwise, turn on menu bars."
dad8e392 796 (interactive "P")
dad8e392 797
7b7d6615
RS
798 ;; Make menu-bar-mode and default-frame-alist consistent.
799 (let ((default (assq 'menu-bar-lines default-frame-alist)))
800 (if default
801 (setq menu-bar-mode (not (eq (cdr default) 0)))
802 (setq default-frame-alist
803 (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
804 default-frame-alist))))
805
806 ;; Toggle or set the mode, according to FLAG.
807 (setq menu-bar-mode (if (null flag) (not menu-bar-mode)
808 (> (prefix-numeric-value flag) 0)))
809
810 ;; Apply it to default-frame-alist.
811 (let ((parameter (assq 'menu-bar-lines default-frame-alist)))
812 (if (consp parameter)
813 (setcdr parameter (if menu-bar-mode 1 0))
814 (setq default-frame-alist
815 (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
816 default-frame-alist))))
817
818 ;; Apply it to existing frames.
819 (let ((frames (frame-list)))
820 (while frames
821 (let ((height (cdr (assq 'height (frame-parameters (car frames))))))
822 (modify-frame-parameters (car frames)
823 (list (cons 'menu-bar-lines
824 (if menu-bar-mode 1 0))))
825 (modify-frame-parameters (car frames)
826 (list (cons 'height height))))
827 (setq frames (cdr frames)))))
1db87953 828
bffa5d4d
RS
829(provide 'menu-bar)
830
235aa29b 831;;; menu-bar.el ends here