Mercurial > hg > xemacs-beta
comparison lisp/keymap.el @ 209:41ff10fd062f r20-4b3
Import from CVS: tag r20-4b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:04:58 +0200 |
parents | |
children | 677f6a0ee643 |
comparison
equal
deleted
inserted
replaced
208:f427b8ec4379 | 209:41ff10fd062f |
---|---|
1 ;; keymap.el --- Keymap functions for XEmacs. | |
2 | |
3 ;; Copyright (C) 1993-4, 1997 Free Software Foundation, Inc. | |
4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. | |
5 | |
6 ;; Maintainer: XEmacs Development Team | |
7 ;; Keywords: internals, dumped | |
8 | |
9 ;; This file is part of XEmacs. | |
10 | |
11 ;; XEmacs is free software; you can redistribute it and/or modify it | |
12 ;; 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 ;; XEmacs is distributed in the hope that it will be useful, but | |
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 ;; General Public License for more details. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with XEmacs; see the file COPYING. If not, write to the | |
23 ;; Free Software Foundation, 59 Temple Place - Suite 330, | |
24 ;; Boston, MA 02111-1307, USA. | |
25 | |
26 ;;; Synched up with: FSF 19.28. | |
27 | |
28 ;;; Commentary: | |
29 | |
30 ;; This file is dumped with XEmacs. | |
31 | |
32 ;;; Note: FSF does not have a file keymap.el. This stuff is | |
33 ;;; in keymap.c. | |
34 | |
35 ;Prevent the \{...} documentation construct | |
36 ;from mentioning keys that run this command. | |
37 | |
38 ;;; Code: | |
39 | |
40 (put 'undefined 'suppress-keymap t) | |
41 | |
42 (defun undefined () | |
43 (interactive) | |
44 (ding)) | |
45 | |
46 (defun suppress-keymap (map &optional nodigits) | |
47 "Make MAP override all normally self-inserting keys to be undefined. | |
48 Normally, as an exception, digits and minus-sign are set to make prefix args, | |
49 but optional second arg NODIGITS non-nil treats them like other chars." | |
50 (substitute-key-definition 'self-insert-command 'undefined map global-map) | |
51 (or nodigits | |
52 (let ((string (make-string 1 ?0))) | |
53 (define-key map "-" 'negative-argument) | |
54 ;; Make plain numbers do numeric args. | |
55 (while (<= (aref string 0) ?9) | |
56 (define-key map string 'digit-argument) | |
57 (incf (aref string 0)))))) | |
58 | |
59 (defun substitute-key-definition (olddef newdef keymap &optional oldmap prefix) | |
60 "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF. | |
61 In other words, OLDDEF is replaced with NEWDEF wherever it appears. | |
62 Prefix keymaps are checked recursively. If optional fourth argument OLDMAP | |
63 is specified, we redefine in KEYMAP as NEWDEF those chars which are defined | |
64 as OLDDEF in OLDMAP, unless that keybinding is already present in keymap. | |
65 If optional fifth argument PREFIX is defined, then only those occurrences of | |
66 OLDDEF found in keymaps accessible through the keymap bound to PREFIX in | |
67 KEYMAP are redefined. See also `accessible-keymaps'." | |
68 (let ((maps (accessible-keymaps (or oldmap keymap) prefix)) | |
69 (shadowing (not (null oldmap))) | |
70 prefix map) | |
71 (while maps | |
72 (setq prefix (car (car maps)) | |
73 map (cdr (car maps)) | |
74 maps (cdr maps)) | |
75 ;; Substitute in this keymap | |
76 (map-keymap #'(lambda (key binding) | |
77 (if (eq binding olddef) | |
78 ;; The new bindings always go in KEYMAP even if we | |
79 ;; found them in OLDMAP or one of it's children. | |
80 ;; If KEYMAP will be shadowing OLDMAP, then do not | |
81 ;; redefine the key if there is another binding | |
82 ;; in KEYMAP that will shadow OLDDEF. | |
83 (or (and shadowing | |
84 (lookup-key keymap key)) | |
85 ;; define-key will give an error if a prefix | |
86 ;; of the key is already defined. Otherwise | |
87 ;; it will define the key in the map. | |
88 ;; #### - Perhaps this should be protected? | |
89 (define-key | |
90 keymap | |
91 (vconcat prefix (list key)) | |
92 newdef)))) | |
93 map) | |
94 ))) | |
95 | |
96 | |
97 ;; From Bill Dubuque <wgd@martigny.ai.mit.edu> | |
98 | |
99 ;; This used to wrap forms into an interactive lambda. It is unclear | |
100 ;; to me why this is needed in this function. Anyway, | |
101 ;; `key-or-menu-binding' doesn't do it, so this function no longer | |
102 ;; does it, either. | |
103 (defun insert-key-binding (key) ; modeled after describe-key | |
104 "Insert the command bound to KEY." | |
105 (interactive "kInsert command bound to key: ") | |
106 (let ((defn (key-or-menu-binding key))) | |
107 (if (or (null defn) (integerp defn)) | |
108 (error "%s is undefined" (key-description key)) | |
109 (if (or (stringp defn) (vectorp defn)) | |
110 (setq defn (key-binding defn))) ;; a keyboard macro | |
111 (insert (format "%s" defn))))) | |
112 | |
113 ;; From Bill Dubuque <wgd@martigny.ai.mit.edu> | |
114 (defun read-command-or-command-sexp (prompt) | |
115 "Read a command symbol or command sexp. | |
116 A command sexp is wrapped in an interactive lambda if needed. | |
117 Prompts with PROMPT." | |
118 ;; Todo: it would be better if we could reject symbols that are not | |
119 ;; commandp (as does 'read-command') but that is not easy to do | |
120 ;; because we must supply arg4 = require-match = nil for sexp case. | |
121 (let ((result (car (read-from-string | |
122 (completing-read prompt obarray 'commandp))))) | |
123 (if (and (consp result) | |
124 (not (eq (car result) 'lambda))) | |
125 `(lambda () | |
126 (interactive) | |
127 ,result) | |
128 result))) | |
129 | |
130 (defun local-key-binding (keys) | |
131 "Return the binding for command KEYS in current local keymap only. | |
132 KEYS is a string, a vector of events, or a vector of key-description lists | |
133 as described in the documentation for the `define-key' function. | |
134 The binding is probably a symbol with a function definition; see | |
135 the documentation for `lookup-key' for more information." | |
136 (let ((map (current-local-map))) | |
137 (if map | |
138 (lookup-key map keys) | |
139 nil))) | |
140 | |
141 (defun global-key-binding (keys) | |
142 "Return the binding for command KEYS in current global keymap only. | |
143 KEYS is a string or vector of events, a sequence of keystrokes. | |
144 The binding is probably a symbol with a function definition; see | |
145 the documentation for `lookup-key' for more information." | |
146 (lookup-key (current-global-map) keys)) | |
147 | |
148 ;; from Bill Dubuque <wgd@martigny.ai.mit.edu> | |
149 (defun global-set-key (key command) | |
150 "Give KEY a global binding as COMMAND. | |
151 COMMAND is a symbol naming an interactively-callable function. | |
152 KEY is a string, a vector of events, or a vector of key-description lists | |
153 as described in the documentation for the `define-key' function. | |
154 Note that if KEY has a local binding in the current buffer | |
155 that local binding will continue to shadow any global binding." | |
156 ;;(interactive "KSet key globally: \nCSet key %s to command: ") | |
157 (interactive (list (setq key (read-key-sequence "Set key globally: ")) | |
158 ;; Command sexps are allowed here so that this arg | |
159 ;; may be supplied interactively via insert-key-binding. | |
160 (read-command-or-command-sexp | |
161 (format "Set key %s to command: " | |
162 (key-description key))))) | |
163 (define-key (current-global-map) key command) | |
164 nil) | |
165 | |
166 ;; from Bill Dubuque <wgd@martigny.ai.mit.edu> | |
167 (defun local-set-key (key command) | |
168 "Give KEY a local binding as COMMAND. | |
169 COMMAND is a symbol naming an interactively-callable function. | |
170 KEY is a string, a vector of events, or a vector of key-description lists | |
171 as described in the documentation for the `define-key' function. | |
172 The binding goes in the current buffer's local map, | |
173 which is shared with other buffers in the same major mode." | |
174 ;;(interactive "KSet key locally: \nCSet key %s locally to command: ") | |
175 (interactive (list (setq key (read-key-sequence "Set key locally: ")) | |
176 ;; Command sexps are allowed here so that this arg | |
177 ;; may be supplied interactively via insert-key-binding. | |
178 (read-command-or-command-sexp | |
179 (format "Set key %s locally to command: " | |
180 (key-description key))))) | |
181 (if (null (current-local-map)) | |
182 (use-local-map (make-sparse-keymap))) | |
183 (define-key (current-local-map) key command) | |
184 nil) | |
185 | |
186 (defun global-unset-key (key) | |
187 "Remove global binding of KEY. | |
188 KEY is a string, a vector of events, or a vector of key-description lists | |
189 as described in the documentation for the `define-key' function." | |
190 (interactive "kUnset key globally: ") | |
191 (global-set-key key nil)) | |
192 | |
193 (defun local-unset-key (key) | |
194 "Remove local binding of KEY. | |
195 KEY is a string, a vector of events, or a vector of key-description lists | |
196 as described in the documentation for the `define-key' function." | |
197 (interactive "kUnset key locally: ") | |
198 (if (current-local-map) | |
199 (define-key (current-local-map) key nil))) | |
200 | |
201 | |
202 ;; Yet more RMS brain-death. | |
203 (defun minor-mode-key-binding (key &optional accept-default) | |
204 "Find the visible minor mode bindings of KEY. | |
205 Return an alist of pairs (MODENAME . BINDING), where MODENAME is | |
206 the symbol which names the minor mode binding KEY, and BINDING is | |
207 KEY's definition in that mode. In particular, if KEY has no | |
208 minor-mode bindings, return nil. If the first binding is a | |
209 non-prefix, all subsequent bindings will be omitted, since they would | |
210 be ignored. Similarly, the list doesn't include non-prefix bindings | |
211 that come after prefix bindings. | |
212 | |
213 If optional argument ACCEPT-DEFAULT is non-nil, recognize default | |
214 bindings; see the description of `lookup-key' for more details about this." | |
215 (let ((tail minor-mode-map-alist) | |
216 a s v) | |
217 (while tail | |
218 (setq a (car tail) | |
219 tail (cdr tail)) | |
220 (and (consp a) | |
221 (symbolp (setq s (car a))) | |
222 (boundp s) | |
223 (symbol-value s) | |
224 ;; indirect-function deals with autoloadable keymaps | |
225 (setq v (indirect-function (cdr a))) | |
226 (setq v (lookup-key v key accept-default)) | |
227 ;; Terminate loop, with v set to non-nil value | |
228 (setq tail nil))) | |
229 v)) | |
230 | |
231 | |
232 (defun current-minor-mode-maps () | |
233 "Return a list of keymaps for the minor modes of the current buffer." | |
234 (let ((l '()) | |
235 (tail minor-mode-map-alist) | |
236 a s v) | |
237 (while tail | |
238 (setq a (car tail) | |
239 tail (cdr tail)) | |
240 (and (consp a) | |
241 (symbolp (setq s (car a))) | |
242 (boundp s) | |
243 (symbol-value s) | |
244 ;; indirect-function deals with autoloadable keymaps | |
245 (setq v (indirect-function (cdr a))) | |
246 (setq l (cons v l)))) | |
247 (nreverse l))) | |
248 | |
249 | |
250 ;;#### What a crock | |
251 (defun define-prefix-command (name &optional mapvar) | |
252 "Define COMMAND as a prefix command. | |
253 A new sparse keymap is stored as COMMAND's function definition. | |
254 If second optional argument MAPVAR is not specified, | |
255 COMMAND's value (as well as its function definition) is set to the keymap. | |
256 If a second optional argument MAPVAR is given and is not `t', | |
257 the map is stored as its value. | |
258 Regardless of MAPVAR, COMMAND's function-value is always set to the keymap." | |
259 (let ((map (make-sparse-keymap name))) | |
260 (fset name map) | |
261 (cond ((not mapvar) | |
262 (set name map)) | |
263 ((eq mapvar 't) | |
264 ) | |
265 (t | |
266 (set mapvar map))) | |
267 name)) | |
268 | |
269 | |
270 ;;; Converting vectors of events to a read-equivalent form. | |
271 ;;; This is used both by call-interactively (for the command history) | |
272 ;;; and by macros.el (for saving keyboard macros to a file). | |
273 | |
274 ;; ### why does (events-to-keys [backspace]) return "\C-h"? | |
275 ;; BTW, this function is a mess, and macros.el does *not* use it, in | |
276 ;; spite of the above comment. `format-kbd-macro' is used to save | |
277 ;; keyboard macros to a file. | |
278 (defun events-to-keys (events &optional no-mice) | |
279 "Given a vector of event objects, returns a vector of key descriptors, | |
280 or a string (if they all fit in the ASCII range). | |
281 Optional arg NO-MICE means that button events are not allowed." | |
282 (if (and events (symbolp events)) (setq events (vector events))) | |
283 (cond ((stringp events) | |
284 events) | |
285 ((not (vectorp events)) | |
286 (signal 'wrong-type-argument (list 'vectorp events))) | |
287 ((let* ((length (length events)) | |
288 (string (make-string length 0)) | |
289 c ce | |
290 (i 0)) | |
291 (while (< i length) | |
292 (setq ce (aref events i)) | |
293 (or (eventp ce) (setq ce (character-to-event ce))) | |
294 ;; Normalize `c' to `?c' and `(control k)' to `?\C-k' | |
295 ;; By passing t for the `allow-meta' arg we could get kbd macros | |
296 ;; with meta in them to translate to the string form instead of | |
297 ;; the list/symbol form; but I expect that would cause confusion, | |
298 ;; so let's use the list/symbol form whenever there's | |
299 ;; any ambiguity. | |
300 (setq c (event-to-character ce)) | |
301 (if (and c | |
302 character-set-property | |
303 (key-press-event-p ce)) | |
304 (cond ((symbolp (event-key ce)) | |
305 (if (get (event-key ce) character-set-property) | |
306 ;; Don't use a string for `backspace' and `tab' to | |
307 ;; avoid that unpleasant little ambiguity. | |
308 (setq c nil))) | |
309 ((and (= (event-modifier-bits ce) 1) ;control | |
310 (integerp (event-key ce))) | |
311 (let* ((te (character-to-event c))) | |
312 (if (and (symbolp (event-key te)) | |
313 (get (event-key te) character-set-property)) | |
314 ;; Don't "normalize" (control i) to tab | |
315 ;; to avoid the ambiguity in the other direction | |
316 (setq c nil)) | |
317 (deallocate-event te))))) | |
318 (if c | |
319 (aset string i c) | |
320 (setq i length string nil)) | |
321 (setq i (1+ i))) | |
322 string)) | |
323 (t | |
324 (let* ((length (length events)) | |
325 (new (copy-sequence events)) | |
326 event mods key | |
327 (i 0)) | |
328 (while (< i length) | |
329 (setq event (aref events i)) | |
330 (cond ((key-press-event-p event) | |
331 (setq mods (event-modifiers event) | |
332 key (event-key event)) | |
333 (if (numberp key) | |
334 (setq key (intern (make-string 1 key)))) | |
335 (aset new i (if mods | |
336 (nconc mods (cons key nil)) | |
337 key))) | |
338 ((misc-user-event-p event) | |
339 (aset new i (list 'menu-selection | |
340 (event-function event) | |
341 (event-object event)))) | |
342 ((or (button-press-event-p event) | |
343 (button-release-event-p event)) | |
344 (if no-mice | |
345 (error | |
346 "Mouse events can't be saved in keyboard macros.")) | |
347 (setq mods (event-modifiers event) | |
348 key (intern (concat "button" | |
349 (event-button event) | |
350 (if (button-release-event-p event) | |
351 "up" "")))) | |
352 (aset new i (if mods | |
353 (nconc mods (cons key nil)) | |
354 key))) | |
355 ((or (and event (symbolp event)) | |
356 (and (consp event) (symbolp (car event)))) | |
357 (aset new i event)) | |
358 (t | |
359 (signal 'wrong-type-argument (list 'eventp event)))) | |
360 (setq i (1+ i))) | |
361 new)))) | |
362 | |
363 | |
364 (defun next-key-event () | |
365 "Return the next available keyboard event." | |
366 (let (event) | |
367 (while (not (key-press-event-p (setq event (next-command-event)))) | |
368 (dispatch-event event)) | |
369 event)) | |
370 | |
371 (defun key-sequence-list-description (keys) | |
372 "Convert a key sequence KEYS to the full [(modifiers... key)...] form. | |
373 Argument KEYS can be in any form accepted by `define-key' function." | |
374 (let ((vec | |
375 (cond ((vectorp keys) | |
376 keys) | |
377 ((stringp keys) | |
378 (vconcat keys)) | |
379 (t | |
380 (vector keys)))) | |
381 (event-to-list | |
382 #'(lambda (ev) | |
383 (append (event-modifiers ev) (list (event-key ev)))))) | |
384 (mapvector | |
385 #'(lambda (key) | |
386 (cond ((key-press-event-p key) | |
387 (funcall event-to-list key)) | |
388 ((characterp key) | |
389 (funcall event-to-list (character-to-event key))) | |
390 ((listp key) | |
391 key) | |
392 (t | |
393 (list key)))) | |
394 vec))) | |
395 | |
396 | |
397 ;;; Support keyboard commands to turn on various modifiers. | |
398 | |
399 ;;; These functions -- which are not commands -- each add one modifier | |
400 ;;; to the following event. | |
401 | |
402 (defun event-apply-alt-modifier (ignore-prompt) | |
403 (event-apply-modifier 'alt)) | |
404 (defun event-apply-super-modifier (ignore-prompt) | |
405 (event-apply-modifier 'super)) | |
406 (defun event-apply-hyper-modifier (ignore-prompt) | |
407 (event-apply-modifier 'hyper)) | |
408 (defun event-apply-shift-modifier (ignore-prompt) | |
409 (event-apply-modifier 'shift)) | |
410 (defun event-apply-control-modifier (ignore-prompt) | |
411 (event-apply-modifier 'control)) | |
412 (defun event-apply-meta-modifier (ignore-prompt) | |
413 (event-apply-modifier 'meta)) | |
414 | |
415 ;;; #### `key-translate-map' is ignored for now. | |
416 (defun event-apply-modifier (symbol) | |
417 "Return the next key event, with a modifier flag applied. | |
418 SYMBOL is the name of this modifier, as a symbol. | |
419 `function-key-map' is scanned for prefix bindings." | |
420 (let (events binding) | |
421 ;; read keystrokes scanning `function-key-map' | |
422 (while (keymapp | |
423 (setq binding | |
424 (lookup-key | |
425 function-key-map | |
426 (vconcat | |
427 (setq events | |
428 (append events (list (next-key-event))))))))) | |
429 (if binding ; found a binding | |
430 (progn | |
431 ;; allow for several modifiers | |
432 (if (and (symbolp binding) (fboundp binding)) | |
433 (setq binding (funcall binding nil))) | |
434 (setq events (append binding nil)) | |
435 ;; put remaining keystrokes back into input queue | |
436 (setq unread-command-events | |
437 (mapcar 'character-to-event (cdr events)))) | |
438 (setq unread-command-events (cdr events))) | |
439 ;; add a modifier SYMBOL to the first keystroke or event | |
440 (vector | |
441 (append (list symbol) | |
442 (delq symbol | |
443 (aref (key-sequence-list-description (car events)) 0)))))) | |
444 | |
445 (defun synthesize-keysym (ignore-prompt) | |
446 "Read a sequence of keys, and returned the corresponding key symbol. | |
447 The characters must be from the [-_a-zA-Z0-9]. Reading is terminated | |
448 by RET (which is discarded)." | |
449 (let ((continuep t) | |
450 event char list) | |
451 (while continuep | |
452 (setq event (next-key-event)) | |
453 (cond ((and (setq char (event-to-character event)) | |
454 (or (memq char '(?- ?_)) | |
455 (eq ?w (char-syntax char (standard-syntax-table))))) | |
456 ;; Advance a character. | |
457 (push char list)) | |
458 ((or (memq char '(?\r ?\n)) | |
459 (memq (event-key event) '(return newline))) | |
460 ;; Legal termination. | |
461 (setq continuep nil)) | |
462 (char | |
463 ;; Illegal character. | |
464 (error "Illegal character in keysym: %c" char)) | |
465 (t | |
466 ;; Illegal event. | |
467 (error "Event has no character equivalent: %s" event)))) | |
468 (vector (intern (concat "" (nreverse list)))))) | |
469 | |
470 ;; This looks dirty. The following code should maybe go to another | |
471 ;; file, and `create-console-hook' should maybe default to nil. | |
472 (add-hook | |
473 'create-console-hook | |
474 #'(lambda (console) | |
475 (letf (((selected-console) console)) | |
476 (define-key function-key-map [?\C-x ?@ ?h] 'event-apply-hyper-modifier) | |
477 (define-key function-key-map [?\C-x ?@ ?s] 'event-apply-super-modifier) | |
478 (define-key function-key-map [?\C-x ?@ ?m] 'event-apply-meta-modifier) | |
479 (define-key function-key-map [?\C-x ?@ ?S] 'event-apply-shift-modifier) | |
480 (define-key function-key-map [?\C-x ?@ ?c] 'event-apply-control-modifier) | |
481 (define-key function-key-map [?\C-x ?@ ?a] 'event-apply-alt-modifier) | |
482 (define-key function-key-map [?\C-x ?@ ?k] 'synthesize-keysym)))) | |
483 | |
484 ;;; keymap.el ends here |