### svn binding for vim

4 July 2009

Lately, I've been making an effort to clean up my development tools and methods. I got onto the Subversion train a little late in the game — 1&1's basic web hosting doesn't support version control in any natural way — but figured I've gone too far without any sort of versioning system.

Moving to VCS was awesome, through-and-through. No more crappy FTP utilities! I just commit and let a shell script on the server move everything to dev. Had I known it was going to be this simple, I would've done it a long time ago (having been introduced to VCS courtesy of CVS, I assumed all versioning systems were a pain to use).

Still, I use vim heavily in my day-to-day code management, so I was having to do a lot of save, switch-to-cmd, commit, switch-back, edit, repeat, which is really still a pain. I knew vim has a pretty substantial binding ability, and this seemed like a good way to look at the innards. To be honest, I've traditionally just used it as a lightweight, glorified text editor with awesome regex support.

In vim, any command beginning with :! is executed through the system shell. In Windows, this means that if you run :!cd, you get a printout of the current working directory (generally, the directory the file you're editing is in, but I haven't pushed that). This means that we can put some generic batch script somewhere on the system path, and it will execute straight from vim. If I could only leverage that into something useful for SVN commits...

By no means am I terribly good with Windows batch scripting, but I can do a thing or two (or at least hack together some Perl scripts to string along). Enter svnc.bat, living on the system path:

@ECHO OFF

SET chain=
GOTO SETCHAIN

SET chain=%chain%..\

:SETCHAIN

IF NOT EXIST %chain%.svn GOTO SVNERROR

ECHO Going to commit %chain%.
SET /P message=Please enter a commit message:
SET message=%message:"=^"%
CALL svn commit %chain% -m "%message%"

GOTO END

:SVNERROR
ECHO Error: cannot locate parent .svn directory. Terminating.
EXIT 1

:END


It's simple: it just looks at parent directories until it can't find ..\.svn, then assumes that's the top level of the project. It asks for a commit message, then does its business. Easy peasy (you might argue that this should only commit a single file, but given my general usage, it makes sense to commit all changes). This doesn't take care of adds or deletes, but they're comparably rare, and could be scripted up as well.

How does this hook into vim? vim allows command binding via the map command. That is, map cmd1 cmd_str will cause vim to execute cmd_str whenever cmd1 is called. Awesome.

Put two and two together, and all we need to do is open up .vimrc and add the line map commit :!svnc (since svnc.bat is on PATH). Now all that's necessary during a vim session is <esc>-commit-<enter>, and the commit process is taken care of. Victory! vim mappings are great.

Included $$\LaTeX$$ graphics are generated at LaTeX to png or by .