Setting Up A Dotfiles Repo
A What?
A dotfiles repo is a catch all term that describes a repository - usually on github - that developers use to keep config files and settings that live (mostly) in the home directory. The most common files been .vimrc, .bashrc or .zshrc and so on. Some people include additional automation and scripts to help speed up setting up a freshly installed system.
Motivation
I've put a lot of effort into making sure individual repositories launch their dev environment instantly using Vagrant and production environments deploy consistently using Ansible, but the same wasn't true of re-installing my whole system or keeping my personal settings in sync between machines.
End Result
My dotfiles are at https://github.com/OddEssay/dotfiles
Vim
I've been using Vim (And vi) on and off for nearly 2 decades but I've never fully got why some people so passionately rave about it. Everyone who regularly uses Vim loves how much you can personalize it, but very few people articulated in a meaningful way how they were doing so and how that could help me. Which makes quantifying the advantages of using it yourself unclear and where to start a bit of an enigma.
A couple of months ago I decided to throw myself in at the deep end and get my head around what other people were doing and why they liked it so much.
My first stop was the Vim London Meetup, which gave some pretty insightful views on Vim usage and inspired me to keep going down the Vim rabbit hole.
The most useful resource was without doubt the Vim courses on ThoughtBot's UpCase site, and very quickly gave me some answers to stumbling blocks I'd hit in the past on top of that, seeing people actually use Vim both at the London Meetup and on the UpCase videos really narrowed the gap between abstract concepts and what people were actually doing.
Once I was thinking about making regular changes to my vimrc starting a dotfiles repo was an obvious path to take. In addition to my vimrc I've also started keeping my own cheatsheet file as a reference to the commands I've been working on learning and making a point of only adding one new plugin or set of commands at a time to build up a healthy understanding on all the moving parts.
tmux
Spending a lot of time in Vim in multiple terminals on a Mac isn't great, so using tmux to handle splitting a single terminal into multiple panes and switching between different sessions has become a major part of my current workflow.
One extra feature I've taken from Thoughtbot's dotfiles is a tat command for switching directory based context quickly which makes juggling multiple projects in a single terminal window really easy.
Git Hooks
I've been doubling down on fine tuning my workflow of late and taking full advantage of git-hooks to automate a bunch of tiny tasks which would on occasion trip me up.
The main things I've done are:
Make sure PHP Composer libraries match the current branch - Not tracking vendor files in git is great, but if you're not careful you can end up with the .lock file not correctly identifying what is actually in your vendor directory.
[ -e composer.lock ] && [ -e Vagrantfile ] && vagrant ssh -c "cd /vagrant; composer install" || true
Run grunt build to make sure assets are up to date and for the current branch - Again, when switching branches for different tasks or pulling down changes after someone else has pushed to that branch remembering to run grunt manually is a chore.
[ -e Gruntfile.js ] && grunt build || true
Run Rubocop on Rails and lint PHP files before committing - Automated style guides are great, but it's an order of magnitude easier to fix them before you commit then have to come back around later when a CI service flags up the error so checking which files have changed and testing them before allowing a commit reinforces this into a workflow.
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM) for FILE in $CHANGED_FILES do if [[ "$FILE" =~ ^.+(\.rb)$ ]]; then RUBY_FILES="$RUBY_FILES $FILE" fi if [[ "$FILE" =~ ^.+(\.php)$ ]]; then PHP_FILES="$PHP_FILES $FILE" fi done if [ -n "$RUBY_FILES" ] && [ -e ".rubocop.yml" ]; then echo "Running Rubocop on $RUBY_FILES" rubocop $RUBY_FILES if [ $? -ne 0 ]; then exit 1 fi fi if [ -n "$PHP_FILES" ]; then echo "PHP Linting on $PHP_FILES" for PHP_FILE in $PHP_FILES do php -l $PHP_FILE 2> /dev/null > /dev/null if [ $? -ne 0 ]; then echo "PHP Lint error on $PHP_FILE" exit 1 fi done fi
ZSH
I've been using Oh My ZSH for a while now and the default plugins have been a handy way to save a few key presses here and there, but expanding on that there are a handful of commands I find myself using over and over again that I've wrapped up in shortcuts to streamline my workflow.
The most useful additions so far, a vudo command to replace vagrant ssh -c
function vudo() { eval "vagrant ssh -c \"cd /vagrant && $@\"" }
Running composer update with the right flags and cleaning up caches
function cu() { eval "vudo php -d memory_limit=-1 /usr/local/bin/composer update '$@'; vudo rm -f tmp/*.php" }
Ansible
Most people seem to opt for plain old shell scripts for setting up their dotfiles, but since I'm using Ansible heavily anyway it makes sense to leverage its features for setting up the various file links and it has brew cask functionality the can automate a bunch of system app set ups.
Because I install with Ansible, this does mean it's a little more tricky to install my Dotfiles on a remote server. But because I aim to never edit files on servers directly anyway and ensure everything is done by automation this situation should never occur.
Other People's dotfiles and resources
Thoughtbot publish their company wide dotfiles publicly and they give a very comprehensive example. - https://github.com/thoughtbot/dotfiles
Ben Orenstein has an extensive set of dotfiles, and with over 800 forks it can lead to a wide range of examples - https://github.com/r00k/dotfiles
Github have a handy guide to setting up dotfiles which is way more comprehensive than I could hope to repeat myself https://dotfiles.github.io/
And of course, my own dotfiles - https://github.com/OddEssay/dotfiles