/tinyletter

The Programs of the Week of the Big Game

This Week’s Program: Jan 29 - Feb 2

It’s been another couple of weeks since my last Tinyletter. I decided to shelve Overscan’s ongoing gui work/debacle/obsession and get back to basics. I have enough pieces in place to get something to work, and an open thread on the Racket dev mailing list to try to better understand some odd behavior on the things that aren’t working.

This week I mostly focused on doing the best thing to recharge energy on a project: write documentation. Overscan’s gstreamer module has evolved and quite a bit has been added since I started down this GUI path, so I took some time to write out docs for that new functionality. Writing documentation is like pruning a bonsai: tranquil, meditative work that doesn’t madden you with subtle platform implementation differences.

The other thing I’ve spent time on over the past couple of weeks is mechwarper, my repository hosting Ansible playbooks for the care and feeding of my computer machines.

Recently, the release of Ruby 2.5.0 meant it was time to do a bit of house cleaning on my MacBook. I also decided to upgrade to High Sierra. It made me realize I never want to think about bespoke installations of software again. I want every Mac I interact with to basically run the same suite. I turned to Ansible to figure out how to manage the bootstrapping of a new Mac development machine.

local.yml

The main playbook is located at local/local.yml and is split into several roles. The basics role installs Homebrew, Homebrew-Cask, the Mac App Store CLI, Git, GNU Stow, and my Dotfiles. From there, there are roles to install Homebrew formula I use frequently, some Mac apps installed through Cask (including Racket), and apps from the Mac App Store. I also have roles for setting up a Ruby installation with rbenv, getting my Emacs set up just the way I like it, and for installing the GStreamer components that I use frequently with Overscan.

Of all the roles that I use here, the one I’m most proud of is the aesthetics role.

aesthetics

This is a role to make my Mac look and feel like I want it to.

Like, for instance, pulling out the SF Mono font out of embedded applications into the system font library:

# https://simonfredsted.com/1438
- name: SF Mono font availability
  copy:
    src: ""
    dest: ~/Library/Fonts/
  with_fileglob:
    - "/Applications/Utilities/Terminal.app/Contents/Resources/Fonts/SFMono*.otf"
  tags:
    - font

But the pièce de résistance of this role is the little hack to map the Caps Lock key to Control, which is the most important thing a developer can do for their productivity.

The first thing is to fetch information about the hardware from the system:

- name: Apple Internal Keyboard vendor/product id
  shell: |
    set -e
    tmpfile=$(mktemp)
    ioreg -c AppleHSSPIDevice -r -d 1 -a > $tmpfile
    vendor_id=$(/usr/libexec/PlistBuddy -c 'Print :0:idVendor' $tmpfile)
    product_id=$(/usr/libexec/PlistBuddy -c 'Print :0:idProduct' $tmpfile)
    echo $vendor_id-$product_id-0
  register: keyboard_id
  changed_when: false
  check_mode: no
  ignore_errors: true
  tags:
    - keyboard

This will pull out a vendor and product id for an internal MacBook keyboard. It does not work with USB or Bluetooth keyboards. Look at this shell script! mktemp, ioreg, PlistBuddy — the gang’s all here! Next, I set some preferences using defaults:

- name: Caps-Lock -> Ctrl mapping
  shell: |
    set -e
    key='com.apple.keyboard.modifiermapping.'
    found=$(defaults -currentHost find $key)
    if [[ $found =~ ^Found ]]; then
      echo $found
      exit 0
    else
      defaults -currentHost write -globalDomain $key -array \
      '<dict><key>HIDKeyboardModifierMappingDst</key><integer>30064771300</integer><key>HIDKeyboardModifierMappingSrc</key><integer>30064771129</integer></dict>'
    fi
  register: result
  changed_when: result.stdout == ''
  when: keyboard_id.rc == 0
  tags:
    - keyboard

This is Incantation TN2450 to tell Apple that one key on your keyboard is actually another key. Preferences are heavily cached, so give it a minute.

Feel free to check out Mechwarper and give it a run, but only if you want your Mac to behave just like my Mac. There’s a bunch more to do to get a machine fully operational, and I expect I’ll be adding those steps over time. Ansible makes this so easy!

For further reference check out some of these projects that served as inspiration:

Have a great weekend!

– Mark