Archive for March, 2010

I was over at vimcasts and I stumbled upon the episode on Tidying whitespace.

They came up with a function that removes trailing whitespace. Unlike my “homemade” solution, it goes the extra mile by keeping the history clean and putting your cursor back to where it was before you invoked the command.

function! <SID>StripTrailingWhitespaces()
  " Preparation: save last search, and cursor position.
  let _s=@/
  let l = line(".")
  let c = col(".")
  " Do the business:
  " Clean up: restore previous search history, and cursor position
  let @/=_s
  call cursor(l, c)

There’s room for improvement, however. Although the Single Responsibility Principle is used to talk about classes, arguably it also applies to functions. That function doesn’t do one thing, it does two (useful) things: saving the “state” and executing a command to remove the trailing whitespace.

Here’s a function that preserves the state:

function! Preserve(command)
  " Preparation: save last search, and cursor position.
  let _s=@/
  let l = line(".")
  let c = col(".")
  " Do the business:
  execute a:command
  " Clean up: restore previous search history, and cursor position
  let @/=_s
  call cursor(l, c)

Notice how you can inject the command into that function. Even if Vim does function pointers (to some extent), let’s just punt on this one and pass a string.

Here’s the mapping to strip out trailing whitespace:

nmap _$ :call Preserve("%s/\\s\\+$//e")<CR>

Back on Tidying whitespace, k00pa mentioned in the comments how he modified the original function to perform the same indentation. But, it was a copy and paste(!). With the “Preserve” function, we can turn this into a one-liner.

:call Preserve("normal gg=G")

Read Full Post »

deps: what am I missing?

Over the years, I’ve had to set up my work environment on many computers. By “work environment”, I don’t necessarily mean work-related — just the configuration and customizations I like to get things done.

The first things I do on a new computer is download my dotfiles and symlink everything correctly. Under a minute, I can be up and running with all the software I use configured the way I like it. Then, I usually pick a new prompt color (from 256!) to visually identify what machine I’m logged into.

I share my config files across computers by pushing/pulling to github [1].

For years, I’ve been very happy with this setup.

The Problem

The problem is what happens after. At some point, I’m going to type a command and it’s not going to be there.
screen not found
I forgot to install it… no big deal.

BUT! Now, I’m probably going to emerge --sync, apt_get something, port install whatever — the point is, when I typed that command, I was getting into the flow and now I’m not anymore: I’m probably swearing and/or doing some sysadmin.

A Possible Solution

I had a vision:

deps screenshot

The point of deps is to answer “what am I missing?”.

That screenshot shows the output of deps on two different computers. It’s a simple script but it automates a haphazard process I used to do by hand. I would sit there, try to come up with what I need, get most of it right but miss a few commands.

Of course, you and I probably have very different ideas of what a “work environment” looks and feels like. That’s ok, this script is meant to be customized.


RED=$(tput setaf 1)
GREEN=$(tput setaf 2)

ATTR_RESET=$(tput sgr0)

# ok_failed(cmd, description)
ok_failed() {
  local cmd=$1
  local description=$2

  eval $cmd > /dev/null 2>&1

  if [ $? == 0 ]; then
    echo "[${GREEN}  OK  ${ATTR_RESET}]" $description
    echo "[${RED}FAILED${ATTR_RESET}]" $description

# check_installed(prg_name, cmd_name=prg_name)
check_installed() {
  local prg_name=${1}
  local cmd_name=${2:-$1}

  ok_failed "which $cmd_name" $prg_name

check_installed vim
check_installed screen
check_installed git
check_installed awk
check_installed sed
check_installed ruby
check_installed gem
check_installed rake
check_installed cap
check_installed tidy
check_installed xmllint
check_installed spidermonkey js

That’s a snapshot when I wrote this post. The up-to-date version (which will change over time) can be found in my dotfiles.


[1] It could be anything though, I used to do that with subversion and mercurial before. Also, you might not want to make your files public like I did. Do what’s right for you.

Read Full Post »