jasonwryan.com

Miscellaneous ephemera…

A Vimprobable Walkthrough

I have written about Vimprobable a couple of times over the last two years1, it is one of those projects that, for a variety of reasons, I have picked up and stuck with. Like dwm, Vim and tmux, it is an essential part of my working environment and is installed on all of my machines, where it is my default browser. It’s simplicity, power and configurability are why, despite looking at a few other similar projects, I have stuck with Vimprobable since first installing it.

After my last post, a dwm screencast, I wanted to have another crack at making a decent screencast. Sadly, this is not it. I can say that making a good screencast is not a simple accomplishment; there are so many elements that require significant attention. I spent a good many hours this time around playing with custom Xorg modelines, ffmpeg’s arcane encoding options and, to be frank, the final product is just not worth all that effort.

I’m going to stick with plain text from now on. It requires little more from me than a passing acquaintance with the subject matter, some loosely held and firmly expressed opinions and my unbridled confidence in the fact that anyone who has read this far down the page is so bereft of other, more pressing things to think about that they may inadvertently find a scintilla of amusement in here…

With that explanation out of the way, I give you my final screencast:

An Introduction to Vimprobable on Vimeo.

Notes

  1. First back in October, 2010 and then, more recently, in June, 2011.

A dwm Screencast

Over the last week as I have been at home convalescing I have, quite unaccountably, found myself watching videos of tiling window managers. In all, I have probably watched between twenty and thirty of these videos so I feel, quite confidently, that I have a firm grasp of what constitutes the genre. Consequently, I also feel that I can—based on the range of the material I have reviewed, and the scrutiny and attention therein applied—share an unequivocal judgement as to the overall quality of the genre: it sucks.

Moreover, these videos invariably suck in the same couple of ways; they always lack any sort of narration, which means that you are stuck silently watching some sort of paroxysm of window rearrangement without any context or explanation, as if the fact that you can inflict this sort of injury on an X display is rationale enough. And, secondly, just as frequently, they feature a cursor being dragged around the screen doing the damage; using the mouse to demonstrate the capabilities of a tiling window manager is the sort of vestigial behaviour more commonly associated with pagan superstition or mild enfeeblement…

Rather that simply bask in the sense of superiority that these observations have afforded me, I thought that I would make my own, more lasting, contribution to the canon. I can only describe this process as instructive.

The best that can be said of this video is that, while it sucks just as hard as the others that I have reviewed over the past week, it has the distinguishing feature of at least sucking differently. For example, it has an audio track, so in theory the actions on the screen should be accompanied by the narrator’s soothing tones. Sadly, this is not the case. The crappy quality of my headset, my hoarse throat, and most egregiously, my decision to eschew post production and shoot it in one take means that the audio is poorly recorded, and at times literally inarticulate, rambling.

If nothing else, the exercise has taught me to really appreciate the work of people who do this thing well; Drew Neil’s excellent Vimcasts being a case in point.

Improved Notes Utility

Nearly two years ago, I posted about my adaption of a simple command line note utility. I have used this setup on all of my machines on a daily basis since and it has worked marvellously. Symlinking to a folder in Dropbox means that the notes are accessible from all my machines, including my phone. There has only really been one aspect of this setup that has been sub-optimal.

As an inveterate note-taker (this is one of the “benefits” of ageing; the speed with which you forget information outpaces the acquisition of newer material) I have—in those intervening years—built up quite a store of notes. Consequently, in order to maintain a semblance of order, I have arranged them in a series of directories. There is a minor flaw with this approach: retreiving a note depended on two factors, a) excellent recall1 and, b) accurately typing out the full path. Neither of these are things that I am inherently good at or inclined to master.

This had been irritating me for some time before I came across this question on Unix & Linux StackExchange. This provided me with a partial solution to the issue but, as I note in my answer, I was not able to solve it for nested directories, which was my particular use case. Once I had muddled my way through the solution on U&L I pushed it to the back of my mind and tried to ignore it.

Recently, though, the accumulation of notes and the frustration of trying to access them without Tab completion drove me to do something about it.

The documentation on programmable completion is typically terse and searching the web returns very little in the way of instructions as to how to accomplish this.2 Undeterred, I decided to hack up a completion function that worked for nested directories.

What I arrived at was this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
shopt -s globstar
shopt -s progcomp

n() { $EDITOR $HOME/.notes/"$*".txt ;}

 # completion for notes
_notes() {
local cur
    cur=${COMP_WORDS[COMP_CWORD]}
    files=($HOME/.notes/**)
    file="${files[@]##*/}"
    COMPREPLY=( $( compgen -f "${file[@]}" -- ${cur} ) )
}
complete -o default -F _notes n

The best that can be said about it is that it nearly works…3

Realising that I was completely out of my depth, I turned to #bash for help, and I was indeed fortunate that geihra offered some much needed assistance. geirha’s solution is an elegant one:

1
2
3
4
5
6
7
8
9
10
n() {
local arg files=(); for arg; do files+=( ~/".notes/$arg" ); done
${EDITOR:-vi} "${files[@]}"
}

_notes() {
local files=($HOME/.notes/**/"$2"*)
    [[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]##~/.notes/}" )
}
complete -o default -F _notes n

In addition to working exactly as I hoped, it had the benefit of introducing me to a couple more bash concepts that I hadn’t encountered; adding elements to an array with +=() being one. For posterity, the full script is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
n() {
local arg files=(); for arg; do files+=( ~/".notes/$arg" ); done
${EDITOR:-vi} "${files[@]}"
}

nls() {
tree -CR --noreport $HOME/.notes | awk '{ 
    if (NF==1) print $1; 
    else if (NF==2) print $2; 
    else if (NF==3) printf "  %s\n", $3 
    }'
}

 # TAB completion for notes
_notes() {
local files=($HOME/.notes/**/"$2"*)
    [[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]##~/.notes/}" )
}
complete -o default -F _notes n

Notes

  1. The alternative to remembering the full path name is to list all of the notes before each operation with the nls function; this is not ideal either…
  2. Which means that it is either so straightforward that few have bothered to write up their experiences (most likely), or so arcane that not many have bothered (how it feels to me). However, there are a couple of pages that I referenced in addition to the official documentation:
  3. It fails, as geirha pointed out, because it breaks the filenames on whitespace.

Creative Commons image on Flickr by nicholasjon.