evil-paredit.el 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. ;;; evil-paredit.el --- Paredit support for evil keybindings
  2. ;;
  3. ;; Copyright (C) 2012 Roman Gonzalez
  4. ;;
  5. ;; Author: Roman Gonzalez <romanandreg@gmail.com>
  6. ;; Mantainer: Roman Gonzalez <romanandreg@gmail.com>
  7. ;; Keywords: paredit, evil
  8. ;;
  9. ;; This file is NOT part of GNU Emacs.
  10. ;;
  11. ;; This file is free software (MIT License)
  12. ;; Version: 0.0.2
  13. ;; URL: https://github.com/roman/evil-paredit
  14. ;; Package-Requires: ((evil "1.0.9") (paredit "25beta"))
  15. ;;; Code:
  16. (require 'evil)
  17. (require 'paredit)
  18. ;;;###autoload
  19. (define-minor-mode evil-paredit-mode
  20. "Minor mode for setting up Evil with paredit in a single buffer"
  21. :keymap '()
  22. (let ((prev-state evil-state))
  23. (evil-normal-state)
  24. (evil-change-state prev-state)))
  25. (defun -evil-paredit-check-region (beg end)
  26. (if (fboundp 'paredit-check-region-state)
  27. (if (and beg end)
  28. ;; Check that region begins and ends in a sufficiently similar
  29. ;; state, so that deleting it will leave the buffer balanced.
  30. (save-excursion
  31. (goto-char beg)
  32. (let* ((state (paredit-current-parse-state))
  33. (state* (parse-partial-sexp beg end nil nil state)))
  34. (paredit-check-region-state state state*))))
  35. (paredit-check-region-for-delete beg end)))
  36. (evil-define-operator evil-paredit-yank (beg end type register yank-handler)
  37. "Saves the characters in motion into the kill-ring."
  38. :move-point nil
  39. :repeat nil
  40. (interactive "<R><x><y>")
  41. (-evil-paredit-check-region beg end)
  42. (cond
  43. ((eq type 'block)
  44. (evil-yank-rectangle beg end register yank-handler))
  45. ((eq type 'line)
  46. (evil-yank-lines beg end register yank-handler))
  47. (t
  48. (evil-yank-characters beg end register yank-handler))))
  49. (evil-define-operator evil-paredit-yank-line (beg end type register)
  50. "Saves whole lines into the kill-ring."
  51. :motion evil-line
  52. :move-point nil
  53. (interactive "<R><x>")
  54. (let* ((beg (point))
  55. (end (evil-paredit-kill-end)))
  56. (evil-paredit-yank beg end type register)))
  57. (evil-define-operator evil-paredit-delete
  58. (beg end type register yank-handler)
  59. "Delete text from BEG to END with TYPE respecting parenthesis.
  60. Save in REGISTER or in the kill-ring with YANK-HANDLER."
  61. (interactive "<R><x><y>")
  62. (evil-paredit-yank beg end type register yank-handler)
  63. (if (eq type 'block)
  64. (evil-apply-on-block #'delete-region beg end nil)
  65. (delete-region beg end))
  66. ;; place cursor on beginning of line
  67. (when (and (evil-called-interactively-p)
  68. (eq type 'line))
  69. (evil-first-non-blank)))
  70. (evil-define-operator evil-paredit-delete-line
  71. (beg end type register yank-handler)
  72. "Delete to end of line respecting parenthesis."
  73. :motion nil
  74. :keep-visual t
  75. (interactive "<R><x>")
  76. (let* ((beg (point))
  77. (end (evil-paredit-kill-end)))
  78. (evil-paredit-delete beg end
  79. type register yank-handler)))
  80. (defun evil-paredit-kill-end ()
  81. "Returns the position where paredit-kill would kill to"
  82. (when (paredit-in-char-p) ; Move past the \ and prefix.
  83. (backward-char 2)) ; (# in Scheme/CL, ? in elisp)
  84. (let* ((eol (point-at-eol))
  85. (end-of-list-p (save-excursion
  86. (paredit-forward-sexps-to-kill (point) eol))))
  87. (if end-of-list-p (progn (up-list) (backward-char)))
  88. (cond ((paredit-in-string-p)
  89. (if (save-excursion (paredit-skip-whitespace t (point-at-eol))
  90. (eolp))
  91. (kill-line)
  92. (save-excursion
  93. ;; Be careful not to split an escape sequence.
  94. (if (paredit-in-string-escape-p)
  95. (backward-char))
  96. (min (point-at-eol)
  97. (cdr (paredit-string-start+end-points))))))
  98. ((paredit-in-comment-p)
  99. eol)
  100. (t (if (and (not end-of-list-p)
  101. (eq (point-at-eol) eol))
  102. eol
  103. (point))))))
  104. (evil-define-operator evil-paredit-change
  105. (beg end type register yank-handler delete-func)
  106. "Change text from BEG to END with TYPE respecting parenthesis.
  107. Save in REGISTER or the kill-ring with YANK-HANDLER.
  108. DELETE-FUNC is a function for deleting text, default `evil-delete'.
  109. If TYPE is `line', insertion starts on an empty line.
  110. If TYPE is `block', the inserted text in inserted at each line
  111. of the block."
  112. (interactive "<R><x><y>")
  113. (let ((delete-func (or delete-func #'evil-paredit-delete))
  114. (nlines (1+ (- (line-number-at-pos end)
  115. (line-number-at-pos beg)))))
  116. (funcall delete-func beg end type register yank-handler)
  117. (cond
  118. ((eq type 'line)
  119. (evil-open-above 1))
  120. ((eq type 'block)
  121. (evil-insert 1 nlines))
  122. (t
  123. (evil-insert 1)))))
  124. (evil-define-operator evil-paredit-change-line
  125. (beg end type register yank-handler)
  126. "Change to end of line respecting parenthesis."
  127. :motion evil-end-of-line
  128. (interactive "<R><x><y>")
  129. (let* ((beg (point))
  130. (end (evil-paredit-kill-end)))
  131. (evil-paredit-change beg end type register yank-handler)))
  132. (defun evil-paredit-change-whole-line ()
  133. "Change whole line."
  134. (interactive)
  135. (beginning-of-line)
  136. (evil-paredit-change-line nil nil)
  137. (indent-according-to-mode))
  138. ;;TODO: doesn't switch back to normal-mode on an error
  139. (defun evil-paredit-backward-down ()
  140. (interactive)
  141. (evil-insert 1)
  142. (paredit-backward-down)
  143. (evil-force-normal-state))
  144. (defun evil-paredit-backward-up ()
  145. (interactive)
  146. (evil-insert 1)
  147. (paredit-backward-up)
  148. (evil-force-normal-state))
  149. (defun evil-paredit-forward-down ()
  150. (interactive)
  151. (evil-append 1)
  152. (paredit-forward-down)
  153. (evil-force-normal-state))
  154. (defun evil-paredit-forward-up ()
  155. (interactive)
  156. (evil-append 1)
  157. (paredit-forward-up)
  158. (evil-force-normal-state))
  159. (evil-define-key 'normal evil-paredit-mode-map
  160. (kbd "[") 'evil-paredit-backward-down
  161. (kbd "]") 'evil-paredit-forward-down
  162. (kbd "(") 'evil-paredit-backward-up
  163. (kbd ")") 'evil-paredit-forward-up
  164. (kbd "d") 'evil-paredit-delete
  165. (kbd "c") 'evil-paredit-change
  166. (kbd "y") 'evil-paredit-yank
  167. (kbd "D") 'evil-paredit-delete-line
  168. (kbd "C") 'evil-paredit-change-line
  169. (kbd "S") 'evil-paredit-change-whole-line
  170. (kbd "Y") 'evil-paredit-yank-line
  171. (kbd "X") 'paredit-backward-delete
  172. (kbd "x") 'paredit-forward-delete
  173. (kbd "RET") 'paredit-newline
  174. [tab] 'indent-according-to-mode)
  175. (provide 'evil-paredit)
  176. ;;; evil-paredit.el ends here