/
evil-space.el
150 lines (122 loc) · 5.21 KB
/
evil-space.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
;;; evil-space.el --- Repeat motion in Evil. Correct the behaviour of what SPC should do.
;; Copyright (C) 2015 Quang Linh LE
;; Author: Quang Linh LE <linktohack@gmail.com>
;; URL: http://github.com/linktohack/evil-space
;; Version: 1.0.0
;; Keywords: space repeat motion
;; Package-Requires: ((evil "1.0.0"))
;; This file is not part of GNU Emacs.
;;; License:
;; This file is part of evil-space
;;
;; evil-space is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published
;; by the Free Software Foundation, either version 3 of the License,
;; or (at your option) any later version.
;;
;; evil-space is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; This program emulates vim-space initially developed by Henrik Öhman
;; (spiiph) It help you using <SPC> key to repeat the last motion like
;; what the dot <.> key does to repeat the last command. The motion
;; are normally setup in pair, that means the <S-SPC> (or customized
;; to what one needs) to reverse that motion.
;;; Example:
;;
;; After hits <}> to go to next paragraph, hits <SPC> again will move
;; to the next one, while <S-SPC> will move to the previous one.
;;; Code:
(require 'evil)
(defgroup evil-space nil
"Repeat motion in Evil"
:group 'evil
:prefix "evil-space-")
(eval-and-compile
(defcustom evil-space-auto-setup t
"Whether or not to setup the initial motions. If you are having conflicts
with your own mappings, then best to set this to nil and do your own."
:group 'evil-space)
(defcustom evil-space-next-key (kbd "SPC")
"Key that triggers the repeat motion."
:group 'evil-space)
(defcustom evil-space-prev-key (kbd "S-SPC")
"Key that triggers the repeat motion in reverse direction."
:group 'evil-space)
(defun evil-space-lookup-key (key &optional keymap)
"Normalize KEY into a function."
(cond ((eq (car-safe key) 'quote) (cadr key))
((symbolp key) (symbol-value key))
((stringp key)
(if keymap
(lookup-key (symbol-value keymap) (kbd key))
(lookup-key evil-motion-state-map (kbd key))))
(t (user-error "Not a valid key: %s" key)))))
;;;###autoload
(defmacro evil-space-setup (key next prev &optional keymap)
"Makes KEY repeatable with `evil-space-next-key' and `evil-space-prev-key'.
NEXT and PREV represent the key bindings that repeat KEY forward and backwards,
respectively.
KEY, NEXT and PREV can be a key, function symbol, or forms that evaluate to a
function.
KEYMAP, if non-nil, specifies where to lookup KEY, NEXT and PREV. If nil, it
defaults to `evil-motion-state-map'.
Examples:
(evil-space-setup \"f\" \";\" \",\")
;; Probably not a great idea.
(evil-space-setup \"s-/\" \"s-/\" \"s-/\" evil-commentary-mode-map)
;; Map * in evil-visualstar-mode-map, in visual state
(evil-space-setup \"*\" \"n\" \"N\" (evil-get-auxiliary-keymap evil-visualstar-mode-map 'visual))
;; Map functions directly, rather than keys
(evil-space-setup evil-snipe-f evil-snipe-repeat evil-snipe-repeat-reverse)"
(let* ((key-func-next (evil-space-lookup-key next keymap))
(key-func-prev (evil-space-lookup-key prev keymap))
(key-to-replace (evil-space-lookup-key key keymap))
(func-next (intern (format "evil-space--%s" key-func-next)))
(func-prev (intern (format "evil-space--%s" key-func-prev))))
`(progn
(fset ',func-next (symbol-function ',key-func-next))
(fset ',func-prev (symbol-function ',key-func-prev))
(defadvice ,key-to-replace
(before ,(intern (format "%s--space" (symbol-name key-to-replace))) activate)
,(format "Setup evil-space for motion %s. Its delegates are `%s' and `%s'" key func-next func-prev)
(evil-define-key 'motion evil-space-mode-map ,evil-space-next-key ',func-next)
(evil-define-key 'motion evil-space-mode-map ,evil-space-prev-key ',func-prev)))))
;;;###autoload
(define-minor-mode evil-space-mode
"Evil space mode."
:lighter " SPC"
:global t
:keymap (make-sparse-keymap)
(when evil-space-auto-setup
(evil-space-setup "gj" "gj" "gk")
(evil-space-setup "gk" "gk" "gj")
(evil-space-setup "-" "-" "+")
(evil-space-setup "+" "+" "-")
;; search motions
(evil-space-setup "n" "n" "N")
(evil-space-setup "N" "N" "n")
(evil-space-setup "t" ";" ",")
(evil-space-setup "f" ";" ",")
(evil-space-setup "T" "," ";")
(evil-space-setup "F" "," ";")
(evil-space-setup "*" "*" "#")
(evil-space-setup "#" "#" "*")
;; block motions
(evil-space-setup "(" "(" ")")
(evil-space-setup ")" ")" "(")
(evil-space-setup "{" "{" "}")
(evil-space-setup "}" "}" "{")
(evil-space-setup "]]" "]]" "[[")
(evil-space-setup "[[" "[[" "]]")))
;;;###autoload
(define-obsolete-function-alias 'evil-space-default-setup
'evil-space-mode "0.0.4")
(provide 'evil-space)
;;; evil-space.el ends here