-
Notifications
You must be signed in to change notification settings - Fork 19
/
evil-paredit.el
167 lines (149 loc) · 5.56 KB
/
evil-paredit.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
;;; evil-paredit.el --- Paredit support for evil keybindings
;;
;; Copyright (C) 2012 Roman Gonzalez
;;
;; Author: Roman Gonzalez <romanandreg@gmail.com>
;; Mantainer: Roman Gonzalez <romanandreg@gmail.com>
;; Keywords: paredit, evil
;;
;; This file is NOT part of GNU Emacs.
;;
;; This file is free software (MIT License)
;; Version: 0.0.2
;; URL: https://github.com/roman/evil-paredit
;; Package-Requires: ((evil "1.0.9") (paredit "25beta"))
;;; Code:
(require 'evil)
(require 'paredit)
;;;###autoload
(define-minor-mode evil-paredit-mode
"Minor mode for setting up Evil with paredit in a single buffer"
:keymap '()
(let ((prev-state evil-state))
(evil-normal-state)
(evil-change-state prev-state)))
(defun -evil-paredit-check-region (beg end)
(if (fboundp 'paredit-check-region-state)
(if (and beg end)
;; Check that region begins and ends in a sufficiently similar
;; state, so that deleting it will leave the buffer balanced.
(save-excursion
(goto-char beg)
(let* ((state (paredit-current-parse-state))
(state* (parse-partial-sexp beg end nil nil state)))
(paredit-check-region-state state state*))))
(paredit-check-region-for-delete beg end)))
(evil-define-operator evil-paredit-yank (beg end type register yank-handler)
"Saves the characters in motion into the kill-ring."
:move-point nil
:repeat nil
(interactive "<R><x><y>")
(-evil-paredit-check-region beg end)
(cond
((eq type 'block)
(evil-yank-rectangle beg end register yank-handler))
((eq type 'line)
(evil-yank-lines beg end register yank-handler))
(t
(evil-yank-characters beg end register yank-handler))))
(evil-define-operator evil-paredit-yank-line (beg end type register)
"Saves whole lines into the kill-ring."
:motion evil-line
:move-point nil
(interactive "<R><x>")
(let* ((beg (point))
(end (evil-paredit-kill-end)))
(evil-paredit-yank beg end type register)))
(evil-define-operator evil-paredit-delete
(beg end type register yank-handler)
"Delete text from BEG to END with TYPE respecting parenthesis.
Save in REGISTER or in the kill-ring with YANK-HANDLER."
(interactive "<R><x><y>")
(evil-paredit-yank beg end type register yank-handler)
(if (eq type 'block)
(evil-apply-on-block #'delete-region beg end nil)
(delete-region beg end))
;; place cursor on beginning of line
(when (and (evil-called-interactively-p)
(eq type 'line))
(evil-first-non-blank)))
(evil-define-operator evil-paredit-delete-line
(beg end type register yank-handler)
"Delete to end of line respecting parenthesis."
:motion nil
:keep-visual t
(interactive "<R><x>")
(let* ((beg (point))
(end (evil-paredit-kill-end)))
(evil-paredit-delete beg end
type register yank-handler)))
(defun evil-paredit-kill-end ()
"Returns the position where paredit-kill would kill to"
(when (paredit-in-char-p) ; Move past the \ and prefix.
(backward-char 2)) ; (# in Scheme/CL, ? in elisp)
(let* ((eol (point-at-eol))
(end-of-list-p (save-excursion
(paredit-forward-sexps-to-kill (point) eol))))
(if end-of-list-p (progn (up-list) (backward-char)))
(cond ((paredit-in-string-p)
(if (save-excursion (paredit-skip-whitespace t (point-at-eol))
(eolp))
(kill-line)
(save-excursion
;; Be careful not to split an escape sequence.
(if (paredit-in-string-escape-p)
(backward-char))
(min (point-at-eol)
(cdr (paredit-string-start+end-points))))))
((paredit-in-comment-p)
eol)
(t (if (and (not end-of-list-p)
(eq (point-at-eol) eol))
eol
(point))))))
(evil-define-operator evil-paredit-change
(beg end type register yank-handler delete-func)
"Change text from BEG to END with TYPE respecting parenthesis.
Save in REGISTER or the kill-ring with YANK-HANDLER.
DELETE-FUNC is a function for deleting text, default `evil-delete'.
If TYPE is `line', insertion starts on an empty line.
If TYPE is `block', the inserted text in inserted at each line
of the block."
(interactive "<R><x><y>")
(let ((delete-func (or delete-func #'evil-paredit-delete))
(nlines (1+ (- (line-number-at-pos end)
(line-number-at-pos beg)))))
(funcall delete-func beg end type register yank-handler)
(cond
((eq type 'line)
(evil-open-above 1))
((eq type 'block)
(evil-insert 1 nlines))
(t
(evil-insert 1)))))
(evil-define-operator evil-paredit-change-line
(beg end type register yank-handler)
"Change to end of line respecting parenthesis."
:motion evil-end-of-line
(interactive "<R><x><y>")
(let* ((beg (point))
(end (evil-paredit-kill-end)))
(evil-paredit-change beg end type register yank-handler)))
(defun evil-paredit-change-whole-line ()
"Change whole line."
(interactive)
(beginning-of-line)
(evil-paredit-change-line nil nil)
(indent-according-to-mode))
(evil-define-key 'normal evil-paredit-mode-map
(kbd "d") 'evil-paredit-delete
(kbd "c") 'evil-paredit-change
(kbd "y") 'evil-paredit-yank
(kbd "D") 'evil-paredit-delete-line
(kbd "C") 'evil-paredit-change-line
(kbd "S") 'evil-paredit-change-whole-line
(kbd "Y") 'evil-paredit-yank-line
(kbd "X") 'paredit-backward-delete
(kbd "x") 'paredit-forward-delete)
(provide 'evil-paredit)
;;; evil-paredit.el ends here