Strategy to maintain dotfiles for different OSs (i.e. osx and ubuntu)
Solution 1:
For shell scripts like .zshrc you can use an environment variable or the answer to some command like uname. But for non-shell dotfiles like .vimrc you should do the manual work of commiting patches from one branch to another (from one OS to another).
Solution 2:
In addition to Envite's answer: I use one common .zshrc
file, where all ,,portable'' stuff (like shell function definitions etc.) is included. Additionally, I have an extra file .zshrc-MACHINE_A
etc. for every computer where I'm using the shared config. Here I define e.g. the PATH
, some alias reflecting the current installed programs and so on.
The last part of my common .zshrc
file reads
# load $HOST specific setting
if [[ -f ~/.zshrc-$HOST ]]; then
[[ ! -f ~/.zshrc-$HOST.zwc || ~/.zshrc-$HOST -nt ~/.zshrc-$HOST.zwc ]] && { zcompile ~/.zshrc-$HOST; print - compiled \~/.zshrc-$HOST. }
source ~/.zshrc-$HOST
fi
According to man zshparam
the parameter $HOST
contains the current host name, hence should be portable and saves an external program call.
And every time the according .zshrc-$HOST
file is changed it'll get compiled (via zcompile
). The compilation serves the purpose of (I quote man zshbuiltins
):
(...) faster autoloading of functions and execution of scripts by avoiding parsing of the text when the files are read.
Probably nowadays you won't notice any difference(?), but it won't hurt either. Btw. the compiles *.zwc
files are architecture dependent and cannot be exchanges between different systems.
Solution 3:
Here is the best solution I've come across. I recommend clicking the link rather than reading about it here:
THE IDEA
I've adapted @holman's ideia of symlinking files whose filename ends with ".symlink", and instead I'm symlinking files whose filename matches the regular expression
\.(<os>-)?symlink$
. By doing that, I can have files that are always symlinked, and files that are symlinked just in a specific environment.For example, in my
~/.gitconfig
I include~/.gitconfig_include
, which contains OS-specific configurations.[include] path = ~/.gitconfig_include
Then I have two .gitconfig_include files: one for Linux and another one for Windows.
dotfiles |-- git |-- .gitconfig.symlink |-- .gitconfig_include.linux-symlink |-- .gitconfig_include.windows-symlink
This allows a symlink to have the same name, but different targets, depending on the OS.
Unfortunatelly, this strategy wasn't enough to handle all the requirements for my cross-platform dotfiles.
Vim's bad decision on Windows
For some reason, Vim looks for its files in
~/vimfiles
instead of~/.vim
on Windows. This means that, if I wanted to maintain the same strategy, I would have to duplicate the files folder—which I didn't want to do, for obvious reasons.dotfiles |-- vim |-- .vim.linux-symlink |-- vimfiles.windows-symlink
Instead of duplicating the files folder, I've created a file matching the folder's name, with the ".symlinks" extension.
dotfiles |-- vim |-- .vim |-- .vim.symlinks
The .vim.symlinks file contains the symlink name for each environment.
linux: .vim windows: vimfiles
This allows a symlink to have different names, but the same target, depending on the OS.
THE WORKING SOLUTION
If you want to check how everything ended up, please visit my dotfiles on GitHub.