The maze book for programmers!
mazesforprogrammers.com

Algorithms, circle mazes, hex grids, masking, weaving, braiding, 3D and 4D grids, spheres, and more!

DRM-Free Ebook

The Buckblog

assorted ramblings by Jamis Buck

Vim Follow-up

17 November 2008 — The fallout from the author's return to Vim is recounted, with a review of tips and plugins that have been found to be particularly useful — 4-minute read

So, it’s been over a month and a half since I switched back to Vim, and I figured I’d post a bit about how things are going.

I love it. Though the future is notoriously difficult to foretell, I think it’s safe to say that I won’t be switching editors again anytime soon. Vim is where it’s at, for me.

Here’s the combination of plugins and such that I’ve found work best for me.

MacVim FTW

Any Vim will do, really, but if you’re on a Mac, you really ought to consider MacVim. Like any self-respecting Vim port, it does the command-line really well, but it also has a great OS X GUI interface.

Settings

I’ve got my <Leader> character (:h mapleader) mapped to the comma (since it’s easier to reach than the backspace character).


let mapleader = ","

I’ve installed ack and have configured Vim to use ack for grep.

1
2
set grepprg=ack
set grepformat=%f:%l:%m

I’m a believer in spaces instead of tabs (let’s just agree not to go there), and I prefer a tab size of 2. I also like editors to try and guess the indentation level.

1
2
3
4
5
6
set tabstop=2
set smarttab
set shiftwidth=2
set autoindent
set expandtab
set backspace=start,indent

But, some file types really do require explicit tabs, and not spaces:

1
2
autocmd FileType make     set noexpandtab
autocmd FileType python   set noexpandtab

(Update: apparently, python can do tabs or spaces. All my python vimming for the last 8 years has been read-only, so it never actually came up.)

I like my lines numbered, syntax highlighting on, and highlighted searches:

1
2
3
set number
set hlsearch
syntax on

I’ve got quite a few other things tweaked in my .vimrc, but those are the major biggest ones.

Plugins

FuzzyFinder

The FuzzyFinder and FuzzyFinder TextMate plugins have become essential for me. For now, installation of the TextMate-like behavior is kind of painful, but I plan to get something up on the Vim scripts index in the nearish future.

My settings for FuzzyFinder TextMate:

1
2
3
4
5
let g:fuzzy_ignore = "*.log"
let g:fuzzy_matching_limit = 70

map <leader>t :FuzzyFinderTextMate<CR>
map <leader>b :FuzzyFinderBuffer<CR>

NERD_tree

Thanks to all who recommended the NERD tree plugin by Marty Grenfell. It really is fantastic, definitely the best-of-breed of VIM project/directory explorers. I especially like that it is easily toggled away. I usually keep it hidden, and toggle it open only when I need to browse to something. (Thanks to the fuzzyfinder stuff, my need for a project browser is pretty small, but when I need one, NERD_tree works great.)

1
map <leader>d :execute 'NERDTreeToggle ' . getcwd()<CR>

rails.vim

The rails.vim plugin is pretty extensive, and I’m currently only scratching the surface. I don’t use snippets at all (never did in TextMate, either), but the Rake integration is pretty handy, and I’ve used the migration generator pretty often lately.

I need to spend some more time reading the docs for this one, and practicing some of the commands, since I’m sure it could turn into a real time-saver for programmers (like myself) who spend a good part of their day in Rails code.

scratch.vim

I’ve really come to love scratch.vim. Sometimes I just need to jot down some numbers, or paste the result of some query, or even take notes on a phone call. Writing any of that on a scrap of paper is a sure way to lose the info. The scratch plugin lets me take notes right where I am all day: in Vim. It doesn’t come with a way to toggle the scratch buffer (which is odd), so I wrote a quick one:

1
2
3
4
5
6
7
8
9
function! ToggleScratch()
  if expand('%') == g:ScratchBufferName
    quit
  else
    Sscratch
  endif
endfunction

map <leader>s :call ToggleScratch()<CR>

tComment

Maybe it’s just my own coding style, but I find myself commenting and uncommenting large blocks of code on a daily basis. The tComment plugin from Tom Link is perfect for this. You can toggle comments by using the Vim motion operators, or just do a quick visual block followed by “gc”. Good stuff!

Others

There are a few other plugins I’m experimenting with (surround.vim, vcscommand.vim), but which I use infrequently enough that they haven’t become muscle memory yet.

Workflow

Because I prefer the GUI version of MacVim, I typically have only one or two terminal windows open. I then type “mvim” to open vim from the root of whichever project(s) I’m working on, and then use ”,t” (my FuzzyFinder TextMate trigger) to search for and open files. I also use ”,b” (my FuzzyFinderBuffer trigger) to search my buffer list if I know the file is already open.

Switching between buffers with the carat character ”^” is a huge time saver. I used to use :ls (to list open buffers) and :buffer (to jump to a buffer), but the FuzzyFinderBuffer has really taken the place of both of those.

Ironically, split windows (which I missed most of all when I switched to TextMate) have taken me the longest to fit back into my workflow. TextMate trained them out of me. :) That said, I’m still trying to fit them back in, and when I remember to use them, I love them.

You?

So, that’s me. How does Vim fit in your own workflow? What settings do you prefer, and why? And what customizations are you using in your own setup?

Reader Comments

I use vim from within IRB. Wrote a gem that sets it up. It’s got a quirk or two but it’s very productive for hacks and experiments. You go into IRB, type “vi”, pop into vi, edit your code, exit back into IRB, it evals the code. Repeat as necessary until you get the results you need. It’s a fun way to hack.

@Giles

I wish irb was half the repl that ipython is, where that ipython -> vim -> ipython workflow is explicitly supported. It sure is nice. Have you published that source anywhere?

@Jamis

I often have 9 splits open at a time, I use my 17” macbook for browser/terminal/etc and all of my 19” widescreen for vim when coding. It’s super nice to have it all open in front of me.

You really should leave your python code with expandtab, pep 8 is the canonical style guide for python and it says “Use 4 spaces per indentation level.”

There’s lots of good tips here: http://items.sjbach.com/319/configuring-vim-right .

My favorite personal bindings are:

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

which make maneuvering around splits much easier.

@Bill, thanks re: python indentation. I guess it never mattered since I haven’t written python in 8 years, and only rarely need to read python. :) That configuring-vim-right post is awesome, though. Thanks for the link!

Awesome, thanks a ton for posting this.

Right now I’m just trying to figure out how I’m going to use Vim after using TextMate for years … due to now running on Ubuntu exclusively.

Overall, I have a similar setup as you but with fewer plugins/scripts. The NERD-tree looks very interesting and I might work that in.

Because I tend to work on three separate machines at different times, I keep my .vim folder versioned with git and on GitHub. That’s been very nice so far as it allows me to keep everything the same across the three machines. I also keep my .vimrc file in there and then link it to my home directory so that I can keep it versioned as well.

I’ve checked out NERDTree, but prefer the Project plugin as it’s more, well, project-oriented. You use a project file that you can edit and refresh to include just the files you want. One powerful capability is to grep those files. rails.vim will create the file for you with the :Rproject command. Another feature is the ability to list files “flatly” instead of hierarchically. This can be different for each section of the project. Also, Project isn’t so cutesy-wutesy.

FuzzyFinder is great, but I tend to use its MRU list more than the file locator, which is why I haven’t given the Jamis version a try.

If you like the NERD_tree plugin, it’s also worth checking out Marty’s NERD_commenter plugin. I find the best place to track these is on GitHub rather than vimscripts.

The other big win recently was setting up standard vim for 256 colours (with the railscasts theme). With a better colour palette, it’s much more usable when doing those little sysadmin tasks.

Great Post! I love to see how other people get things done. The Fuzzy Finder ** plugins will really help me out a lot with my current project set.

Why not using rak instead of ack ? http://rak.rubyforge.org/

I don’t know ack but I like rak features (like ignoring vcs files) which makes it a nice replacement for grep imo.

@Mark, I absolutely LOVE that you call NERD_tree “cutesy-wutesy”. :) I don’t think there’s anything about Vim that I’d call “cutesy-wutesy”; it’s all very industrial-with-the-pipes-showing to me. :) I’ll check out the Project plugin, though I’m quite happy with NERD_tree.

@Jean-Philippe, I went with ack because it was recommended to me. It’s a pretty mature tool, and even Rak is “based on the Perl tool” (ack). They appear to have very similar feature sets, too.

For what I’ve seen for now, there are two kinds of vim users : those who love :set number (or :set nu) and those who don’t.

If you love :set nu, you’ll probably love :set cursorline too :)

My experience of the Project plugin was that I wound up spending as much time configuring it as actually using it. NERD tree is one of those things I almost never think about but use constantly. That said, I don’t really have any projects that are too big to be easily navigable via filesystem layout.

ack (or ack-grep, as the package seems to be called on Debian & kin) is sufficiently awesome that I seldom use grep on source code any more. rak may be equally nifty, but it does not appear to provide a “—thppt”.

I agree, I love seeing what other people use as plugins and config. Let’s see.

I don’t use either nerd_tree or project, at least partly because, due to a weirdness with voiceover and macvim, I can’t use vertical windows. When I arrow down, it reads the whole line, vertical windows included, <grin>. More than a bit offputting.

On the other hand, I usually know where my files are, and if I don’t, a standard vim directory buffer does well enough. Nerd_commenter for comments, vcscommand for version control, although I’m finding with git it’s easier just to use a terminal.

rails.vim, obviously. snippetsemu, and a handful of others I can’t remember right now, although I’m always experimenting. I’m trying to start using taglist, for example.

Oh yeah, and also a vim tail plugin, so I don’t have to switch between vim and a terminal all the time to see failing test output. I’ve got most of my test runners using sounds for success/fail, but I sometimes need to see why it failed, <grin>.

you must try out tabs! :tabe to open a tab gt to switch

Also there is NerdComment for commenting source

I’m in my 3rd or 4th week of VIM (MacVIm) and have not missed textmate at all, with one exception: I can’t seem to figure out how to do mult-file search and replace. How do you pull that off in VIM? (I’m using NerdTree, etc…)

When I made the move to vim full time it was because it had tab support finally. After years of using things like eclipse, komodo, etc I thought they were must haves.

Then I got into how buffers worked and splits and I never use tabs any more. Why would you need them?

Thanks for the tip on tCommenter. hadn’t seen that one and it seems to work well.

Some settings I love:

hooked on using ctrl-s for saving a file: ” shortcuts for saving with ctrl-s nmap <c-s> :w<cr> vmap <c-s> <esc><c-s> imap <c-s> <esc><c-s>

Moving with splits a little easier: ” Shortcuts for dealing with splits easier {{{ map <c-j> <c-w>j<c-w>_ map <c-k> <c-w>k<c-w>_ map <c-l> <c-w>l<c-w> map <c-h> <c-w>h<c-w>

and a fix so hjkl move ‘properly’ on wrapped lines like comments/emails/etc: ” mapping to make movements operate on 1 screen line in wrap mode {{{ function! ScreenMovement(movement) if &wrap return “g” . a:movement else return a:movement endif endfunction onoremap <silent> <expr> j ScreenMovement(“j”) onoremap <silent> <expr> k ScreenMovement(“k”) onoremap <silent> <expr> 0 ScreenMovement(“0”) onoremap <silent> <expr> ^ ScreenMovement(““) onoremap <silent> <expr> $ ScreenMovement(”$”) nnoremap <silent> <expr> j ScreenMovement(“j”) nnoremap <silent> <expr> k ScreenMovement(“k”) nnoremap <silent> <expr> 0 ScreenMovement(“0”) nnoremap <silent> <expr> ^ ScreenMovement(““) nnoremap <silent> <expr> $ ScreenMovement(”$”)

@Keith

if you do something like

:vimgrep /SomethingToFind/ */.java

it will search all java files from the current vim directory (whatever :pwd spits out) for the “SomethingToFind” string. You can then do

:cn :cp :cc

to cycle between finds. then do one find/replace by

:s/find-string/replace-string/

type :cn to go to the next result press & (the ampersand) to re-execute last substitution.

that’s how I currently accomplish a project-wide find/replace. Anybody else want to share how they do it?

Sorry, for some reason my comment got parsed weird.

the vimgrep command should be

:vimgrep /SomethingToFind/ ’* * / * . java’

where the string in the single quotes should have no spaces in it

cheers!

You could use the screen + vim ( http://technotales.wordpress.com/2007/10/03/like-slime-for-vim/ ) trick to directly execute code snippets from vim in irb.

NERDTree is wonderful, I prefer it to project. tComment is great also. I use the following commands to check syntax and run scripts from within vim.

:autocmd FileType php noremap <c-m> :w

/usr/bin/php %<cr> :autocmd FileType php noremap <c-l> :!/usr/bin/php -l %<cr>

:autocmd FileType ruby noremap <c-m> :!/usr/bin/ruby -w %<cr> :autocmd FileType ruby noremap <c-l> :!/usr/bin/ruby -cw %<cr>

:autocmd FileType perl noremap <c-m> :!/usr/bin/perl -w %<cr> :autocmd FileType perl noremap <c-l> :!/usr/bin/perl -cw %<cr>

Also I find the following status line useful:

set statusline=<%f%h%m%r=%b\ 0x%B\ \ %l,%c%V\ %P

Thanks for the idea of setting the leader to a comma! I used to use vimmate, but the file limits were getting in the way. NERDTree is the best solution so far for me.

I’ve never understood what C-^ is useful for.

Surely you have something easy mapped for :bn and :bp? (I use <left> and <right>) and along with C-O/C-I, toggling between two files or trying to remember a count-prefix for C-^ always seemed not useful.

Am I missing something?

Ok, I’m totally offtopic, but I oouldn’t add a response to your ontopic post. You probably don’t remember me, but we’ve corresponded about your gaming apps. Could you please send me the standalone version of the apps you made downloadable? My old computer crashed, and it didn’t occur to me that they wouldn’t still be around. I miss them terribly.

seren

You’ve not mentioned anything about SVN/CVS or any other source control integration, I’d be interested into finding out more about this.

Is getcwd() actually opening NERDTree in the current directory for you? I can’t get it to work.

Jamis, I’m selfishly glad you went to the dark side for awhile so you could come back motivated to find all these gems and report them.

As for split windows, the key to getting the most awesome out of them, IMHO, is remapping ctrl-hjkl to window navigation.

@Scott, I actually use FuzzyFinderBuffer instead of :bn and :bp. C-^ is super useful, though, for switching between the buffer you were just editing, and the buffer you are editing now. In other words, you’re in one file, want to check something quick in another, and then jump back. C-^ is great for that “jump back” part.

@seren, I’ve made the source code for those generators available in the public domain (http://github.com/jamis, look for the dnd-* projects), but I no longer support them. I do not have a windows build environment available anymore for building standalone versions.

@George, I hinted at it—the vcscommand.vim plugin. But as I said, it’s not one I’ve used enough for it to be really useful to me. I always have a terminal open anyway, so I just use that.

@Adam, yeah, it works for me, though I always start mvim after cd’ing to the root of my project. Maybe that’s the key?

Great post! I used the rails wiki article to help me get set up with vim+rail, but this post, and the configuring-vim-right post, did wonders for my vim set up! Thanks for the post, and thanks to all of the commenters; it was super, super helpful.

@David – Thanks – I’ll try that. Still not as elegant as TM…. And, I had forgotten about the & command. Damn there are a lot of commands :-)

Argh! Don’t use ‘set tabstop=2’.

What you mean is: ‘set sts=2’

Tabs should always be displayed as mod-8 horizontal spaces so that your code looks the same in less/more as in your editor; not everyone is going to be using the same tab width setting as you, so using ‘set sts’ to get what you want for indentation is a much better strategy and will let other people work with your code easily, too.

:help ‘sts’

Nice tip, Jeramey! I wasn’t aware of softtabstop (sts).

Glad to be helpful! Spread the good word about softtabstop; it’s one of my favorite vim features. :-)

If you like Ctrl-^, you'll love Ctrl-W ^. That opens the previous file in a new window.

@Scott: Ctrl-^ is different from :bn. That goes to the next buffer in the list, which is not necessarily the previously edited file.

Howdy chum

You dont need that autocommand to :set noet for make, it should already be set in the make ftplugin in the vim runtime. Go :e $VIMRUNTIME/ftplugin/make.vim to see.

Also, you can just go :nnoremap <leader>d :NERDTreeToggle<cr> (here http://pastie.org/318295 incase the formatting gets screwed up)

No need for getcwd() since it defaults to the current dir anyway.

Been liking your fuzzyfinder_textmate hax, I get a massive throbbing boner every time i activate it.

Also, you should make your ToggleScratch() function local to your vimrc (or where ever you defined it), like this http://vim.pastey.net/102188. Better not to add stuff to the global namespace unless you gawts to. </nit-pickz0r>

FuzzyFinderBuffer is pretty neat, but do you know if there’s a way to make it go to the result? As it is for me now, it just opens the file/buffer wherever I currently have focus, instead of going to whichever tab the file is currently open on.

I gotta ask, because I can not seem to figure out how to use FuzzyFinderTextmate to only search from the root of my project.

For instance, I have ~/Code/project1 open in NerdTree. When I invoke FuzzyFinderTextMate I want it to only search the files in ~/Cde/project1 and below, but can not seem to figure out how to define a root in FuzzyFinder. As of now it searches my entire drive, which takes forever. :(

Is there a command to set the root so that FuzzyFinder doesn’t go nuts and search my entire drive?

Thanks.

Hi,

Just a quick question regarding FuzzyFinder.

if I enter ‘pr’ and get two results: 34 projects/ 56 prz/

How do you select (get it into the cmd line) the first entry? If I use cursors + enter I open a file called projects If I use ctrl-n or ctrl-u, it selects prz in the command line

Thanks

no mention of matchit.vim – does everyone just include it by default and not bother mentioning it? anyway, if you do any sort of do/end type programming, it’s indispensable.

also, if you’re doing any sort of halfway-complex regexp stuff, use :rubydo or :perldo and pcres – it’s a lot quicker than figuring out the quirks of vim’s native regexps

I’m a Ruby on Rails programmer and I don’t like TextMate. I LOVE Vim but I didn’t know MacVim, FuzzyFinder… I’m very happy with this!

I’ll read all the comments and try all things. Thanks for all.

Hi Jamis. I looked for a way to contact you that wasn’t in a comment box for an article that’s high above my head. Unfortunately, I couldn’t find an e-mail address for you, so I hope you will forgive me.

I am looking for the INCREDIBLY useful D&D tools that you used to have posted at http://www.aarg.net/~minam/dungeon.cgi I’m running a 3.5 game while here at college and I used to use these generators a lot. Unfortunately, the site that hosted them seems to have disappeared. Is there any way they could be reposted somewhere, or perhaps I could get them in an e-mail attachment, etc.?

Again, apologies for putting this in a completely random place.

-Ben

@Ben, the source code for the generators is all in the public domain, hosted at GitHub: http://github.com/jamis (look for the projects that start with dnd-*). Aside from that, I’m afraid I no longer support them—but you’re welcome to do what you will with the source code.

I had to meantion another great rails.vim feature I just discovered: :Rgenerate migration CreateFooTable. script/generate creates the file with the long unwieldy timestamp, then rails.vim opens it for you. Also :Rpp which evaluates one line of code in script/console.

Thanks for the post.

I really love rails.vim, and couldn’t live without “gf, MyModel or

Reading the complete doc for this wonderful plugin is a must.

Unless it’s greatly improved, rak is not nearly as featureful as ack, although it is pretty slick.

Now, if I can only get the tarball searching working…

Hi Jamis,

I’ve recently released a Creative Commons-licensed book on Vim 7 which I thought might interest you – http://www.swaroopch.com/notes/Vim , would greatly appreciate any feedback and comments :)

Regarding the settings I use, I’ve listed some of them at http://www.swaroopch.com/notes/Vim_en:Plugins#Customization_using_vimrc

Regards, Swaroop

@Keith

To search and replace across all open buffers use

:bufdo %s/search_term/replace_term/g

More flexibility of how to match terms can be had by using the :g command. :help :bufdo and :help :g give more details.

just wanted to drop a line and thank you for the EXCELLENT textmate mod of fuzzy_finder. This is getting me to seriously consider to move back to Vim after a long while of jumping between editors like Emacs, Textmate, Notepad++ (using wine) etc. Thanks!

Oh, I should mention that I took the liberty of extending your excellent fuzzy_finder_textmate to enable users to provide a g:fuzzy_include in addition to g:fuzzy_ignore. I work on a rather large project with a lot of different filetypes, so it’s handy to be able to filter out source code in addition to ignoring certain filepatterns.

If anyone is interested in this mod, it’s available here:

http://dl-client.getdropbox.com/u/55205/fuzzy/fuzzy_finder_textmate.zip

Hi,

github-vim: http://github.com/solars/github-vim/tree/master and gist.vim: http://www.vim.org/scripts/script.php?script_id=2423

are really useful when working with github

I’ve spent quite a lot of time making (g)Vim work exactly the way I want it too. You can find all of it here:

http://steveno.wordpress.com/vimrc

Hi Jamis,

Version 2.16 of fuzzyfinder.vim breaks fuzzy_finder_textmate because:

function! g:FuzzyFinderMode.Base.launch(initial_text, partial_matching, prev_bufnr, tag_files)

is now:

function! g:FuzzyFinderMode.Base.launch(initial_text, partial_matching)

Version 2.13 works for me.

-Christian

Hi Jamis,

Your fuzzy finder textmate plugin works great on my machine but unfortunately I can’t use it on one of our servers at work because the vim installation does not have ruby built in. Any chance your forthcoming solution on vim.org will not rely on ruby? ;)

Matt

@Matt, I’m afraid I have no plans to do a pure-vim version of this. Please do feel free to port the code, though, if you’d like a pure vim version.

@Jamis: Thanks for the response. Perhaps I will try once I get enough vim fu.

In the meantime, I made a small patch to your version that makes it behave a bit more like the Textmate version. Instead of stripping space at the end of the pattern, I changed my version so it removes all spaces completely. This behavior is a little more consistent with Textmate, and for whatever reason i happen to hit space in my patterns sometimes.

I submitted a pull request to you on Github with the change.

Matt

Had a bit of trouble getting fuzzyfinder_textmate working. I’m working with the current HEAD version (b9d541db).

When it didn’t work with the latest version of Fuzzyfinder (2.19) I went back to 2.13 (reported above to work) and started working my way up to see what happened. Here are the different errors I get on doing :FuzzyFinderTextMate>

- Fuzzyfinder 2.1.3: “E119: Not enough arguments for function: 104”

- 2.1.4: same

- 2.1.5: same

- 2.1.6:

Error detected while processing function <snr>4_CompleteFunc..176:line 27: Errno::EACCES: /Users/wincent/.vim/ruby/fuzzy_file_finder.rb:218:in `open’: Permission denied – /Users/wincent/Applications/KisMAC.app/Contents/Resources/WLanDriver.kext

- 2.1.7:

Error detected while processing function <snr>4_CompleteFunc..176:line 3: E716: Key not present in Dictionary: exists_prompt(a:base) || len(self.remove_prompt(a:base)) < self.min_length

- 2.1.8: same

- 2.1.9: same

In the end, the only version I could get to work at all was 2.1.6, and only then by trashing the kext in the KisMAC.app that it didn’t like.

I had a similar issue to Wincent while trying to use FuzzyFinderTextMate with gvim 7.1 on ubuntu 8.10. I’m just posting to confirm that fuzzy_finder.vim version 2.16 fixed it for me as well.

Yep, experiencing the same behaviour Wincent & Keith are describing!

All, please see http://weblog.jamisbuck.org/2009/1/28/the-future-of-fuzzyfinder-textmate. I am no longer support this vim extension. It works fine for me, but if you need updates please consider forking the project and adding them independently.