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:


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 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:


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.

Thursday, March 5, 2015

Two plugins which (you and) I will be looking into

Not much time to collect philosophizings for here have I had so instead, have links to two plugins which I have both tried briefly and failed to yet try for long enough:

  1. cmdalias. This is by Hari Krishna Dara and the short version of its story is that it replaces :cabbrev for you, or rather gives you a wrapper function which, as I understand it, creates aliases (to replace “abbreviations” as :cabbrev creates) and only allows those to be expanded when they begin a command at the Vim command line.

    I toyed with this briefly—obviously it would relate to the trick #2 of my five weird tricks, and I do use those abbreviations but I was not able (in my brief experimenting with it) to set up a suitable replacement using cmdalias. I am perfectly willing to put that down to my lack of time spent on it rather than the plugin itself for now, so I may yet post on how you can replace that trick’s code.

  2.  Seek. By Vic Goldfeld, this creates a motion using s. (I mention this one in the book, by the way, as a good source, code-wise, of inspiration for new plugin authors.) The motion takes two characters and moves the cursor to where they appear in the current line (so it’s like a more-specific f). I don’t doubt that this is useful in practice, but I use s a lot to a replace text, and was having some difficulty reconciling Seek with my current customs in that regard. More work is needed here, since Seek does consider such use (and has had more thought put into it by its author so far than by me as a user).

So. Try those out yourself (I command you), and hopefully I will have more to say about them in future postings. Meantime, happy Vimming!

Tuesday, March 3, 2015

Two of my most-used Vim mappings (yo)

I’ve been complaining (sometimes misdirecting my complaints) about this being broken for a while now, so perhaps as I have it working again now I might as well give it a Shout-Out.™

One of the cool things to result from my recent re-upgrade to Vim 7.4 was the return of the * clipboard. I have these two (well, four, with the comments) lines in my .vimrc:

" In visual mode, use Y to copy to system clipboard
vnoremap Y "*y

" In normal mode, do the same with the current line
nnoremap Y "*yy

They might explain themselves (well, with the comments), no? In case they don’t: They map the Y key so that it yanks text into the * register. This register represents Vim’s view of your OS’s clipboard… it’s a little hard to get from the docs, but here is from clipboard under :help quotestar:

There is a special register for storing this selection, it is the "* register.  Nothing is put in here unless the information about what text is selected is about to change (e.g. with a left mouse click somewhere), or when another application wants to paste the selected text.  Then the text is put in the "* register.  For example, to cut a line and make it the current selection/put it on the clipboard:


Similarly, when you want to paste a selection from another application, e.g., by clicking the middle mouse button, the selection is put in the "* register first, and then 'put' like any other register.  For example, to put the selection (contents of the clipboard):


(I copied that using my Y mapping! Hee, hee!)

This was not working for me on pre-7.4 Vim, but it is on post-7.4. Also, I do not know what the hubbub seems to be about left mouse clicks or middle mouse buttons; I just use a keyboard-derived visual selection in Vim. So what this means is that I can select text using v or V (Vim’s visual mode, either linewise or characterwise), hit Y, and then Cmd+V into TextEdit, or Messages or Blogger via Firefox. (I’m on a Mac.)

This is hugely helpful, since I prefer to deal with text from inside Vim (and I use terminal Vim), but then of course text is often needed elsewhere and to be dealt with from within other apps. My terminal emulator (iTerm2, although I don’t know that I use any of its distinguishing-from-Terminal features) was always more or less a first-class application in this regard, but not its Vim; with these mappings making use of this register, I can copy from Vim and then paste into primitive text-handling facilities unaware of its existence anything.

Tip #984 on the venerable Vim Tips Wiki covers this, with additional and related discussion.

Thursday, February 26, 2015

First Step In Z Shell (AKA “Give Me a Prompt or Give Me bash”)

published by Suby

Ironic, isn’t it, that for the prompt being maybe the coolest and flashiest thing that you always hear about Z shell (zsh), when you first switch from bash you get this:


So it’s giving us the computer name (or hostname), and then uses a % as delimiter before our input begins (where bash uses a $). This, by itself and with nothing else to recommend it to our collective impressionability, is not exactly what we in the geosciences* call “earth-shattering stuff.”

This is more like what I normally saw as the prompt (on OS X) when I was on bash:

Scrooge-and-Marley:bookshelf ebenezer$

Let’s start simple and just try to replicate that on zsh for now.

Ye Olde prompt string

The relevant setting (or “parameter”), in both bash and zsh, is PS1 (zsh also allows PROMPT). Both shells have a nice array of special characters which we can use, escaped, to represent various bits of info which we want in our command prompt (the prompt string). My old OS X bash prompt used three, which are listed under PROMPTING in the man page for bash:

h    the hostname up to the first `.'
W    the basename of the current working directory,
     with $HOME abbreviated with a tilde
u    the username of the current user

In bash, these are escaped with a \, so this would have been the value of PS1 there:

\h:\W \u\$

Or, quoted as we could set it with export:

export PS1='\h:\W \u\$ '

So now to make that, but in zsh.

The new prompt string (New Look, Same Different Taste)

zsh has a huge manual, which (as it explains in man zsh—that acts as a sort of index) is broken out into different sections. The relevant one here is:

man zshparam

…except that it turns out it’s not. Well, it sort of is. Here’s what it says for PS1:

       PS1 <S>
              The primary prompt string, printed before a command is read.  It undergoes a special form of expansion before being displayed; see EXPANSION OF PROMPT SEQUENCES in  zsh-misc(1).  The default is `%m%# '.

So, to man zshmisc!

Under SIMPLE PROMPT ESCAPES, we have a list: the special characters which stand for informational bits in our prompt string. These are the three which correspond to our bash special characters:

       %m     The hostname up to the first `.'.  An integer may follow the `%' to specify how many components of the hostname are desired.  With a negative  integer,  trailing  components of the hostname are shown.

       /      Current working directory.  If an integer follows the `%', it specifies a number of trailing components of the current working directory to show; zero  means  the  whole path.  A negative integer specifies leading components, i.e. %-1d specifies the first component.

       %n     $USERNAME.

If you do not yet have a .zshrc, create one. This can be its first line:

PS1='%m:%1d %n$ '

We can see the % for escaping rather than \ (as bash uses), of course. Other than that, we have the hostname (%m), a literal colon (:), the first item in our current working directory path (%1d), a space, and then our username (%n) and a literal dollar sign ($).

The %d confused me for a bit (I am not a Nobel-winning rocket scientist). Using the example in the man page, I tried something like

PS1='%m:%-1d %n$ '

which gives us something like:

Scrooge-and-Marley:/Users ebenezer$

Yes, the first item is indeed the first. (Who would have thought? A Nobel-winning rocket scientist would have, for one.)

So there you have a familiar (if you’re a fellow switcher from bash) prompt. Obviously we’ve not really taken over the world here—this is just about (if you’re also on OS X) getting back to what you were used to—but we now know how to modify prompt strings, or at least one of them, in zsh. Stay tuned for more exciting updates in this space…

(I stole the title of this post from that of the excellent book by James Ward and Bruce Eckel, First Steps in Flex.)

* I am not in the geosciences.

Tuesday, February 24, 2015

A More Betterer Autosave In Vim

Run :version in your local Vim. What do you see?

Here are the first two lines I get:

VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Feb 24 2015 14:04:47)

That 7.4 is the key thing.

I actually wrote in old time (December 2013, as I recall; this was on an older site) about a cool new(-ish) autocommand event, or rather a pair of events, which someone sent a patch to the vim_dev list about—they were not mentioned in the help file. I don’t know when the events were added, but in Vim 7.4, the help file situation was remedied, and now we have this as the help for TextChanged and TextChangedI:

TextChanged            After a change was made to the text in the
                       current buffer in Normal mode.  That is when
                       b:changedtick has changed.
                       Not triggered when there is typeahead or when
                       an operator is pending.
                       Careful: This is triggered very often, don't
                       do anything that the user does not expect or
                       that is slow.
TextChangedI           After a change was made to the text in the
                       current buffer in Insert mode.
                       Not triggered when the popup menu is visible.
                       Otherwise the same as TextChanged.

I’ve (since writing that) upgraded to OS X Yosemite, and was back on its system Vim until today, in fact. (Its system Vim is a 7.3.) So I’d forgotten about these events, and was not even using an auto-saving trick for some time (until my last post, as it turns out). Then “Unknown” reminded me of the events (albeit indirectly) with a comment on that last post, “Save time in Vim NOW with these five weird tricks”, which mentioned an auto-saving autocommand as a bonus (sixth) trick:

Sadly auto-save a file when you leave insert mode doesn't do anything for edits made in normal mode (dd to delete a line etc)

(And yes, as you can see, I just upgraded to 7.4 again today. Yay Homebrew!)

I hereby, therefore, give you a new and improved (or at least improved) autocommand, Unknown! Here it is:

autocmd InsertLeave,TextChanged * if expand('%') != '' | update | endif

As the help text says, TextChanged watches for changes to the text (hmm—what a surprise!) when we’re in normal mode, which is where we do things such as dd, p, c, etc.; InsertLeave only notices that we’ve left insert mode (and thus lets us save all of the changes we made there, which is very nice of it). So the combined effect of the two events in this improved autocommand should be to take care of All Your Autosaving Needs (TM).

The one thing to keep in mind with this version is that, well, it saves after basically every change to the buffer. This means that after every accidental command or mis-pasted text, Vim will write the file. You can always undo it right afterwards, of course, if you notice it, but still. (Plus, as the help implies, this will cause our file to be saved quite often—normally we would consider this a Win, but if you’re the kind of Vimmist that’s doing 382,000,000,000 editing operations a second, who knows.)

So, I’m going to go with something like at the end of a recipe when they say “Salt to taste.” Try it out, and maybe it’ll prove massively helpful. (I’m trying it out again now myself.) Or, your taste might run more toward the old InsertLeave one (or even to not using an autosave at all—I would not understand that point of view myself, but to own his each).

Thursday, February 19, 2015

Save time in Vim NOW with these five weird tricks

[Yo. If you like these, check for additional tricks in the series: see posts labeled “Vim tips”.—Ed.]
It’s not just, as Alex, Mathias, and Andrew point out, that you can refactor your .vimrc (though, to be sure, you can—and probably should!). You can also niftily rework Vim, as it were, using this full-blown programming language to redirect its interface (your keyboard) in ways that save you time.

Here are five excellent ways to do that, which I’ve gradually come across in that unending fountain of Vim wisdom, the World-Wide Web. (Where I can recall a source, I’ve linked to it; also, I’ve sometimes tweaked such snippets for my own I’ll-have-you-to-know completely well-intentioned purposes.) Add the code from each to your .vimrc to try it out.

1. Exit insert mode without using Esc

inoremap jk <Esc>

This is for the “how can you possibly use Vim you’re always at the body shop for new pinky fingers you spend all day hitting Esc” crowd. Your right index finger is on the j key by default, right? And k is right next to that. So this is a brilliantly fast way to get back to normal mode, no Esc required.

Credit: This tactic is crazy-common among Vim masters, of course. I think I first came across the idea in Steve Losh’s epic “Coming Home To Vim”.

2. Allow mispelings when :wq-ing

cabbrev ew :wq
cabbrev qw :wq

:cabbrev is one of the abbreviation commands. It’s specific to commands, so that in the first word of each of these lines, when we type it, will be taken as the second word (the command—in this case, :wq).

3. Switch windows with two keystrokes

noremap <c-j> <c-w>j
noremap <c-k> <c-w>k
noremap <c-l> <c-w>l
noremap <c-h> <c-w>h

I use these all the time. Normally, to switch windows (split windows) in Vim, you have to do Ctrl+W and then a direction key (j, k, h, or l). This changes that to just Ctrl and then the direction.

Credit: Chris McKinnel’s Coderwall protip, “Speed up your already speedy Vim development”.

4. Enter command mode with one keystroke

nnoremap ; :
nnoremap : ;

Likewise this—now, instead of Shift+; to run a command, you can just hit the ; key. YOU’RE SAVING A KEYSTROKE!

(No, seriously—if you use the Vim command line as much throughout the day as I do, you’ll find that every such keystroke adds up. Use this. You’re quite welcome.)

Credit: Also Chris McKinnel.

5. Start an external command with a single bang

nnoremap ! :! 

To run an external command from within Vim, we just have to prepend ! at the Vim command line (as in :!date or :!ls). So that makes at least three keystrokes: (Shift+); and Shift+1—unless you use this mapping, in which case you can just hit Shift+1 in normal mode.



6. Auto-save a file when you leave insert mode

autocmd InsertLeave * if expand('%') != '' | update | endif

There are other ways to do this—I used to use something like this variation on #1 above:

inoremap jk <Esc>:w<cr>

Then I saw Romain Lafourcade recommending this autocommand on Stack Overflow, and switched to it right away. (A huge benefit of this approach: it catches, for example, when you leave insert mode via Ctrl+C—the InsertLeave event is triggered, as you might expect, whenever we leave insert mode.)

After the event (InsertLeave) and file pattern (*, or “any file”), we have an if statement which checks for something in the % special character.* If we’re editing a file, this will give us its filename; if not, it will return '' (an empty string). So we check for a non-empty string, and if we get one, we run :update (which saves the file only if it’s been modified—basically like a smarter :w). Then we end the if.

(Worth noting also is the | line separator. In VimL, this functions like the semicolon ; does in many other programming languages, denoting the end of a line and allowing us to continue our code all on the same line of the file, if we wish. We use it here to write all three lines of our autocommand’s code on the one autocommand line.)

UPDATE: See my newer post on this particular trick: “A More Betterer Autosave In Vim.”

And yourself?

What weird tricks do you have in your .vimrc?

* See :help cmdline-special for the whole list of those characters.