On 2013-02-20, Christoph LANGE <[email protected]> wrote:
Hi all,
on the one hand I welcome the new commands evil-shift-right-line (C-t) and evil-shift-left-line (C-d) in insert mode, as this has been one of the features I had always missed in evil.
And it is good that evil-shift-right-line is bound to C-t instead of C-i as in vim, as C-i does other useful things in Emacs.
C-i should never be bound, because it's exactly the same key-event as TAB in the terminal.
However, one of my most frequently used Emacs functions in insert mode has so far been transpose-chars, which is what Emacs binds to C-t. (Transposing two characters in vim is a PITA; you'd have to do "_xp in command mode.)
This was exactly what I've been afraid of and why I was reluctant to add this binding. I asked in #evil and we came to the conclusion that it's easier to remove a binding than to add a new one, so if one doesn't like C-t in its current form then (define-key evil-insert-state-map "\C-t" nil) is sufficient to get rid of it. But of course, the question is what to do if you have two potential commands, both candidates for the same key, and you can't live without one of them. I don't know. Probably the best is to find an alternative binding for one of the two commands.
So I came up with the following for my .emacs:
(defadvice evil-shift-right-line (around evil activate) "call transpose-chars if universal argument given" (if (equal current-prefix-arg '(4)) (transpose-chars 1) ad-do-it))
I would never use an advice. If the advised function is called somewhere else, e.g. as a subroutine (which is currently not the case for `evil-shift-right-line`, but who knows the future ...) this could easily introduce strange bugs. It's better to write a new command and bind it to \C-t.
This gives me transpose-chars with C-u C-t, and evil-shift-right-line with C-t.
The only drawback is that it unconditionally calls transpose-chars with an argument of 1, but so far I have never used it with different arguments anyway.
You could check whether the prefix argument is a number and pass that number as count to `transpose-char`. I would do (defun shift-right-or-transpose (count) "Some really descriptive doc should go here, but I'm too lazy ..." (interactive "P") (cond ((null count) (evil-shift-right-line 1)) ((numberp count) (transpose-chars count)) (t (transpose-chars 1)))) (define-key evil-insert-state-map "\C-t" 'shift-right-or-transpose) Then you can use, in addition to C-t for right shift or C-u C-t for a single transpose, C-u 5 C-t or M-5 C-t to transpose 5 characters. If we get the possibility to have C-t and C-t C-t bound both in insert state one could, e.g., use C-t for indent and C-t C-t for transpose, which could also be a solution. Unfortunately, this does not work yet, until we find someone who implements this ... ;) Best regards, Frank