I am trying to define a function that moves to the begin/end of current text-object.

First - I define an operator:

(evil-define-operator evil-forward-text-object (beg end type)
  "move to end of text object"
  (if (eq type 'block)
      (evil-apply-on-block #'evil-forward-text-object beg end nil)
    (goto-char end)))

In this case I need to press M-w i ) to move forward a bracket. There will be an i or a, it is troublesome to type a or i, and there is no difference between i and a.

Next - I try to set the keymap:

(define-key evil-motion-state-map (kbd "M-w")
  evil-inner-text-objects-map)

This works in some cases, such as M-w p or M-w o (forward a kebab-style Lisp symbol). But in most cases it does not work - for example, M-w ) and M-w ".

How can I define a command such as I described?

in evil-commands.el state:

Text objects

Text objects are defined with evil-define-text-object. In Visual state, they modify the current selection; in Operator-Pending state, they return a pair of buffer positions. Outer text objects are bound in the keymap evil-outer-text-objects-map, and inner text objects are bound in evil-inner-text-objects-map.

Common text objects like words, WORDS, paragraphs and sentences are defined via a corresponding move-function. This function must have the following properties:

  1. Take exactly one argument, the count.
  2. When the count is positive, move point forward to the first character after the end of the next count-th object.
  3. When the count is negative, move point backward to the first character of the count-th previous object.

so after call text-object function for positive number, which should move cursor to the end. but only some text-object function move cursor to end, so i define some advice to them:

(defun move-to-begine (region)
  (goto-char (nth 0 region))
  region)
(defun move-to-end (region)
  (goto-char (nth 1 region))
  region)
(advice-add #'evil-inner-paren :filter-return #'move-to-end)

:filter-return mean pass origin function output to advice. then origin method by define M-w as evil-inner-text-object-map work.

finally i use read-key-sequence to read text-object then execute it:

;; move over text object
(evil-define-motion evil-forward-text-object
  (count &optional text-object)
  "move to the end of following input text-object define 
in evil-inner-text-objects-map ."
  (unless text-object
      (setf text-object
            (let ((key (read-key-sequence "text-object:")))
              (lookup-key evil-inner-text-objects-map key))))
  (let* ((region (funcall text-object count))
         (end (nth 1 region)))
    (goto-char end)))
(define-key evil-motion-state-map (kbd "M-w")
  #'evil-forward-text-object)

(evil-define-motion evil-backward-text-object
  (count &optional text-object)
  "move to the begin of following input text-object define 
in evil-inner-text-objects-map ."
  (unless text-object
      (setf text-object
            (let ((key (read-key-sequence "text-object:")))
              (lookup-key evil-inner-text-objects-map key))))
  (let* ((region (funcall text-object count))
         (start (nth 0 region)))
    (goto-char start)))
(define-key evil-motion-state-map (kbd "M-b")
  #'evil-backward-text-object)
  • 1
    Please edit your original answer to include this part rather than submit two answers. – Dan Oct 7 at 12:34
  • i think they are 2 different aproach. it is better to keep in 2 answer. – gholk Oct 9 at 9:02

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.