noctuid / lispyville

lispy + evil = lispyville
GNU General Public License v3.0
315 stars 23 forks source link

Evil navigation #66

Open sorawee opened 4 years ago

sorawee commented 4 years ago

Hello. First of all, thanks for this amazing package!

I'm personally used to a navigation in normal and visual state where backward-sexp is analogous to evil-backward-word-begin and forward-sexp is analogous to evil-forward-word-end. To elaborate, I want:

abc def
^ >
(abc def) ghi
^       >
(abc def) ghi
        ^   >

where ^ is the current position of the point and > is where the point should be after the forward-sexp operation. Similarly, I want:

abc def
    < ^
ghi (abc def)
    <       ^
ghi (abc def)
<   ^

where ^ is the current position of the point and < is where the point should be after the backward-sexp operation.

IIUC, none of the functionalities that lispyville provides does something like this, due to the off-by-one error from the mismatch between Emacs's point system and Vim's point system. Therefore, I wrote my own:

(defun significantp (old-point new-point)
  (not (or (equal old-point new-point)
           (equal (1+ old-point) new-point))))

(evil-define-motion my/lispyville-forward-sexp (count)
  "This is an evil motion equivalent of `forward-sexp'."
  (let ((original-point (point)))
    (when (nth 3 (syntax-ppss))
      (forward-char))
    (condition-case nil
        (forward-sexp (or count 1))
      (error nil))
    (unless (significantp original-point (point))
      (goto-char (1+ original-point))
      (condition-case nil
          (forward-sexp (or count 1))
        (error nil)))
    (backward-char)))

(evil-define-motion my/lispyville-backward-sexp (count)
  "This is an evil motion equivalent of `backward-sexp'."
  (let ((original-point (point)))
    (when (nth 3 (syntax-ppss (1+ (point))))
      (backward-char))
    (condition-case nil
        (backward-sexp (or count 1))
      (error nil))
    (unless (significantp original-point (point))
      (goto-char original-point)
      (condition-case nil
          (backward-sexp (or count 1))
        (error nil)))))

If you think it's useful, feel free to adapt it. Any suggestion would be appreciated, too!