Created
November 9, 2012 06:38
-
-
Save hchbaw/4044079 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; evil.el version of textobj-motionmotion.vim | |
;; https://github.com/hchbaw/textobj-motionmotion.vim | |
;; Thanks very much the authors of evil.el -- extensible vi layer! | |
;; TODO: | |
;; - Am I totally doing wrong? | |
;; - arrgh! exclusive/inclusive in general | |
(defvar *evil-motionmotion-point* nil | |
"Saved value of `point' result before invoking the | |
`evil-textobj-motionmotion-operator'.") | |
(defmacro evil-with-motionmotion-point (&rest body) | |
(declare (indent 0)) | |
`(let ((*evil-motionmotion-point* (point))) | |
,@body)) | |
(defun evil-motionmotion-text-object-outer-motion-p (motion) | |
(string-match (rx string-start "evil-" (or "outer" "a") "-") | |
(format "%s" motion))) | |
(defun evil-motionmotion-text-object-inner-motion-p (motion) | |
(string-match (rx string-start "evil-" (or "inner" "i") "-") | |
(format "%s" motion))) | |
(evil-define-operator evil-motionmotion-operator (beg end type) | |
(interactive "<R>") | |
(cond ((evil-motionmotion-text-object-inner-motion-p evil-this-motion) | |
(cons beg (1- end))) | |
((evil-motionmotion-text-object-outer-motion-p evil-this-motion) | |
(cons beg end)) | |
((= *evil-motionmotion-point* end) ;; left | |
(goto-char beg) | |
(cons (point) (point))) | |
((= *evil-motionmotion-point* beg) ;; right | |
(goto-char end) | |
(when (eq type 'inclusive) | |
(goto-char (1- (point)))) | |
(cons (point) (point))) | |
(t (cons beg end)))) | |
(defun evil-motionmotion-range (interim) | |
(macrolet ((save-this-command-keys (&rest body) | |
;; While an operator is in effect, subsequent operator | |
;; invocation may break the `evil-operator-range'. | |
;; For example, issuing "dimfa" will result that "d" as the | |
;; operator and the result of `this-command-keys'. | |
;; Then (note the operator "d" is in effect) "imfa" part will | |
;; try to invoke the operator `evil-motionmotion-operator', | |
;; so `evil-operator-range' will get called. At this point, | |
;; `this-command-keys' will result "dim", | |
;; `evil-extract-count' will complain "Key sequence contains | |
;; no complete binding". | |
;; So for now, while invoking an operator, hold the result of | |
;; `this-command-keys' and use it on subsequent calls. | |
;; fixes - "dimfi" -> insert mode. | |
`(letf* (((symbol-function 'this-command-keys-orig) | |
(symbol-function 'this-command-keys)) | |
((symbol-function 'this-command-keys) | |
(apply-partially (lambda (keys) | |
(let ((len (length keys))) | |
(substring keys 0 (1- len)))) | |
(this-command-keys-orig)))) | |
(progn ,@body)))) | |
(let ((pos (point))) | |
(pcase-let | |
((`((,b . _) . (_ . ,e)) | |
(save-this-command-keys | |
(cons | |
#1=(evil-with-motionmotion-point | |
(call-interactively 'evil-motionmotion-operator)) | |
(progn | |
(funcall interim pos) | |
#1#))))) | |
(let ((range (evil-range b (goto-char e)))) | |
;; XXX: textobj-motionmotion.vim tends to be inclusive | |
(evil-normalize-range range) | |
(evil-set-range-type range 'inclusive) | |
(evil-expand-range range)))))) | |
(evil-define-text-object evil-a-motionmotion (count &optional beg end type) | |
(evil-motionmotion-range 'ignore)) | |
(evil-define-text-object evil-i-motionmotion (count &optional beg end type) | |
(evil-motionmotion-range 'goto-char)) | |
(define-key evil-outer-text-objects-map "m" 'evil-a-motionmotion) | |
(define-key evil-inner-text-objects-map "m" 'evil-i-motionmotion) | |
(dont-compile | |
(when (fboundp 'expectations) | |
(require 'evil-tests) | |
(expectations | |
(expect (no-error) | |
(evil-test-buffer | |
"This[ ]test hl" | |
("dimhl") | |
"Thiest hl") | |
(evil-test-buffer | |
"This[ ]test lh" | |
("dimlh") | |
"Thiest lh") | |
)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment