Having my :vim and M-x emacs-ing it too

In 2008 or so, I switched from Textmate to vim. Then from vim to emacs. Then emacs to vim. Back to emacs. Vim. Emacs. Vim.

Then I discovered Vimpulse for emacs, and that was that.

Vimpulse is now Evil and it’s better than ever.

Here are some great tweaks.

[lisp gutter=”false”]
(evil-define-motion evil-little-word (count)
:type exclusive
(let* ((case-fold-search nil)
(count (if count count 1)))
(while (> count 0)
(forward-char)
(search-forward-regexp "[_A-Z]\\|\\W" nil t)
(backward-char)
(decf count))))
[/lisp]

This is essentially clw from a previous post, but here we’re defining a new unit of editing. This lets you:

[lisp gutter=”false”]
(define-key evil-operator-state-map (kbd "lw") ‘evil-little-word)
[/lisp]

And then you’ve got clw and dlw which delete the “one” in “oneTwoThree” or in “one_two_three”. I use this all the time.

Here’s something even more useful: Ever boil over because in emacs (and vim for that matter) every text deletion pulls that text into your kill-ring (register)? I sure do. Sometimes, I just want something gone, and I never want to see it again!

More often, I want to paste something from my clipboard over something else, which requires that my clipboard not be messed with by the pasting process.

(Emacs translation: More often, I want to yank something from my kill-ring…)
(Vim translation: More often, I want to put something from my default register…)

[lisp gutter=”false”]
(evil-define-operator evil-destroy (beg end type register yank-handler)
(evil-delete beg end type ?_ yank-handler))
[/lisp]

There is some unfortunate copy and paste code going on here, and I’d be happy to hear about how to eliminate it, but in essence this is just the d operator (delete), but without any clipboard operations going on. (Note the updated, cleaner implementation, inspired by Russell’s comment.)

You can then bind this to something, I use X, and utterly and irrevocably DESTROY some text. But that’s not end game. Next step is this:

[lisp gutter=”false”]
(evil-define-operator evil-destroy-replace (beg end type register yank-handler)
(evil-destroy beg end type register yank-handler)
(evil-paste-before 1 register))
[/lisp]

This will replace a bit of text with whatever’s in the clipboard without altering the clipboard, and I use this all the time.

I bind it to q, which, yeah, is supposed to be for evil macros, but I’ve got emacs macro bindings, so that’s fine.

This works with motion and text objects, so you can do things like yi" to copy between double-quotes and then qi"┬áto paste inside different double-quotes (assuming you’ve bound to q). qi(, qi' and qi{ all also work as you’d expect.

This is incredibly useful, and once you have it, you won’t know how you lived without it. It is also possible in vim. Read all about it here (the second response) http://stackoverflow.com/questions/2471175/vim-replace-word-with-contents-of-paste-buffer.

One last thing, and this one is great!

[lisp gutter=”false”]
(defun whitespace-only-p (string)
(equal "" (replace-regexp-in-string "[ \t\n]" "" string)))

(defadvice evil-delete (around evil-delete-yank activate)
(if (whitespace-only-p (buffer-substring beg end))
(evil-destroy beg end type register yank-handler)
ad-do-it))
[/lisp]

What does this do? Only the best thing ever! With regular, pull-into-the-clipboard deletion, things work as usual. However, should you delete a blank line (or any whitespace-only region), the clipboard is left alone.

Ooooooh lordy, that’s nice. No more pushing blank line deletions into your clipboard! Who wanted that anyway?

(If anyone knows how to build a similar solution for vim, post to the comments.)

About selah

Programmer at Prominence Advisors. Also dabbling musician. Also cycling commuter.
This entry was posted in Emacs, Programming, Vim and tagged , , . Bookmark the permalink.

5 Responses to Having my :vim and M-x emacs-ing it too

Leave a Reply

Your email address will not be published. Required fields are marked *