Friday, May 30, 2008

A Different Mark Jump

Most people know how handy marks are and most use them to jump to the exact location marked. You can also jump to the first character on the marked line rather than the exact location. Just use '{a-z} rather than `{a-z}.

Thanks to Nate for this tip as well.

Thursday, May 29, 2008

Two Copies, Same Buffer

Oftentimes I like to have two copies of the same window open in a horizontal split, so I can look at different pieces of code in the same file. Vim has a handy shortcut to quickly split the current file in a new window. Just hit ctrl-w s. A side bonus is that you don't have to save the file first unlike using :new filename.

Thanks to Nate for the tip!

Wednesday, May 28, 2008

Easier Shared Key Authentication

I use ssh shared key authentication to access a good number of servers I work on. In an effort to make things more secure, the shared keys usually have passwords associated with them. Generally speaking, I try to keep remote sessions alive inside of screen or just minimized on my current workspace, but I'm a habitual window closer, so I end up having to login again pretty regularly. Luckily, openssh has a facility that saves me from typing my passwords over and over again. I keep all my keys inside /home/myuser/.ssh for convenience sake. When I start my desktop session, I cd into that directory and do ssh-add *. It prompts me to type each distinct password once, and that's it. After that, the ssh agent has the password stored in memory until I terminate my desktop session.

Tuesday, May 27, 2008

Running Out of Space?

Running out of space on your HD? I am on a few of my machines. I found the following small Perl script that does a great job helping me locate redundant files. It recurses through a given root directory and looks for files of the same size. When it finds two files of the same size, it does an md5sum on them to determine if they're duplicates. It runs pretty quickly and is easy to tweak to pipe into other scripts.

Find duplicate files.

Thursday, May 15, 2008

Goodbye Console Beep

I guess the console beeps for a reason, but I find it annoying for the most part, and I can generally tell when something isn't working. Here's the procedure to disable console beep in X and on the console.

# Console
setterm -blength 0

# X Windows
xset b off

Start of Match

When searching or writing macros in Vim, it's sometimes helpful to have a search position your cursor at the end of the matching term rather than the beginning. You can use the start of match atom to accomplish this.

/some term\zs

This would match "some term" and position your cursor at the end of the match. See (help :regexp) for other atoms and general regexp goodness.

Thanks to Chris Sutter for contributing this tip.

Tuesday, May 13, 2008

Zsh Alias Suffixing

Here's a handy feature I just noticed with Zsh. You can specify a suffix when creating an alias, and execute an arbitrary command on the given file suffix.

alias -s php=vim
alias -s java=vim
alias -s pl=vim

Now typing "foo.php" on the command-line will open the file in vim automatically. You can get fancy and do stuff like:

alias -s org=firefox-2

Type "", and your browser goes to the URL.

Monday, May 12, 2008

Bash Substring Manipulation

I recently completed a project for work to automate pulling specific subversion revisions of code and publishing them to various servers. While relatively simple in practice, a number of operational dependencies had to be considered, and it had to be written in bash. I've done a bit of shell programming in the past, but never really written a "system" in shell. Not surprisingly, I learned a few things in the process, which I'll be sharing on this blog as they come to mind. One thing I learned, which will come in handy down the road, is that bash has a number of builtin substring operations. As an example, I had to trim a number of paths to insure that there wasn't a trailing forward-slash at the end. Obviously, there are a few ways of doing this, but I found a very convenient and simple idiom that I'll be adding to my toolbox.


removes shortest match of substring from end of string

so, if mydir="/home/travis/"

echo "${mydir%/}" will produce /home/travis
echo "${mydir%/*/}" will produce /home

What's nice as opposed to just chopping the last character off the string is that if the string is already formatted without a trailing slash, nothing will change.

echo "${mydir%/}" will produce /home/travis

Friday, May 9, 2008

Demystifying File Attributes

Unix based operating systems store three attributes regarding file access and modification. At least one of these attributes is a common source of confusion, and while it's generally a harmless mistake to misinterpret it's meaning, knowing what it actually means could save you some headache down the road.

atime (access time):

This is the last time a file was accessed or read. It's also updated when a file is executed.

view with: ls -lu

mtime (modification time):

This is updated whenever a file is modified.

view with: ls -l

ctime (change time):

This attribute is regularly confused for "creation time", which is totally wrong. It's actually not possible to determine a file's creation time on a Unix based OS. Rather, ctime actually means "change time". This flag is set whenever a files owner or permissions change or when the contents change.

view with: ls -lc

Thursday, May 8, 2008

Reverse Lines in a File

You can quickly reverse all lines in a file using the following ex command.


This is particularly useful for files that are in chronological order such as logs or email mbox files. Thanks to Skyler for submitting the tip.

Wednesday, May 7, 2008

Number Pad Madness

A friend of mine was trying to use the numpad inside Vim using Putty (Win32 SSH Client). Unfortunately, this wasn't working for him and was just echoing a bunch of alphabetic characters to his term. After looking online for a few minutes, we found a fix.

Go into Terminal->Features-> and check in "Disable Application keypad mode". Hopefully this helps some Windows users out there.

Tuesday, May 6, 2008

Right Help, Right Mode

Vim's help system is incredibly comprehensive and dare I say, "kick ass". One thing that initially frustrated me though was that searching for a keystroke (i.e., :help ctrl-p) would always return the documentation for normal mode. You can search help for any mode by prepending an identifier to your query (:help i_ctrl-p) would display documentation for ctrl-p from insert mode. (:help v_ctrl-c) would explain ctrl-c from visual mode. Also, remember you can tab-complete help to make finding the right document easier.

Monday, May 5, 2008


This is one of my favorite features in Vim. In fact, I use it so often that it didn't occur to me until recently that some people may not take advantage of it. If you're familiar with getting around on a modern shell (bash, csh, zsh, etc...), you're almost certainly acquainted with command completion. Vim offers a similar facility that works on the current buffers you have open (although it can do ex command completion as well ;-). When working in your current window, simply type a portion of a string (i.e., hereIsAReallyLong...) then hit ctrl-n. Vim should display a menu of possible completion options. Scroll up and down the menu with ctrl-p and ctrl-n. Hit enter when you find the entry you want to insert. This saves a lot of typing on longer method names and strings and also helps avoid spelling typos. If you find ctrl-p and ctrl-n too cumbersome to type or simply want to make completion feel more like it does on the shell, you can grab the SuperTab Plugin and use that instead.

Side tip: inside of ex mode, you can just use the tab key to complete your ex commands.

Friday, May 2, 2008

Finding Recent SVN Commits

Here's a quick Perl script I whipped up to ease finding newly committed files in our subversion repository. It's a little cleaner than what the client provides and nice to quickly find changes.

#!/usr/bin/perl -w

# quick script to succinctly display SVN changes since a given date
# usage: YYYY-MM-DD HH:MM

use strict;
use Date::Calc qw(Date_to_Time);

if (!defined($ARGV[0]) || $ARGV[0] !~ /^\d\d\d\d-\d\d-\d\d$/) {
die("Invalid date. Usage: $0 YYYY-MM-DD HH:MM.");

if (!defined($ARGV[1]) || $ARGV[1] !~ /^\d\d:\d\d$/) {
die("Invalid time. Usage: $0 YYYY-MM-DD HH:MM.");

my $date_thresh = date_to_epoch($ARGV[0], $ARGV[1]);
my $svn_file = "";
my $svn_date = "";
open(SVN, "svn info -R |") || die("Can't run svn client: $!");

while (<SVN>) {
if (/^Path: (.+)/) {
$svn_file = $1;

if (/^Last Changed Date: (\d\d\d\d-\d\d-\d\d) (\d\d:\d\d)/) {
$svn_date = date_to_epoch($1, $2);
if ($svn_date >= $date_thresh) {
print "$1 $2 $svn_file\n";

sub date_to_epoch {
my ($date, $time) = @_;
my ($year, $month, $day) = split(/-/, $date);
my ($hour, $minute) = split(/:/, $time);
return Date_to_Time($year, $month, $day, $hour, $minute, 0);

Remove Empty Lines

Here's a quick sub to remove all the empty lines in a file. I use this to cleanup after macros that leave a bunch of blanks.