Emacs Evil mode: how to create a new text object to select words with any non-space characters?

后端 未结 3 675
小蘑菇
小蘑菇 2021-02-08 18:58

I am trying to create a new text object in Evil. For example, the text object iw will only select subsets of strings containing hyphens. I want the new text object to m

3条回答
  •  长发绾君心
    2021-02-08 19:19

    Update: evil-regexp-range was recently replaced with evil-select-paren. This works on current evil and has the same usage as the old one:

    (defmacro define-and-bind-text-object (key start-regex end-regex)
      (let ((inner-name (make-symbol "inner-name"))
            (outer-name (make-symbol "outer-name")))
        `(progn
           (evil-define-text-object ,inner-name (count &optional beg end type)
             (evil-select-paren ,start-regex ,end-regex beg end type count nil))
           (evil-define-text-object ,outer-name (count &optional beg end type)
             (evil-select-paren ,start-regex ,end-regex beg end type count t))
           (define-key evil-inner-text-objects-map ,key (quote ,inner-name))
           (define-key evil-outer-text-objects-map ,key (quote ,outer-name)))))
    

    Original Answer:

    If you end up defining more than one new text object, the repetition can get annoying, especially if you want to bind both inner and outer objects. If you hit that barrier, try this:

    (defmacro define-and-bind-text-object (key start-regex end-regex)
      (let ((inner-name (make-symbol "inner-name"))
            (outer-name (make-symbol "outer-name")))
        `(progn
          (evil-define-text-object ,inner-name (count &optional beg end type)
            (evil-regexp-range count beg end type ,start-regex ,end-regex t))
          (evil-define-text-object ,outer-name (count &optional beg end type)
            (evil-regexp-range count beg end type ,start-regex ,end-regex nil))
          (define-key evil-inner-text-objects-map ,key (quote ,inner-name))
          (define-key evil-outer-text-objects-map ,key (quote ,outer-name)))))
    

    Usage:

    ; between dollar signs:
    (define-and-bind-text-object "$" "\\$" "\\$")
    
    ; between pipe characters:
    (define-and-bind-text-object "|" "|" "|")
    
    ; from regex "b" up to regex "c", bound to k (invoke with "vik" or "vak"):
    (define-and-bind-text-object "k" "b" "c")
    

    (This is more than you wanted, but I'll leave it here in case it helps someone :)

提交回复
热议问题