Skip to content

Commit 4caa7a8

Browse files
committed
Precede vi-mode keymaps over major-mode.
1 parent 04c7b9c commit 4caa7a8

12 files changed

+177
-142
lines changed

extensions/vi-mode/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ To enable, add the following code to `~/.lem/init.lisp`:
1212

1313
```common-lisp
1414
;; NORMAL mode
15-
(define-key lem-vi-mode:*command-keymap* "q" 'quit-window)
16-
(define-key lem-vi-mode:*command-keymap* "Space @" 'paredit-splice)
15+
(define-key lem-vi-mode:*normal-keymap* "q" 'quit-window)
16+
(define-key lem-vi-mode:*normal-keymap* "Space @" 'paredit-splice)
1717
1818
;; INSERT mode
1919
(define-key lem-vi-mode:*insert-keymap* "(" 'paredit-insert-paren)

extensions/vi-mode/binds.lisp

+104-104
Original file line numberDiff line numberDiff line change
@@ -9,118 +9,118 @@
99
:lem-vi-mode/visual))
1010
(in-package :lem-vi-mode/binds)
1111

12-
(define-key *command-keymap* "0" 'vi-move-to-beginning-of-line/universal-argument-0)
13-
(define-key *command-keymap* "1" 'universal-argument-1)
14-
(define-key *command-keymap* "2" 'universal-argument-2)
15-
(define-key *command-keymap* "3" 'universal-argument-3)
16-
(define-key *command-keymap* "4" 'universal-argument-4)
17-
(define-key *command-keymap* "5" 'universal-argument-5)
18-
(define-key *command-keymap* "6" 'universal-argument-6)
19-
(define-key *command-keymap* "7" 'universal-argument-7)
20-
(define-key *command-keymap* "8" 'universal-argument-8)
21-
(define-key *command-keymap* "9" 'universal-argument-9)
22-
(define-key *command-keymap* "l" 'vi-forward-char)
23-
(define-key *command-keymap* "Space" 'vi-forward-char)
24-
(define-key *command-keymap* "h" 'vi-backward-char)
25-
(define-key *command-keymap* "j" 'vi-next-line)
26-
(define-key *command-keymap* "+" 'vi-next-line)
27-
(define-key *command-keymap* "k" 'vi-previous-line)
28-
(define-key *command-keymap* "-" 'vi-previous-line)
29-
(define-key *command-keymap* "g j" 'vi-next-display-line)
30-
(define-key *command-keymap* "g k" 'vi-previous-display-line)
31-
(define-key *command-keymap* "w" 'vi-forward-word-begin)
32-
(define-key *command-keymap* "b" 'vi-backward-word-begin)
33-
(define-key *command-keymap* "W" 'vi-forward-word-begin-broad)
34-
(define-key *command-keymap* "B" 'vi-backward-word-begin-broad)
35-
(define-key *command-keymap* "e" 'vi-forward-word-end)
36-
(define-key *command-keymap* "E" 'vi-forward-word-end-broad)
37-
(define-key *command-keymap* "$" 'vi-move-to-end-of-line)
38-
(define-key *command-keymap* "g _" 'vi-move-to-last-nonblank)
39-
(define-key *command-keymap* "H" 'vi-move-to-window-top)
40-
(define-key *command-keymap* "M" 'vi-move-to-window-middle)
41-
(define-key *command-keymap* "L" 'vi-move-to-window-bottom)
42-
(define-key *command-keymap* "C-d" 'next-page)
43-
(define-key *command-keymap* "C-u" 'previous-page)
44-
(define-key *command-keymap* "^" 'vi-back-to-indentation)
45-
(define-key *command-keymap* "_" 'vi-back-to-indentation)
46-
(define-key *command-keymap* "=" 'vi-indent)
47-
(define-key *command-keymap* "{" 'backward-paragraph)
48-
(define-key *command-keymap* "}" 'forward-paragraph)
49-
(define-key *command-keymap* "s" 'vi-substitute)
50-
(define-key *command-keymap* "x" 'vi-delete-next-char)
51-
(define-key *command-keymap* "X" 'vi-delete-previous-char)
52-
(define-key *command-keymap* "d" 'vi-delete)
53-
(define-key *command-keymap* "D" 'vi-delete-line)
54-
(define-key *command-keymap* "c" 'vi-change)
55-
(define-key *command-keymap* "C" 'vi-change-line)
56-
(define-key *command-keymap* "g J" 'vi-join)
57-
(define-key *command-keymap* "J" 'vi-join-line)
58-
(define-key *command-keymap* "y" 'vi-yank)
59-
(define-key *command-keymap* "p" 'vi-paste-after)
60-
(define-key *command-keymap* "P" 'vi-paste-before)
61-
(define-key *command-keymap* "r" 'vi-replace-char)
62-
(define-key *command-keymap* "g U" 'vi-upcase)
63-
(define-key *command-keymap* "g u" 'vi-downcase)
64-
(define-key *command-keymap* "u" 'vi-undo)
65-
(define-key *command-keymap* "C-r" 'vi-redo)
66-
(define-key *command-keymap* "C-f" 'next-page)
67-
(define-key *command-keymap* "C-b" 'previous-page)
68-
(define-key *command-keymap* "%" 'vi-move-to-matching-paren)
69-
(define-key *command-keymap* "/" 'vi-search-forward)
70-
(define-key *command-keymap* "?" 'vi-search-backward)
71-
(define-key *command-keymap* "n" 'vi-search-next)
72-
(define-key *command-keymap* "N" 'vi-search-previous)
73-
(define-key *command-keymap* "*" 'vi-search-forward-symbol-at-point)
74-
(define-key *command-keymap* "g g" 'vi-goto-first-line)
75-
(define-key *command-keymap* "G" 'vi-goto-line)
76-
(define-key *command-keymap* "Return" 'vi-return)
77-
(define-key *command-keymap* "f" 'vi-find-char)
78-
(define-key *command-keymap* "F" 'vi-find-char-backward)
79-
(define-key *command-keymap* "t" 'vi-find-char-before)
80-
(define-key *command-keymap* "T" 'vi-find-char-backward-after)
81-
(define-key *command-keymap* ";" 'vi-find-char-repeat)
82-
(define-key *command-keymap* "," 'vi-find-char-repeat-backward)
83-
(define-key *command-keymap* "z z" 'recenter)
84-
(define-key *command-keymap* "Z Z" 'vi-write-quit)
85-
(define-key *command-keymap* "C-w s" 'split-active-window-vertically)
86-
(define-key *command-keymap* "C-w C-s" 'split-active-window-vertically)
87-
(define-key *command-keymap* "C-w w" 'other-window)
88-
(define-key *command-keymap* "C-w C-w" 'other-window)
89-
(define-key *command-keymap* "C-w q" 'vi-quit)
90-
(define-key *command-keymap* "C-w h" 'window-move-left)
91-
(define-key *command-keymap* "C-w C-h" 'undefined-key)
92-
(define-key *command-keymap* "C-w l" 'window-move-right)
93-
(define-key *command-keymap* "C-w C-l" 'undefined-key)
94-
(define-key *command-keymap* "C-w k" 'window-move-up)
95-
(define-key *command-keymap* "C-w C-k" 'undefined-key)
96-
(define-key *command-keymap* "C-w j" 'window-move-down)
97-
(define-key *command-keymap* "C-w C-j" 'undefined-key)
12+
(define-key *motion-keymap* "0" 'vi-move-to-beginning-of-line/universal-argument-0)
13+
(define-key *motion-keymap* "1" 'universal-argument-1)
14+
(define-key *motion-keymap* "2" 'universal-argument-2)
15+
(define-key *motion-keymap* "3" 'universal-argument-3)
16+
(define-key *motion-keymap* "4" 'universal-argument-4)
17+
(define-key *motion-keymap* "5" 'universal-argument-5)
18+
(define-key *motion-keymap* "6" 'universal-argument-6)
19+
(define-key *motion-keymap* "7" 'universal-argument-7)
20+
(define-key *motion-keymap* "8" 'universal-argument-8)
21+
(define-key *motion-keymap* "9" 'universal-argument-9)
22+
(define-key *motion-keymap* "l" 'vi-forward-char)
23+
(define-key *motion-keymap* "Space" 'vi-forward-char)
24+
(define-key *motion-keymap* "h" 'vi-backward-char)
25+
(define-key *motion-keymap* "j" 'vi-next-line)
26+
(define-key *motion-keymap* "+" 'vi-next-line)
27+
(define-key *motion-keymap* "k" 'vi-previous-line)
28+
(define-key *motion-keymap* "-" 'vi-previous-line)
29+
(define-key *motion-keymap* "g j" 'vi-next-display-line)
30+
(define-key *motion-keymap* "g k" 'vi-previous-display-line)
31+
(define-key *motion-keymap* "w" 'vi-forward-word-begin)
32+
(define-key *motion-keymap* "b" 'vi-backward-word-begin)
33+
(define-key *motion-keymap* "W" 'vi-forward-word-begin-broad)
34+
(define-key *motion-keymap* "B" 'vi-backward-word-begin-broad)
35+
(define-key *motion-keymap* "e" 'vi-forward-word-end)
36+
(define-key *motion-keymap* "E" 'vi-forward-word-end-broad)
37+
(define-key *motion-keymap* "$" 'vi-move-to-end-of-line)
38+
(define-key *motion-keymap* "g _" 'vi-move-to-last-nonblank)
39+
(define-key *motion-keymap* "H" 'vi-move-to-window-top)
40+
(define-key *motion-keymap* "M" 'vi-move-to-window-middle)
41+
(define-key *motion-keymap* "L" 'vi-move-to-window-bottom)
42+
(define-key *motion-keymap* "C-d" 'next-page)
43+
(define-key *motion-keymap* "C-u" 'previous-page)
44+
(define-key *motion-keymap* "^" 'vi-back-to-indentation)
45+
(define-key *motion-keymap* "_" 'vi-back-to-indentation)
46+
(define-key *motion-keymap* "{" 'backward-paragraph)
47+
(define-key *motion-keymap* "}" 'forward-paragraph)
48+
(define-key *motion-keymap* "C-f" 'next-page)
49+
(define-key *motion-keymap* "C-b" 'previous-page)
50+
(define-key *motion-keymap* "%" 'vi-move-to-matching-paren)
51+
(define-key *motion-keymap* "/" 'vi-search-forward)
52+
(define-key *motion-keymap* "?" 'vi-search-backward)
53+
(define-key *motion-keymap* "n" 'vi-search-next)
54+
(define-key *motion-keymap* "N" 'vi-search-previous)
55+
(define-key *motion-keymap* "*" 'vi-search-forward-symbol-at-point)
56+
(define-key *motion-keymap* "g g" 'vi-goto-first-line)
57+
(define-key *motion-keymap* "G" 'vi-goto-line)
58+
(define-key *motion-keymap* "Return" 'vi-return)
59+
(define-key *motion-keymap* "f" 'vi-find-char)
60+
(define-key *motion-keymap* "F" 'vi-find-char-backward)
61+
(define-key *motion-keymap* "t" 'vi-find-char-before)
62+
(define-key *motion-keymap* "T" 'vi-find-char-backward-after)
63+
(define-key *motion-keymap* ";" 'vi-find-char-repeat)
64+
(define-key *motion-keymap* "," 'vi-find-char-repeat-backward)
65+
(define-key *motion-keymap* "z z" 'recenter)
66+
(define-key *motion-keymap* "Z Z" 'vi-write-quit)
67+
(define-key *motion-keymap* "C-w s" 'split-active-window-vertically)
68+
(define-key *motion-keymap* "C-w C-s" 'split-active-window-vertically)
69+
(define-key *motion-keymap* "C-w w" 'other-window)
70+
(define-key *motion-keymap* "C-w C-w" 'other-window)
71+
(define-key *motion-keymap* "C-w q" 'vi-quit)
72+
(define-key *motion-keymap* "C-w h" 'window-move-left)
73+
(define-key *motion-keymap* "C-w C-h" 'undefined-key)
74+
(define-key *motion-keymap* "C-w l" 'window-move-right)
75+
(define-key *motion-keymap* "C-w C-l" 'undefined-key)
76+
(define-key *motion-keymap* "C-w k" 'window-move-up)
77+
(define-key *motion-keymap* "C-w C-k" 'undefined-key)
78+
(define-key *motion-keymap* "C-w j" 'window-move-down)
79+
(define-key *motion-keymap* "C-w C-j" 'undefined-key)
80+
(define-key *motion-keymap* "C-o" 'vi-jump-back)
81+
(define-key *motion-keymap* "C-i" 'vi-jump-next)
82+
(define-key *motion-keymap* ":" 'vi-ex)
9883

99-
(define-key *command-keymap* "v" 'vi-visual-char)
100-
(define-key *command-keymap* "V" 'vi-visual-line)
101-
(define-key *command-keymap* "C-v" 'vi-visual-block)
84+
(define-key *motion-keymap* "v" 'vi-visual-char)
85+
(define-key *motion-keymap* "V" 'vi-visual-line)
86+
(define-key *motion-keymap* "C-v" 'vi-visual-block)
10287

103-
(define-key *command-keymap* "i" 'vi-insert)
104-
(define-key *command-keymap* "I" 'vi-insert-line)
105-
(define-key *command-keymap* "a" 'vi-append)
106-
(define-key *command-keymap* "A" 'vi-append-line)
107-
(define-key *command-keymap* "o" 'vi-open-below)
108-
(define-key *command-keymap* "O" 'vi-open-above)
109-
(define-key *command-keymap* "C-o" 'vi-jump-back)
110-
(define-key *command-keymap* "C-i" 'vi-jump-next)
111-
(define-key *command-keymap* "." 'vi-repeat)
112-
(define-key *command-keymap* ":" 'vi-ex)
113-
(define-key *command-keymap* 'delete-previous-char 'vi-backward-char)
114-
(define-key *command-keymap* 'self-insert 'undefined-key)
88+
(define-key *normal-keymap* "i" 'vi-insert)
89+
(define-key *normal-keymap* "I" 'vi-insert-line)
90+
(define-key *normal-keymap* "a" 'vi-append)
91+
(define-key *normal-keymap* "A" 'vi-append-line)
92+
(define-key *normal-keymap* "o" 'vi-open-below)
93+
(define-key *normal-keymap* "O" 'vi-open-above)
94+
(define-key *normal-keymap* "." 'vi-repeat)
95+
(define-key *normal-keymap* "=" 'vi-indent)
96+
(define-key *normal-keymap* "s" 'vi-substitute)
97+
(define-key *normal-keymap* "x" 'vi-delete-next-char)
98+
(define-key *normal-keymap* "X" 'vi-delete-previous-char)
99+
(define-key *normal-keymap* "d" 'vi-delete)
100+
(define-key *normal-keymap* "D" 'vi-delete-line)
101+
(define-key *normal-keymap* "c" 'vi-change)
102+
(define-key *normal-keymap* "C" 'vi-change-line)
103+
(define-key *normal-keymap* "g J" 'vi-join)
104+
(define-key *normal-keymap* "J" 'vi-join-line)
105+
(define-key *normal-keymap* "y" 'vi-yank)
106+
(define-key *normal-keymap* "p" 'vi-paste-after)
107+
(define-key *normal-keymap* "P" 'vi-paste-before)
108+
(define-key *normal-keymap* "r" 'vi-replace-char)
109+
(define-key *normal-keymap* "g U" 'vi-upcase)
110+
(define-key *normal-keymap* "g u" 'vi-downcase)
111+
(define-key *normal-keymap* "u" 'vi-undo)
112+
(define-key *normal-keymap* "C-r" 'vi-redo)
113+
(define-key *motion-keymap* 'delete-previous-char 'vi-backward-char)
114+
(define-key *motion-keymap* 'self-insert 'undefined-key)
115115

116116
(define-key *insert-keymap* "Escape" 'vi-end-insert)
117117
(define-key *insert-keymap* "C-p" 'abbrev)
118118
(define-key *insert-keymap* "C-w" 'vi-kill-last-word)
119119

120-
(define-key *command-keymap* "C-p" 'yank-pop)
121-
(define-key *command-keymap* "C-n" 'yank-pop-next)
120+
(define-key *normal-keymap* "C-p" 'yank-pop)
121+
(define-key *normal-keymap* "C-n" 'yank-pop-next)
122122

123-
(define-key *command-keymap* "C-g" 'vi-keyboard-quit)
123+
(define-key *motion-keymap* "C-g" 'vi-keyboard-quit)
124124
(define-key *inactive-keymap* "Escape" 'vi-keyboard-quit)
125125

126126
(define-key *visual-keymap* "Escape" 'vi-visual-end)

extensions/vi-mode/commands.lisp

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
:lem-vi-mode/jump-motions
1010
:lem-vi-mode/commands/utils)
1111
(:import-from :lem-vi-mode/states
12-
:*command-keymap*
12+
:*motion-keymap*
1313
:normal
1414
:insert)
1515
(:import-from :lem-vi-mode/commands/utils
@@ -92,7 +92,7 @@
9292

9393
(defun extract-count-keys (keys)
9494
(loop for key in keys
95-
for cmd = (lem-core::keymap-find-keybind *command-keymap* key nil)
95+
for cmd = (lem-core::keymap-find-keybind *motion-keymap* key nil)
9696
unless (member cmd '(lem/universal-argument:universal-argument-0
9797
lem/universal-argument:universal-argument-1
9898
lem/universal-argument:universal-argument-2

extensions/vi-mode/core.lisp

+25-13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
:state=
1919
:change-state
2020
:with-state
21+
:mode-specific-keymaps
2122
:pre-command-hook
2223
:post-command-hook
2324
:state-enabled-hook
@@ -48,15 +49,17 @@
4849
(defun disable-hook ()
4950
(run-hooks *disable-hook*))
5051

52+
(defvar *fallback-keymap* *global-keymap*)
53+
5154
(define-global-mode vi-mode (emacs-mode)
5255
(:name "vi"
56+
:keymap *fallback-keymap*
5357
:enable-hook #'enable-hook
5458
:disable-hook #'disable-hook))
5559

56-
57-
5860
(defclass vi-state ()
5961
((name :initarg :name
62+
:initform nil
6063
:reader state-name)
6164
(message
6265
:initarg :message
@@ -70,10 +73,10 @@
7073
:initarg :modeline-color
7174
:initform 'state-modeline-white
7275
:reader state-modeline-color)
73-
(keymap
74-
:initarg :keymap
75-
:initform *global-keymap*
76-
:reader state-keymap)
76+
(keymaps
77+
:initarg :keymaps
78+
:initform '()
79+
:reader state-keymaps)
7780
(cursor-color
7881
:initarg :cursor-color
7982
:initform nil)))
@@ -82,11 +85,6 @@
8285
(or (slot-value state 'cursor-color)
8386
*default-cursor-color*))
8487

85-
(defmethod initialize-instance ((state vi-state) &rest initargs &key name &allow-other-keys)
86-
(unless name
87-
(setf (getf initargs :name) (class-name (class-of state))))
88-
(apply #'call-next-method state initargs))
89-
9088
(defvar *current-state* nil)
9189

9290
(defun state= (state1 state2)
@@ -133,12 +131,26 @@
133131
(assert (typep state 'vi-state))
134132
state)
135133

134+
(defgeneric mode-specific-keymaps (mode)
135+
(:method (mode) nil))
136+
137+
(defmethod compute-keymaps ((mode vi-mode))
138+
(let* ((buffer (current-buffer))
139+
(major-mode (ensure-mode-object (buffer-major-mode buffer)))
140+
(minor-mode-keymaps (loop for mode-name in (buffer-minor-modes buffer)
141+
for mode = (ensure-mode-object mode-name)
142+
when (mode-keymap mode)
143+
collect it)))
144+
(append minor-mode-keymaps
145+
(mode-specific-keymaps major-mode)
146+
;; Precede state keymaps over major-mode keymaps
147+
(state-keymaps (ensure-state *current-state*)))))
148+
136149
(defun change-state (name)
137150
(and *current-state*
138151
(state-disabled-hook (ensure-state *current-state*)))
139152
(let ((state (ensure-state name)))
140153
(setf *current-state* name)
141-
(change-global-mode-keymap 'vi-mode (state-keymap state))
142154
(state-enabled-hook state)
143155
(set-attribute 'cursor :background (state-cursor-color state))))
144156

@@ -160,7 +172,7 @@
160172
(add-hook *pre-command-hook* 'vi-pre-command-hook)
161173
(add-hook *post-command-hook* 'vi-post-command-hook)
162174

163-
(defmethod state-enabled-hook :after (state)
175+
(defmethod state-enabled-hook :after ((state vi-state))
164176
(lem-if:update-cursor-shape (lem:implementation)
165177
(state-cursor-type state)))
166178

extensions/vi-mode/ex.lisp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
(define-vi-state ex () ()
1414
(:default-initargs
15-
:keymap *ex-keymap*))
15+
:keymaps (list *ex-keymap*)))
1616

1717
(define-command vi-ex () ()
1818
(let* ((directory (uiop:getcwd))

extensions/vi-mode/lem-vi-mode.asd

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
(:file "ex-command" :depends-on ("ex-core" "options" "utils"))
2525
(:file "ex" :depends-on ("core" "ex-parser"))
2626
(:file "binds" :depends-on ("states" "commands" "ex" "visual"))
27+
(:file "special-binds" :depends-on ("core"))
2728
(:file "vi-mode" :depends-on ("core" "options" "ex" "commands" "states"))
2829
(:file "utils"))
2930
:in-order-to ((test-op (test-op "lem-vi-mode/tests"))))

extensions/vi-mode/rc-example.lisp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(in-package :lem-user)
22

33
;;; vi-mode
4-
(define-key lem-vi-mode:*command-keymap* "q" 'quit-active-window)
4+
(define-key lem-vi-mode:*normal-keymap* "q" 'quit-active-window)
55
(define-key lem-vi-mode:*insert-keymap* "C-n" 'lem/abbrev:abbrev-with-pop-up-window)
66

77
(add-hook lem-vi-mode:*enable-hook*

extensions/vi-mode/special-binds.lisp

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(defpackage :lem-vi-mode/special-binds
2+
(:use :cl)
3+
(:import-from :lem-vi-mode/core
4+
:mode-specific-keymaps)
5+
(:import-from :lem/directory-mode
6+
:directory-mode
7+
:*directory-mode-keymap*))
8+
(in-package :lem-vi-mode/special-binds)
9+
10+
(defmethod mode-specific-keymaps ((mode directory-mode))
11+
(list *directory-mode-keymap*))

0 commit comments

Comments
 (0)