Code faster by extending Emacs EVIL text object

  |   Source

I use EVIL text object a lot. For example, press vi( to select the code snippet inside parenthesis.

I could also press vib to do exactly same thing as vi( because below code in EVIL's evil-maps.el,

(define-key evil-outer-text-objects-map "b" 'evil-a-paren)
(define-key evil-inner-text-objects-map "b" 'evil-inner-paren)

As a full stack web developer, I often need select the snippet inside "[]", "{}", "()", "<>". So I prefer using vig to replace vi[, vi{, vi(, and vi<.

Here is my new text object,

(defun my-evil-paren-range (count beg end type inclusive)
  "Get minimum range of paren text object.
COUNT, BEG, END, TYPE is used.  If INCLUSIVE is t, the text object is inclusive."
  (let* ((parens '("()" "[]" "{}" "<>"))
         range
         found-range)
    (dolist (p parens)
      (condition-case nil
          (setq range (evil-select-paren (aref p 0) (aref p 1) beg end type count inclusive))
        (error nil))
      (when range
        (cond
         (found-range
          (when (< (- (nth 1 range) (nth 0 range))
                   (- (nth 1 found-range) (nth 0 found-range)))
            (setf (nth 0 found-range) (nth 0 range))
            (setf (nth 1 found-range) (nth 1 range))))
         (t
          (setq found-range range)))))
    found-range))

(evil-define-text-object my-evil-a-paren (count &optional beg end type)
  "Select a paren."
  :extend-selection t
  (my-evil-paren-range count beg end type t))

(evil-define-text-object my-evil-inner-paren (count &optional beg end type)
  "Select 'inner' paren."
  :extend-selection nil
  (my-evil-paren-range count beg end type nil))

(define-key evil-inner-text-objects-map "g" #'my-evil-inner-paren)
(define-key evil-outer-text-objects-map "g" #'my-evil-a-paren)

In above code,

  • my-evil-paren-range returns the minimum range of text objects "[", "{", "(", and "<".
  • EVIL api evil-define-text-object is used to define a text object whose range is returned by my-evil-paren-range
  • In evil-outer-text-objects-map the text object shortcut "g" is defined

As you can see, understanding my personal workflow and knowing a bit Lisp does make me code faster.

Comments powered by Disqus