add command move-end-of-line
[lice.git] / src / keymap.lisp
blob62ca9740ad1c8e83d980eec50111189d68af6a25
1 ;;; keymaps for lice
3 (in-package "LICE")
5 ;; for mouse click events
6 (defstruct click where button)
8 (defstruct key char control meta alt shift hyper super)
9 ;; (defclass key ()
10 ;; ((char :type character :initarg :char :reader key-char)
11 ;; (control :type boolean :initform nil :initarg :control :reader key-control)
12 ;; (meta :type boolean :initform nil :initarg :meta :reader key-meta)
13 ;; (alt :type boolean :initform nil :initarg :alt :reader key-alt)
14 ;; (shift :type boolean :initform nil :initarg :shift :reader key-shift)
15 ;; (hyper :type boolean :initform nil :initarg :hyper :reader key-hyper)
16 ;; (super :type boolean :initform nil :initarg :super :reader key-super))
17 ;; (:documentation "A key event."))
19 (defun print-mods (key)
20 (concatenate 'string
21 (when (key-control key) "C-")
22 (when (key-meta key) "M-")
23 (when (key-alt key) "A-")
24 (when (key-shift key) "S-")
25 (when (key-super key) "s-")
26 (when (key-hyper key) "H-")))
28 (defun print-key (key)
29 (format nil "~a~a" (print-mods key) (key-char key)))
31 (defmethod print-object ((obj key) stream)
32 (print-unreadable-object (obj stream :type t :identity t)
33 (format stream "~s" (print-key obj))))
35 (define-condition kbd-parse (lice-condition)
36 () (:documentation "Raised when a kbd string failed to parse."))
38 (defun parse-mods (mods end)
39 "MODS is a sequence of <MOD CHAR> #\- pairs. Return a list suitable
40 for passing as the last argument to (apply #'make-key ...)"
41 (unless (evenp end)
42 (signal 'kbd-parse))
43 (apply #'nconc (loop for i from 0 below end by 2
44 if (char/= (char mods (1+ i)) #\-)
45 do (signal 'kbd-parse)
46 collect (case (char mods i)
47 (#\M (list :meta t))
48 (#\A (list :alt t))
49 (#\C (list :control t))
50 (#\H (list :hyper t))
51 (#\s (list :super t))
52 (#\S (list :shift t))
53 (t (signal 'kbd-parse))))))
55 (defvar *keysyms* nil
56 "An alist of keysyms that map a string to either a character or a symbol.")
58 (defmacro define-keysym (string thing)
59 `(pushnew (cons ,string ,thing) *keysyms* :test 'equal))
61 (define-keysym "RET" #\Newline)
62 (define-keysym "TAB" #\Tab)
63 (define-keysym "SPC" #\Space)
65 (define-keysym "up" :up)
66 (define-keysym "down" :down)
67 (define-keysym "left" :left)
68 (define-keysym "right" :right)
69 (define-keysym "prior" :prior)
71 (defun parse-char-name (string)
72 "Return the character whose name is STRING."
73 (or (let ((sym (find string *keysyms* :test 'string= :key 'car)))
74 (when sym
75 (cdr sym)))
76 (name-char string)
77 (and (= (length string) 1)
78 (char string 0))))
80 (defun parse-key (string)
81 "Parse STRING and return a key structure."
82 ;; FIXME: we want to return NIL when we get a kbd-parse error
83 ;;(ignore-errors
84 (let* ((p (when (> (length string) 2)
85 (position #\- string :from-end t :end (- (length string) 1))))
86 (mods (parse-mods string (if p (1+ p) 0)))
87 (ch (parse-char-name (subseq string (if p (1+ p) 0)))))
88 (and ch
89 (apply #'make-key :char ch mods))))
91 (defun parse-key-seq (keys)
92 "KEYS is a key sequence. Parse it and return the list of keys."
93 (mapcar 'parse-key (split-string keys)))
95 (defun kbd (keys)
96 "Convert KEYS to the internal Emacs key representation.
97 KEYS should be a string constant in the format used for
98 saving keyboard macros ***(see `insert-kbd-macro')."
99 ;; XXX: define-key needs to be fixed to handle a list of keys
100 (first (parse-key-seq keys)))
102 ;; ;; XXX: This is hacky. Convert the class into a sequence. Maybe we should
103 ;; ;; use defstruct then?
104 ;; (defun key-hashid (event)
105 ;; (typecase event
106 ;; (key (list (key-char event)
107 ;; (key-control event)
108 ;; (key-meta event)
109 ;; (key-alt event)
110 ;; (key-hyper event)
111 ;; (key-super event)))
112 ;; (t t)))
114 (defvar *current-keymap-theme* :lice)
116 (defvar *overriding-terminal-local-map* nil
117 "Per-terminal keymap that overrides all other local keymaps.
118 If this variable is non-nil, it is used as a keymap instead of the
119 buffer's local map, and the minor mode keymaps and text property keymaps.
120 It also replaces `overriding-local-map'.
122 This variable is intended to let commands such as `universal-argument'
123 set up a different keymap for reading the next command.")
125 (defvar *overriding-local-map* nil
126 "Keymap that overrides all other local keymaps.
127 If this variable is non-nil, it is used as a keymap--replacing the
128 buffer's local map, the minor mode keymaps, and char property keymaps.")
130 (defclass keymap ()
131 ((parent :initform nil :initarg :parent :accessor keymap-parent)
132 (prompt :initform nil :initarg :prompt :accessor keymap-prompt)
133 (themes :initform (make-hash-table) :accessor keymap-themes)))
135 (defun keymapp (object)
136 (typep object 'keymap))
138 (defun make-sparse-keymap (&optional prompt)
139 "Construct and return a new sparse keymap.
140 The optional arg STRING supplies a menu name for the keymap
141 in case you use it as a menu with `x-popup-menu'."
142 (make-instance 'keymap :prompt prompt))
144 (defun get-keymap-theme (keymap theme)
145 (gethash theme (keymap-themes keymap)))
147 (defun get-keymap-theme-create (keymap theme)
148 (or (get-keymap-theme keymap theme)
149 (setf (gethash theme (keymap-themes keymap)) (make-hash-table :size 200 :test 'equalp))))
151 (defgeneric define-key (keymap key def &optional theme)
152 (:documentation "In keymap, define key sequence key as def.
153 keymap is a keymap."))
155 (defmethod define-key (keymap (key vector) def &optional (theme :lice))
156 "for some weirdness in bindings.lisp"
157 (warn "unimplemented define-key"))
159 (defmethod define-key (keymap (key click) def &optional (theme :lice))
160 "Mouse click events"
161 (warn "unimplemented define-key"))
163 (defmethod define-key (keymap (key string) (def string) &optional (theme :lice))
164 "alias a key to another key."
165 (warn "unimplemented define-key"))
167 (defmethod define-key (keymap (key symbol) def &optional (theme :lice))
168 "Special events are represented as symbols."
169 (warn "unimplemented define-key"))
171 (defmethod define-key (keymap (key string) def &optional (theme :lice))
172 (define-key keymap (parse-key-seq key) def theme))
174 (defmethod define-key (keymap (key list) def &optional (theme :lice))
175 (let ((map (lookup-key-internal keymap key nil theme nil t nil)))
176 ;; FIXME: do this error properly
177 (unless map (error "Key sequence %s starts with non-prefix key %s"))
178 (define-key map (car (last key)) def theme)))
180 (defmethod define-key (keymap (key key) def &optional (theme :lice))
181 (let ((map (get-keymap-theme-create keymap theme)))
182 (setf (gethash #|(key-hashid key)|# key map) def)))
184 (defun lookup-key-internal (keymap key accept-default theme norecurse return-kmap check-parents)
185 "RETURN-KMAP means return the key's keymap."
186 (let* ((map (get-keymap-theme keymap theme))
187 ;; some maps may not have a hash table for the theme.
188 (cmd (and map (gethash (if (consp key) (car key) key)
189 map))))
191 ;; if the binding is another keymap, then lookup the rest of the key sequence
192 (cond
193 ((and return-kmap
194 (= (length key) 1)
195 keymap))
196 ((and (keymapp cmd) (not norecurse))
197 (lookup-key-internal cmd (cdr key) accept-default theme norecurse return-kmap check-parents))
198 (t cmd))
199 ;; check parent for binding
200 (when (and check-parents (keymap-parent keymap))
201 (lookup-key-internal (keymap-parent keymap) key nil theme norecurse return-kmap check-parents))
202 (when accept-default
203 (and map (gethash t map))))))
205 (defun lookup-key (keymap key &optional accept-default (theme :lice))
206 "In keymap KEYMAP, look up key sequence KEY. Return the definition.
207 nil means undefined. See doc of `define-key' for kinds of definitions.
209 Normally, `lookup-key' ignores bindings for t, which act as default
210 bindings, used when nothing else in the keymap applies; this makes it
211 usable as a general function for probing keymaps. However, if the
212 third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will
213 recognize the default bindings, just as `read-key-sequence' does."
214 (check-type keymap keymap)
215 (lookup-key-internal keymap key accept-default theme nil nil t))
217 (depricate set-keymap-parent (setf keymap-parent))
218 (defun set-keymap-parent (keymap parent)
219 "Modify keymap to set its parent map to parent.
220 Return parent. parent should be nil or another keymap."
221 (setf (keymap-parent keymap) parent))
223 (defun make-keymap (&optional string)
224 (declare (ignore string))
225 (error "unimplemented make-keymap"))
227 (defun map-keymap (function keymap &optional (theme :lice))
228 "Call FUNCTION once for each event binding in KEYMAP.
229 FUNCTION is called with two arguments: the event that is bound, and
230 the definition it is bound to. If the event is an integer, it may be
231 a generic character (see Info node `(elisp)Splitting Characters'), and
232 that means that all actual character events belonging to that generic
233 character are bound to the definition.
235 If KEYMAP has a parent, the parent's bindings are included as well.
236 This works recursively: if the parent has itself a parent, then the
237 grandparent's bindings are also included and so on."
238 (let ((map (get-keymap-theme keymap theme)))
239 (maphash function map)
240 (when (keymap-parent keymap)
241 (map-keymap function (keymap-parent keymap) theme))))
243 (defvar *esc-map* (make-sparse-keymap)
244 "Default keymap for ESC (meta) commands.
245 The normal global definition of the character ESC indirects to this keymap.")
247 (defvar *global-map* (make-sparse-keymap)
248 "The top level global keymap.")
250 (defvar *ctl-x-4-map* (make-sparse-keymap)
251 "The C-x 4 keymap.")
253 (defvar *ctl-x-5-map* (make-sparse-keymap)
254 "The C-x 4 keymap.")
256 (defvar *ctl-x-map* (make-sparse-keymap)
257 "The C-x keymap.")
259 (defvar *ctl-c-map* (make-sparse-keymap)
260 "The C-c keymap.")
262 (defvar *ctl-h-map* (make-sparse-keymap)
263 "The C-h keymap.")
265 (defvar *function-key-map* (make-sparse-keymap)
266 "Keymap that translates key sequences to key sequences during input.
267 This is used mainly for mapping ASCII function key sequences into
268 real Emacs function key events (symbols).
270 The `read-key-sequence' function replaces any subsequence bound by
271 `function-key-map' with its binding. More precisely, when the active
272 keymaps have no binding for the current key sequence but
273 `function-key-map' binds a suffix of the sequence to a vector or string,
274 `read-key-sequence' replaces the matching suffix with its binding, and
275 continues with the new sequence.
277 If the binding is a function, it is called with one argument (the prompt)
278 and its return value (a key sequence) is used.
280 The events that come from bindings in `function-key-map' are not
281 themselves looked up in `function-key-map'.
283 For example, suppose `function-key-map' binds `ESC O P' to [f1].
284 Typing `ESC O P' to `read-key-sequence' would return [f1]. Typing
285 `C-x ESC O P' would return [?\\C-x f1]. If [f1] were a prefix
286 key, typing `ESC O P x' would return [f1 x].")
288 (defvar *current-global-map* *global-map*)
290 (defvar *current-kmap* nil
291 "The key map that the next key event will use to find a
292 corresponding command.")
294 ;; initialize a skeleton structure for the keymaps
295 (define-key *global-map* "ESC" *esc-map*)
296 (define-key *esc-map* "ESC" (make-sparse-keymap))
297 (define-key *global-map* "C-x" *ctl-x-map*)
298 (define-key *ctl-x-map* "n" (make-sparse-keymap))
299 (define-key *global-map* "C-c" *ctl-c-map*)
300 (define-key *global-map* "C-h" *ctl-h-map*)
301 (define-key *ctl-x-map* "r" (make-sparse-keymap))
302 (define-key *ctl-x-map* "a" (make-sparse-keymap))
303 (define-key *ctl-x-map* "a i" (make-sparse-keymap))
305 (defun copy-keymap (keymap)
306 (declare (ignore keymap))
307 (error "unimplemented copy-keymap"))
309 (defun command-remapping ()
310 (error "unimplemented command-remapping"))
312 (defun key-binding (key &optional accept-default no-remap)
313 (declare (ignore key accept-default no-remap))
314 (error "unimplemented key-binding"))
316 (defun local-key-binding ()
317 (error "unimplemented local-key-binding"))
319 (defun global-key-binding ()
320 (error "unimplemented global-key-binding"))
322 (defun minor-mode-key-binding ()
323 (error "unimplemented minor-mode-key-binding"))
325 (defun define-prefix-command ()
326 (error "unimplemented define-prefix-command"))
328 (defun use-global-map (keymap)
329 (check-type keymap keymap)
330 (setf *current-global-map* keymap))
332 (defun use-local-map (keymap)
333 "Select KEYMAP as the local keymap.
334 If KEYMAP is nil, that means no local keymap."
335 (check-type keymap keymap)
336 (setf (buffer-local-map (current-buffer)) keymap))
338 (defun current-local-map ()
339 "Return current buffer's local keymap, or nil if it has none.
341 LICE: the local map in really the major mode map. Except it might
342 not be in the future."
343 (buffer-local-map (current-buffer)))
345 (defun current-global-map ()
346 "Return the current global keymap."
347 *current-global-map*)
349 (defun current-minor-mode-maps ()
350 (error "unimplemented current-minor-mode-maps"))
352 (defun current-active-maps ()
353 (error "unimplemented current-active-maps"))
355 (defun accessible-keymaps ()
356 (error "unimplemented" accessible-keymaps))
358 (defun key-description ()
359 (error "unimplemented key-description"))
361 (defun describe-vector ()
362 (error "unimplemented describe-vector"))
364 (defun single-key-description ()
365 (error "unimplemented single-key-description"))
367 (defun text-char-description ()
368 (error "unimplemented text-char-description"))
370 (defun where-is-internal ()
371 (error "unimplemented where-is-internal"))
373 (defun describe-buffer-bindings ()
374 (error "unimplemented describe-buffer-bindings"))
376 (defun apropos-internal ()
377 (error "unimplemented apropos-internal"))
379 ;; This is a struct to make it easier to add new elements to, should
380 ;; we want to. Also, it makes code easier to read, I think.
381 (defstruct minor-mode-map
382 variable keymap)
384 (defvar *minor-mode-map-list* nil
385 "Alist of keymaps to use for minor modes.
386 Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read
387 key sequences and look up bindings iff VARIABLE's value is non-nil.
388 If two active keymaps bind the same key, the keymap appearing earlier
389 in the list takes precedence.")
391 (define-buffer-local *minor-mode-overriding-map-list* nil
392 "Alist of keymaps to use for minor modes, in current major mode.
393 This variable is an alist just like `*minor-mode-map-list*', and it is
394 used the same way (and before `*minor-mode-map-list*'); however,
395 it is provided for major modes to bind locally.")
398 ;; (defun make-ctrl-h-map ()
399 ;; (let ((kmap (make-sparse-keymap)))
400 ;; (define-key kmap (make-key :char #\f) 'describe-symbol)
401 ;; kmap))
403 ;; (defun make-ctrl-x-4-map ()
404 ;; (let ((kmap (make-sparse-keymap)))
405 ;; (define-key kmap (make-key :char #\b) 'switch-to-buffer-other-window)
406 ;; kmap))
408 ;; (defun make-ctrl-x-map (ctl-x-4-map)
409 ;; (let ((kmap (make-sparse-keymap)))
410 ;; (define-key kmap (make-key :char #\e :control t) 'eval-last-sexp)
411 ;; (define-key kmap (make-key :char #\b) 'switch-to-buffer)
412 ;; (define-key kmap (make-key :char #\c :control t) 'save-buffers-kill-emacs)
413 ;; (define-key kmap (make-key :char #\f :control t) 'find-file)
414 ;; (define-key kmap (make-key :char #\s :control t) 'save-buffer)
415 ;; (define-key kmap (make-key :char #\k) 'kill-buffer)
416 ;; (define-key kmap (make-key :char #\o) 'other-window)
417 ;; (define-key kmap (make-key :char #\1) 'delete-other-windows)
418 ;; (define-key kmap (make-key :char #\2) 'split-window-vertically)
419 ;; (define-key kmap (make-key :char #\3) 'split-window-horizontally)
420 ;; (define-key kmap (make-key :char #\x :control t) 'exchange-point-and-mark)
421 ;; (define-key kmap (make-key :char #\t :control t) 'transpose-lines)
422 ;; (define-key kmap (make-key :char #\4) ctl-x-4-map)
423 ;; kmap))
425 ;; (defun make-ctrl-c-map ()
426 ;; (let ((kmap (make-sparse-keymap)))
427 ;; kmap))
429 ;; (defun make-global-map (ctl-x-prefix ctl-c-prefix ctl-h-prefix)
430 ;; "Generate self-insert commands for all printable characters. And
431 ;; more."
432 ;; (let ((kmap (make-sparse-keymap)))
433 ;; (loop for i in '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
434 ;; #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j
435 ;; #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t
436 ;; #\u #\v #\w #\x #\y #\z
437 ;; #\A #\B #\C #\D #\E #\F #\G #\H #\I #\J
438 ;; #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T
439 ;; #\U #\V #\W #\X #\Y #\Z
440 ;; #\Space #\! #\" #\# #\$ #\% #\& #\' #\(
441 ;; #\) #\* #\+ #\, #\- #\. #\/ #\: #\; #\<
442 ;; #\= #\> #\? #\@ #\[ #\\ #\] #\^ #\_ #\`
443 ;; #\| #\} #\~ #\{)
444 ;; do (define-key kmap (make-key :char i) 'self-insert-command))
445 ;; (define-key kmap (make-key :char #\Return) 'newline)
446 ;; (define-key kmap (make-key :char #\Newline) 'newline)
447 ;; (define-key kmap (make-key :char #\o :control t) 'open-line)
448 ;; (define-key kmap (make-key :char #\j :control t) 'newline)
449 ;; (define-key kmap (make-key :char #\m :control t) 'newline)
450 ;; (define-key kmap (make-key :char #\f :control t) 'forward-char)
451 ;; (define-key kmap (make-key :char #\f :meta t) 'forward-word)
452 ;; (define-key kmap (make-key :char #\f :control t :meta t) 'forward-sexp)
453 ;; (define-key kmap (make-key :char #\b :control t :meta t) 'backward-sexp)
454 ;; (define-key kmap (make-key :char #\n :control t) 'next-line)
455 ;; (define-key kmap (make-key :char #\p :control t) 'previous-line)
456 ;; (define-key kmap (make-key :char #\b :control t) 'backward-char)
457 ;; (define-key kmap (make-key :char #\b :meta t) 'backward-word)
458 ;; (define-key kmap (make-key :char #\d :control t) 'delete-char)
459 ;; (define-key kmap (make-key :char #\d :meta t) 'kill-word)
460 ;; (define-key kmap (make-key :char #\Rubout :meta t) 'backward-kill-word)
461 ;; (define-key kmap (make-key :char #\Rubout) 'delete-backward-char)
462 ;; (define-key kmap (make-key :char #\Delete) 'delete-backward-char)
463 ;; (define-key kmap (make-key :char #\t :meta t) 'transpose-words)
464 ;; (define-key kmap (make-key :char #\t :control t) 'transpose-chars)
465 ;; ;;(define-key kmap (make-key :char #\h :control t) 'delete-backward-char)
466 ;; (define-key kmap (make-key :char #\u :control t) 'universal-argument)
467 ;; (define-key kmap (make-key :char #\a :control t) 'beginning-of-line)
468 ;; (define-key kmap (make-key :char #\e :control t) 'end-of-line)
469 ;; (define-key kmap (make-key :char #\g :control t) 'keyboard-quit)
470 ;; (define-key kmap (make-key :char #\v :control t) 'scroll-up)
471 ;; (define-key kmap (make-key :char #\v :meta t) 'scroll-down)
472 ;; (define-key kmap (make-key :char #\k :control t) 'kill-line)
473 ;; (define-key kmap (make-key :char #\w :control t) 'kill-region)
474 ;; (define-key kmap (make-key :char #\y :control t) 'yank)
475 ;; (define-key kmap (make-key :char #\y :meta t) 'yank-pop)
476 ;; (define-key kmap (make-key :char #\w :meta t) 'kill-ring-save)
477 ;; (define-key kmap (make-key :char #\> :meta t) 'end-of-buffer)
478 ;; (define-key kmap (make-key :char #\< :meta t) 'beginning-of-buffer)
479 ;; (define-key kmap (make-key :char #\x :meta t) 'execute-extended-command)
480 ;; (define-key kmap (make-key :char #\: :meta t) 'eval-expression)
481 ;; (define-key kmap (make-key :char #\Space :control t) 'set-mark-command)
482 ;; (define-key kmap (make-key :char #\` :control t) 'set-mark-command)
483 ;; (define-key kmap (make-key :char #\! :meta t) 'shell-command)
484 ;; (define-key kmap (make-key :char #\Space :meta t) 'just-one-space)
485 ;; (define-key kmap (make-key :char #\\ :control t :meta t) 'indent-region)
486 ;; (define-key kmap (make-key :char #\a :control t :meta t) 'beginning-of-defun)
487 ;; (define-key kmap (make-key :char #\e :control t :meta t) 'end-of-defun)
488 ;; (define-key kmap (make-key :char #\_ :control t) 'undo)
489 ;; (define-key kmap (make-key :char #\/ :control t) 'undo)
490 ;; (define-key kmap (make-key :char #\} :meta t) 'forward-paragraph)
491 ;; (define-key kmap (make-key :char #\{ :meta t) 'backward-paragraph)
492 ;; (define-key kmap (make-key :char #\x :control t) ctl-x-prefix)
493 ;; (define-key kmap (make-key :char #\c :control t) ctl-c-prefix)
494 ;; (define-key kmap (make-key :char #\h :control t) ctl-h-prefix)
495 ;; kmap))
497 ;; (defun make-global-keymaps ()
498 ;; "Create the default global keymaps and store them in *global-kmap
499 ;; *ctl-x-map*, ..."
500 ;; (setf *ctl-x-4-map* (make-ctrl-x-4-map)
501 ;; *ctl-x-map* (make-ctrl-x-map *ctl-x-4-map*)
502 ;; *ctl-c-map* (make-ctrl-c-map)
503 ;; *ctl-h-map* (make-ctrl-h-map)
504 ;; *global-map* (make-global-map *ctl-x-map* *ctl-c-map* *ctl-h-map*)))