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 "24"))
;;; 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
|