Thursday, May 7, 2015

Edit Vim command lines like an Emacs-using pro

Certain things of the tip type and of the time-saving variety, when applicable to one’s Operating System of Choice, are too useful to forgo in favor of strict allegiance to The Other One True Editor. This I say by way of preface before pointing out how you can make use of (what turn out to be) very helpful Emacs-oriented shortcuts in your own local Vim instance.

It has been pointed out to me—I believe by means of an O’Reilly video series, Mac OS X Productivity Tips for Developers, which features sirs Tim Berglund and Matthew McCullough (I recommend this series, if you are an OS X user)—that certain Emacs-based key bindings involving the moving of cursors are actually built into OS X as it is. The two that I’ve been using most since I realized this are <c-a> (Ctrl+a) and <c-e> (Ctrl+e), which move the cursor to either the beginning (<c-a>) or end (<c-e>) of the text you’ve entered.

You need not be an OS X user to find these useful outside of Emacs, of course. If you’ve switched from The One True Editor to The Other One True Editor, or even if you haven’t but still want to edit command lines in Vim, you may be interested in the following mappings, which are available from :help emacs-keys and which I just discovered recently while perusing tips.txt, as I recommended last time:

" start of line
:cnoremap <c-a>        <home>
" back one character
:cnoremap <c-b>        <left>
" delete character under cursor
:cnoremap <c-d>        <del>
" end of line
:cnoremap <c-e>        <end>
" forward one character
:cnoremap <c-f>        <right>
" recall newer command-line
:cnoremap <c-n>        <down>
" recall previous (older) command-line
:cnoremap <c-p>        <up>
" back one word
:cnoremap <esc><c-b>    <s-left>
" forward one word
:cnoremap <esc><c-f>    <s-right>


That is all taken directly from tips.txt. Quite splendid stuff; I wouldn’t necessarily use all of those, but at least I can now have <c-a> and <c-e> in Vim’s command line, with the others also there in case they should prove useful.

Tuesday, May 5, 2015

Counting occurrences of a string in Vim

On Stack Overflow, Chase T. points out a most useful item in the Vim help, which relates to counting phrases (strings) in the current buffer, which is usually the current file, which is typically long enough that you’d want a command to save you the trouble of just reading through it yourself looking for matches. I will readily admit that string counting is something I don’t do enough to remember how to do without Googling, and yet which I do just enough that I’ve had to Google it more than once. Mayhap this will help me next time?

Toward the point.

The item is count-items, as in :help count-items. The command is simple enough: it’s none other than :s!

As example:

:%s/sympathy/&/gn

35 matches on 35 lines

:%s/sympathy with sounds/&/gn

1 match on 1 line

(Yes, I’m still using Sir Cowper for an example. His Life is now out, in many splendid ebook formats, by the way—go get it from Gutenberg.org yourself.)

When we last saw :s (:substitute), we didn’t cover every aspect of its operation, for example its flags (we were mostly interested in how it operated on a range). For help in understanding the particular :s incantation used here, we can go to :help :s_flags, or more particularly :help sub-replace-special. There we see:

When the {string} starts with "\=" it is evaluated as an expression, see sub-replace-expression.  You can use that for complex replacement or special characters.

Otherwise these characters in {string} have a special meaning:


[…]

magic    nomagic     action    ~
  &      \&          replaced with the whole matched pattern


The & simply stands for the term we’re searching for, so that if we were actually replacing the term, it would replace it with the term itself. We add the n flag to prevent a substitution, but to see that this is indeed how it works, you can go ahead and run the search command without the n:

 :%s/sympathy with sounds/&/g

You should see nothing happen. If that’s not sufficient to convince you that Something Changed, try running u (undo).

So n tells the command not to replace a match. What else does it do? And why are we getting the number of matches after running the command when normally :s does not tell us how many there were?

[n]    Report the number of matches, do not actually substitute.

Ha ha! It turns out that this is basically just a nifty addition to our trusty search-and-replace command—something to let us know how many times a phrase would be replaced. Lacking any dedicated expression-counting command as we are, it also happens to be our best means of counting occurrences of a string in Vim.


For further fun: Note the filename of the help file in which we find :help count-items. It is:

tips.txt

with the explanatory heading:

Tips and ideas for using Vim

Earthquakes and hotcakes! (This is being written by Mr. Moolenaar himself, after all.) It may not be the hugest file in Vim’s help set, but give it a peek nonetheless.