123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- ;;; 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))
- ;;TODO: doesn't switch back to normal-mode on an error
- (defun evil-paredit-backward-down ()
- (interactive)
- (evil-insert 1)
- (paredit-backward-down)
- (evil-force-normal-state))
- (defun evil-paredit-backward-up ()
- (interactive)
- (evil-insert 1)
- (paredit-backward-up)
- (evil-force-normal-state))
- (defun evil-paredit-forward-down ()
- (interactive)
- (evil-append 1)
- (paredit-forward-down)
- (evil-force-normal-state))
- (defun evil-paredit-forward-up ()
- (interactive)
- (evil-append 1)
- (paredit-forward-up)
- (evil-force-normal-state))
- (evil-define-key 'normal evil-paredit-mode-map
- (kbd "[") 'evil-paredit-backward-down
- (kbd "]") 'evil-paredit-forward-down
- (kbd "(") 'evil-paredit-backward-up
- (kbd ")") 'evil-paredit-forward-up
- (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
- (kbd "RET") 'paredit-newline
- [tab] 'indent-according-to-mode)
- (provide 'evil-paredit)
- ;;; evil-paredit.el ends here
|