hmmm....

Syncing Zsh Named Directories

One of my most used features of zsh is named directories. I keep my dotfiles synced across multiple machines via Dropbox (referral link) and a Makefile that creates symlinks automagically.

My named directories start with ~ for my home directory so they need to exist for expansion to work properly and not output errors when I log in. When I first implemented syncing I added this check with a very simple test:

1
[[ -d ~/Dropbox/wiki           ]] && wiki=~/Dropbox/wiki

One line like this isn’t too bad but when you have 30, it gets a little silly looking.

I finally took the time to sit down and read the docs on zsh associative arrays and whipped up a much better solution.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typeset -A NAMED_DIRS

NAMED_DIRS=(
    bin      ~/Dropbox/Documents/bin
    docs     ~/Dropbox/Documents
    lbin     ~/Documents/bin
    wiki     ~/Dropbox/wiki
    dot      ~/Dropbox/Documents/dotfiles
    octo     ~/Dropbox/Documents/octopress
)

for key in ${(k)NAMED_DIRS}
do
    if [[ -d ${NAMED_DIRS[$key]} ]]; then
        export $key=${NAMED_DIRS[$key]}
    else
        unset "NAMED_DIRS[$key]"
    fi
done

The unset isn’t necessary here for the base functionality. I had another problem. With 30 or 40 named dirs, some belonging to projects that I might not have looked at in 6 months and suddenly need to come back to, it’s hard to remember the name I gave for a directory. I added an lsdirs function that lists just the named directories that existing on the machine I’m on.

1
2
3
4
5
6
function lsdirs () {
    for key in ${(k)NAMED_DIRS}
    do
        printf "%-10s %s\n" $key  ${NAMED_DIRS[$key]}
    done
}

This gives me nice easy to read output with both the names and the full path.

This blog post is more future reference for myself but perhaps it may be useful to you.

For those interested, here is the Makefile I use:

(Makefile) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
DOTFILES ?= $(shell pwd)
HOSTNAME ?= $(shell hostname)

all: shell code perl web mail

shell:
  ln -fs $(DOTFILES)/zsh/zshrc        ${HOME}/.zshrc
  ln -fns $(DOTFILES)/zsh/zsh.d       ${HOME}/.zsh.d
  ln -fs $(DOTFILES)/gnupg            ${HOME}/.gnupg
  ln -fs $(DOTFILES)/ssh/config       ${HOME}/.ssh/config

    ifeq ($(HOSTNAME),orion)
      ln -fs $(DOTFILES)/screen/screenrc_orion ${HOME}/.screenrc
    else
      ln -fs $(DOTFILES)/screen/screenrc  ${HOME}/.screenrc
    endif

code:
  ln -fs $(DOTFILES)/gitconfig        ${HOME}/.gitconfig
  ln -fs $(DOTFILES)/vimrc            ${HOME}/.vimrc
  ln -fns $(DOTFILES)/vim             ${HOME}/.vim
  ln -fs $(DOTFILES)/.tm_properties  ${HOME}/.tm_properties

perl:
  ln -fs $(DOTFILES)/perltidyrc       ${HOME}/.perltidyrc
  ln -fs $(DOTFILES)/perlcritic       ${HOME}/.perlcriticrc

web:
  ln -fs $(DOTFILES)/vimperatorrc   ${HOME}/.vimperatorrc

mail:
  ln -fs $(DOTFILES)/muttrc           ${HOME}/.muttrc

Comments