Hi! I was wondering if there was a canonical method for allowing camelcase and underscore word movement in evil-mode. I've looked at the suggestion in http://slashusr.wordpress.com/2011/09/15/heretical-confessions-of-an-emacs-a..., but that solution was somewhat limited (no backward movement, and it only worked with other operators, rather than as an actual method of movement). Many thanks, and apologies in advance if I've missed something obvious! Simon
On Sat, Jun 02 2012 (21:20), Simon Carter <[email protected]> wrote:
I was wondering if there was a canonical method for allowing camelcase and underscore word movement in evil-mode.
Not to my knowledge.
I've looked at the suggestion in http://slashusr.wordpress.com/2011/09/15/heretical-confessions-of-an-emacs-a..., but that solution was somewhat limited (no backward movement, and it only worked with other operators, rather than as an actual method of movement).
Ok this is the solution posted: (evil-define-motion evil-little-word (count) :type exclusive (let ((case-fold-search nil)) (forward-char) (search-forward-regexp "[_A-Z]\\|\\W" nil t) (backward-char))) it only works with other operators, because it was defined in `evil-operator-state-map' define in in `evil-motion-state-map' and it will work on its own (but you maybe want to chose another key sequence to not shadow `l'). Here is code for the backword movement: (evil-define-motion evil-little-word-backward (count) :type inclusive (let ((case-fold-search nil)) (backward-char) (search-backward-regexp "[_A-Z]\\|\\W" nil t))) You have to define it as well as keys, of course. Another change you want to make is the inclusion of `count': (evil-define-motion evil-little-word (count) :type exclusive (let ((case-fold-search nil)) (forward-char) (search-forward-regexp "[_A-Z]\\|\\W" nil t count) (backward-char))) respective (evil-define-motion evil-little-word-backward (count) :type inclusive (let ((case-fold-search nil)) (backward-char) (search-backward-regexp "[_A-Z]\\|\\W" nil t count))) As there's `subword-mode' for vanilla Emacs maybe it would be nice to change the word movements (b, e, w and their ilk) to subword movements if subword-move is active for a tighter emacs integration? Michael
From: Simon Carter <[email protected]> Subject: Evil-mode and camelcase movement Date: Sat, 2 Jun 2012 20:20:40 +0100
I was wondering if there was a canonical method for allowing camelcase and underscore word movement in evil-mode.
If you are looking for Evil implementation of camelcasemotion.vim (http://www.vim.org/scripts/script.php?script_id=1905), then you need to redefine evil-{forward,backward}-word-{begin,end} and evil-{a,inner}-word with somehow dealing with word boundaries of CamelCase/snake_case words. I think using search-forward-regexp is not a good idea for two reasons: a. There are many other uppercase letters other than [A-Z] and it's too hard to write them all in a regular expression. You can see the list of uppercase letters: http://www.fileformat.info/info/unicode/category/Lu/list.htm b. I had a hard experience dealing with word boundaries separated by non-whitespace characters, when I was making a Evil patch to support Japanese words (a CJK patch 7adc3b1). For these reasons, I recommend a way using Emacs' native support of character categories and word boundaries just like in the CJK patch. First, we need to define new character categories for uppercase/lowercase letters and underscore. (define-category ?U "Uppercase") (define-category ?L "Lowercase") (define-category ?_ "Underscore") (modify-category-entry (cons ?A ?Z) ?U) (modify-category-entry (cons ?a ?z) ?L) (modify-category-entry ?_ ?_) (We have (cons ?A ?Z)/(cons ?a ?z) here but I will fix this later to cover all uppercase/lowercase letters.) Then, define word boundaries by indicating which categories of successive characters are separating CamelCase/snake_case words. (setq evil-little-word-separating-categories '((?L . ?U) (?_ . ?L) (?_ . ?U))) (setq evil-little-word-combining-categories '()) Finally, redefine movement commands by using these definitions. Since Evil already have mechanism to deal with Emacs' word boundaries, all we have to do is to activate the above definitions before calling the original movement commands. This can be done by the following macro. (defmacro evil-with-little-word (&rest body) (declare (indent defun) (debug t)) `(let ((evil-cjk-emacs-word-boundary t) ; turn off CJK word boundary (word-separating-categories evil-little-word-separating-categories) (word-combining-categories evil-little-word-combining-categories)) ,@body)) With this macro, we are able to have redefinitions as follows: (evil-define-motion evil-forward-little-word-begin (count) "Move the cursor to the beginning of the COUNT-th next little word." :type exclusive (evil-with-little-word (evil-forward-word-begin count))) (evil-define-motion evil-backward-little-word-begin (count) "Move the cursor to the beginning of the COUNT-th previous little word." :type exclusive (evil-with-little-word (evil-backward-word-begin count))) ... I know this is a way-too-long solution, so I put them together with covering all uppercase/lowercase letters into an Evil plugin: https://github.com/tarao/evil-plugins/blob/master/evil-little-word.el I hope this helps you. -- Lintaro INA mail: [email protected]
participants (3)
-
INA Lintaro -
Michael Markert -
Simon Carter