Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@timcharper
Last active December 14, 2015 05:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timcharper/5034251 to your computer and use it in GitHub Desktop.
Save timcharper/5034251 to your computer and use it in GitHub Desktop.
evil forward-word compromise.
;; Here is a snippet of code that takes a less painful (to me)
;; compromise route between using emacs forward-word. It's a working
;; proof-of-concept, and an approach such as this would allow (nearly)
;; the same speed as emacs forward-word alone, with the advantage of
;; avoiding a major, sore thumb: _'s not treated as word characters in
;; vim motions.
;; * I don't like the `(modify-syntax-entry ?_ "w")` approach as I
;; have to install a hook to enable it for every applicable mode. This
;; is a shotgun-surgery style workaround that affects emacs core
;; commands.
;; * I like Emacs behavior for `M-d`, `C-M-h`, both deleting up to an
;; underscore.
;; * I don't like the new default evil behavior of not respecting _. I
;; have to choose between not liking the `viw` behavior, or not
;; liking `M-d`.
;; * I don't like mode-specific word boundaries for modal editing. It
;; makes things less predictable and causes my fingers to feel
;; rather clumsy. In fact, I don't really like mode-specific word
;; boundaries at all. Unfortunately, there doesn't appear to be a
;; clean way, in Emacs, to modify the boundaries for all mode
;; syntaxes. This is most unfortunate.
;; * The `modify-syntax-entry` tweak is a work-around to restore a vim
;; behavior which persists after evil-mode is disabled.
;; I personally preferred the slow, purist implementation, but I
;; didn't have a workflow that was impeded by the apparent slowness of
;; the implementation.
;; If we have to compromise vim-emulation for speed, I think I would
;; prefer the below approach, and not what is currently in evil HEAD.
(defun evil-move-point-by-word (dir)
"Used internally by evil
A pure-vim emulation of move-word runs slow, but emacs forward-word
does not recognize underscores as word boundaries. This method calls
Emacs native forward-word, and then repeats if it detects it stopped
on an underscore."
(let ((success (forward-word dir))
(fn (if (= 1 dir) 'looking-at 'looking-back)))
(if (and success (funcall fn "_"))
(evil-forward-word-compromise dir)
success)))
(defun evil-forward-word (&optional count)
"Move by words.
Moves point COUNT words forward or (- COUNT) words backward if
COUNT is negative. This function is the same as `forward-word'
but returns the number of words by which point could *not* be
moved."
(setq count (or count 1))
(let* ((dir (if (>= count 0) +1 -1))
(count (abs count)))
(while (and (> count 0)
(evil-move-point-by-word dir))
(setq count (1- count)))
count))
(evil-define-union-move evil-move-word (count)
"Move by words."
(evil-move-chars "^ \t\r\n[:word:]_" count)
(let ((word-separating-categories evil-cjk-word-separating-categories)
(word-combining-categories evil-cjk-word-combining-categories))
(evil-forward-word count))
(evil-move-empty-lines count))
@timcharper
Copy link
Author

This did not make it in to evil. I have an updated approach which overrides the function for the latest version of evil (union-move has been since axed)

https://gist.github.com/timcharper/c8d8bb01b3a13e5f68f4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment