Add an evil text object for all grouping characters

Found a great idead from Chen Bin for not making a distinction between
parens, brackets and braces when doing text object manipulation. This
saves having to press the shift and reach for the another key when ~g~
is riiight there.
This commit is contained in:
Howard Abrams 2022-08-29 09:37:06 -07:00
parent c609e124f3
commit 62c2e13dab

View file

@ -429,6 +429,47 @@ While Im pretty good with the VIM keybindings, I would like to play around wi
- ~i`~ :: inner back quoted string
*Note:* The ~x~ in the above examples are ~d~ for delete, ~v~ for select, ~y~ for copying and ~c~ for changing.
*** Better Parenthesis with Text Object
I took the following clever idea and code from [[http://blog.binchen.org/posts/code-faster-by-extending-emacs-evil-text-object/][this essay]] from Chen Bin for creating a ~xig~ to grab code within any grouping characters, like parens, braces and brackets. For instance, ~dig~ cuts the content inside brackets, etc. First, we need a function to do the work (I changed the original from =my-= to =ha-= so that it is easier for me to distinguish functions from my configuration):
#+begin_src emacs-lisp
(defun ha-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))
#+end_src
Extend the text object to call this function for both /inner/ and /outer/:
#+begin_src emacs-lisp
(evil-define-text-object ha-evil-a-paren (count &optional beg end type)
"Select a paren."
:extend-selection t
(ha-evil-paren-range count beg end type t))
(evil-define-text-object ha-evil-inner-paren (count &optional beg end type)
"Select 'inner' paren."
:extend-selection nil
(ha-evil-paren-range count beg end type nil))
#+end_src
And the keybindings:
#+begin_src emacs-lisp
(define-key evil-inner-text-objects-map "g" #'ha-evil-inner-paren)
(define-key evil-outer-text-objects-map "g" #'ha-evil-a-paren)
#+end_src
*** Key Chord
Using the key-chord project allows me to make Escape be on two key combo presses on both sides of my keyboard:
#+begin_src emacs-lisp