Hardscrabble šŸ«

By Max Jacobson

See also: the archives and an RSS feed

the cop and the hound

September 28, 2014

As a rails developer I keep hearing about Thoughtbotā€™s cool projects. A fairly recent one is Hound, a tool that comments on your GitHub pull requests and points out code style violations. I think consistent style is a nice ideal to strive for, so I want something like this.

Setting up Hound is easy, but it only reviews the code that is added in a pull request, not the existing code base. Which, in theory, is fine. Except, if youā€™re the kind of obsessive compulsive who wants a style guide, itā€™s probably not.

So I managed to make Hound review the full code base but it took some tricky git branching and pull requesting. So I made a screeny1 to share:

I didnā€™t want this video to be too long, so I stopped when I managed to get the full codebase analyzed. But hereā€™s my plan to continue:

  1. Iā€™ll need to learn how to configure Hound to more accurately reflect my tastes. Under the hood it uses rubocop, pre-configured with Thoughtbotā€™s style rules. Iā€™ll add my own configuration and push again, which will hopefully refresh the comments.
  2. Then Iā€™ll fix all the code style violations and keep pushing them up until all of the comments go away. Then Iā€™ll merge the second pull request. At that point my first pull request will (hopefully) have a diff that shows exactly what I want: new configuration and style fixes.
  3. Iā€™ll squash that branch to have just one commit and merge it.
  4. Then Iā€™ll merge that pull request into master and be nicely set up for a future of consistent style.

1. configuring rubocop

These are the default ā€œcopsā€ for rubocop. If I were starting fresh with rubocop (and not using Hound), I would start with this configuration file and start disabling specific cops. In fact, this is exactly what Hound does. Their tweaks are available because Hound is open source.

Hereā€™s what I came up with: https://github.com/maxjacobson/film_snob/blob/hound-it-up/.rubocop.yml (if that link is dead, itā€™s probably because I merged the PR and deleted the branch, in which case the file can be access here).

Maybe Iā€™ll change it over time but it seems good right now.

2. fixing all the violations

Done: https://github.com/maxjacobson/film_snob/pull/46

Being consistent feels good šŸ™‚.

Itā€™s actually not that hard to use rubocop directly without Hound. I also added rubocop to my Travis CI configuration, so even if I didnā€™t have Hound, pull requests would consider style guide violations, because the build would fail. Thereā€™s no commenting, which decreases the visibility. But itā€™s OK because Hound double-comments if you push the same problem twice, so maybe the comments arenā€™t that great? Itā€™s also much more strict. If you have an 81 character line, itā€™s a complete no go, the build fails, you canā€™t merge that.

Iā€™ll try that.

  1. I call them screenies because the app I use to make screenies is called ScreenyĀ 

sleep timers

September 7, 2014

Falling asleep is one of the weirdest things that everyone does every day. Many people struggle to do it all. They experiment and develop workflows that help cope with this necessary evil. Hereā€™s mine.

If Iā€™m very exhausted I simply lie down, close my eyes, and shortly thereafter I fall asleep. This isnā€™t very often due to my sedentary lifestyle, so Iā€™m often lying in bed wondering what Iā€™m supposed to be doing with my arms and/or mind. The recourse I usually take to is to play a podcast. Many would argue that listening to a podcast is counter-productive to the goal of falling asleep. I donā€™t completely disagree, but I like to do something to fill that time, even if doing nothing would mean less time falling asleep, podcasts make the longer time pass quicker, so it evens out.

One problem is that podcast clients often autoplay, such that when one episode ends, the next begins. If you combine this feature with the auto-download feature, this creates the risk that I will go into an infinite loop of listening to podcasts literally forever.

If I could somehow fall asleep while people were talking, I would wake up to hear them still talking, potentially about anything at all, which I imagine to be extremely disorienting.

To mitigate these risks, Iā€™ll apply a sleep timer, which means that Iā€™ll tell the podcast to stop playing after a specified number of minutes has passed. Here are the steps I take:

  1. I press play on a podcast
  2. I apply a sleep timer of 5-15 minutes depending on how sleepy I feel
  3. I listen to the podcast while relaxing my body and mind
  4. I sense the impending timer running out and a curious tension fills me
  5. The podcast fades out and stops and I immediately fall asleep

If I donā€™t fall asleep, I start over, maybe with a shorter timer. I never fall asleep before the sleep timer runs out. If I do that, Iā€™ll miss part of the podcast, which I would hate.

Itā€™s essential to my bedtime workflow that I have fine control over how many minutes the sleep timer will run, because I believe that I can predict how long it will take me to fall asleep based on my current level of sleepiness. Itā€™s also important that the audio fades away because that signals my internal systems to prepare to do that last, most important step (falling asleep).

This is my main complaint about the otherwise terrific new podcast app Overcast which does offer a sleep timer, but one that can only be set in crude chunks of 5 minute increments, and which stops with no fade out at all. I wonā€™t be switching back to Downcast, which set the standard for sleep timers for me, but I suspect my sleep will suffer.

How do you fall asleep?

vim will fix indentation mistakes

September 7, 2014

Today I learned a neat vim trick (via the Aaron Paterson Play by Play interview):

vim auto indent gif

You can highlight some lines with visual mode and then press = and it will fix all of the indentation mistakes therein. If youā€™re in normal mode, you can press == to fix just the line youā€™re currently on.

Paterson cites this trick as an argument in favor of not indenting private methods an extra level, because vim doesnā€™t do that. For example:

# do this:
class Dog
  def bark
    barks.sample
  end

  private

  def barks
    ["woof", "yap", "ruff"]
  end
end

# NOT this:

class Cat
  def meow
    meows.sample
  end

  private

    def meows
      ["meow", "purr", "idk what else, cats are weird"]
    end
end

I generally do that extra indent but I might stop now šŸƒ.

jekyll 2

September 6, 2014

I just finished updating my blog to Jekyll 2.0. It looks the same, but the code is nicer.1

The marquee feature is that Jekyll now knows how to compile Sass and CoffeeScript. I was already using those languages, but relying on a complex Guardfile to accomplish it. Iā€™m pleased to delete that.

Like all files Jekyll processes, Sass and CoffeeScript files must have YAML at the top of them, though no YAML data is actually required to be there, just the hyphens where the YAML would go. Thatā€™s an awkward requirement which I hope goes away.

The other thing I got to delete was some boilerplate configuration in the head of every page and post, in which I would tell Jekyll that posts should use the post layout and pages should use the page layout, so it knows which layout to use. Now I just tell it which layout to use for posts and which to use for pages once in the global configuration file, which is much nicer.

The last new thing I want to explore is using GitHub-style code blocks. Iā€™d prefer to use the triple backtick over the liquid tag. This is supposed to be possible but I couldnā€™t get it to work perfectly ā€“ code blocks were generated, but lost the syntax highlighting so I decided to leave it for now.

The creator of Jekyll, GitHub co-founder Tom Preston-Werner, recently left GitHub after being investigated about very unprofessional behavior. Four months earlier, the Jekyll project was distanced from him a bit when the source code was moved from his personal account to an organization account dedicated to Jekyll and related projects. This is normal and reflects that the project outgrew him, and that heā€™s not the main maintainer anymore. When Jekyll 2.0.0 was released, Preston-Wernerā€™s name was buried in a wall of thank-yous.

I feel slightly weird using Jekyll because of who created it. Iā€™m glad it doesnā€™t follow the naming pattern of toml and tomdoc at least.

  1. The diff says I deleted 3623 lines, but itā€™s not as amazing as that sounds because 3263 of them are from a CSS library that I realized I donā€™t use anymore.Ā 

when your disk fills up, who are you?

September 6, 2014

I got into technology in large part because I was drawn to the Mac community. I started reading blogs about apps and productivity. That occupied a lot of my mind during college in particular, when I was struggling with procrastination and wanted to find some silver bullet app to save me.

During that time I heard of a neat app called DaisyDisk which analyzes your Macā€™s disk and breaks down exactly where your data is on your computer. It can help you remember about huge files you totally can delete or games you donā€™t play anymore and can easily re-download if you want to again. I had a 2006 MacBook with an 80 GB hard drive (the cool black one) that I needed to constantly bail files out of. DaisyDiskā€™s colorful, powerful interface was a life saver and, for me, a benchmark for how cool an app could be.

It was updated fairly recently and seems to still be great. I just re-downloaded and ran it on my 128 GB MacBook Air:

my daisydisk results

Fast-forward to a few months ago, and Iā€™m at work as a web developer and my coworker comments that the disk on one of our production Linux servers is nearly full, and we need to find something to delete. I knew DaisyDisk wouldnā€™t work in the command line but didnā€™t know what to suggest. He remembered something called ncdu and ran it and I had immediate, rippling acid flashbacks to DaisyDisk! ncdu is a tool that runs totally in the command line with a nice interface and accomplishes the same goals and supports the same workflow:

  1. start the app
  2. wait while it analyzes your disk
  3. see your top-level directories sorted by how much disk space they use
  4. let you drill down and see the same for all sub-directories
  5. let you delete culpable files right from its interface

Hereā€™s what it looks like:

my ncdu results

Kind of the same!!

It would have been hopelessly intimidating and weird to me a few years ago but for the me that I am today (someone who sometimes uses Linux) I canā€™t help but find it much cooler.

ncdu can be installed on a Mac via homebrew with brew install ncdu or on Linux with sudo apt-get install ncdu.

my newest git alias is git

September 6, 2014

Adding aliases makes git a lot more pleasant to use. For example, I am too busy to write git status to find out the current status of my project so I did this:

git config --global alias.st status

and now I just write git st.1

I have a few other git aliases that I find helpful. Theyā€™re on my dotfiles repo here: https://github.com/maxjacobson/dotfiles/blob/master/.gitconfig

I want to share my newest one because itā€™s kind of weird and fun. It solves a problem that others might have, but I apparently totally do: I often write git , donā€™t hit enter, and then go do something else. Then I come back and I write git st and hit enter, and I see this output:

ā‡„ git git st
git: 'git' is not a git command. See 'git --help'.

Did you mean one of these?
        hist
        init

I see this probably every day.2

I wanted a new alias that just kind of ignores the extraneous git. Most git aliases donā€™t behave that way. At first I tried aliasing git to nothing at all, but it didnā€™t let me. I landed on this:

git config --global alias.git "! git"

The exclamation mark character means this alias doesnā€™t refer to another git command; instead, I want to run an arbitrary bash commandā€¦ which, in this case, happens to be git itself. Luckily, the git aliasing system doesnā€™t simply run the quoted bash command, but it passes the rest of the arguments along, so git git st now behaves the same as git st, not simply git.

Iā€™m pretty happy with this. I have a nagging worry that itā€™s too weird to not have some unwanted side effects, and if I discover any Iā€™ll update this post.

  1. btw: when you do that, it gets saved in a dotfile in your home directory called ~/.gitconfig. If you open that file youā€™ll see your name and email address too if you set that up (if not, check out GitHubā€™s page on that)Ā 

  2. you might see different output, but hist is another of my aliases and itā€™s close enough to git that git thinks I meant it.Ā 

onscreen texts and I'm so Happy I'm Ecstatic

August 20, 2014

People have been linking to this terrific video by Tony Zhou about how film and television depicts onscreen text messaging:

(I saw it on Kottke which has some additional context)

The video brings up some memories for me, from when I wanted to make movies, and used a similar technique1. My short film ā€œIā€™m so happy Iā€™m Ecstaticā€ was uploaded to Vimeo in May 2010, just two months before Sherlock debuted on BBC.

Zhou isnā€™t the first to notice this trend. In April 2013, Rachel Dodes Whortman wrote an article about it for the Wall Street Journal (ā€œFrom Talkies to Textiesā€). When I saw the article I felt the need to reply:

I think Iā€™m less petulant now than the nerd who wrote that tweet2. I definitely donā€™t think I was the first to do that (Zhouā€™s video provides a few earlier examples, most embarrassingly 2008ā€™s Sex Drive which I did totally see) and I definitely didnā€™t do it as elegantly as Sherlock.

But some small petty part of me wants to be in videos like that or to maybe keep making video things.

  1. I think I wrote it into the screenplay for the short, but I want to give credit to my friend Sarah Mayo who co-edited it with me and made it work ā€“ the few times Iā€™ve seen people watch it, thatā€™s their favorite part by farĀ 

  2. (but then, I am writing this blog post)Ā 

composing a Parslet parser from modules and making code climate happy

July 27, 2014

Iā€™m making very slow and intermittent progress on smashcut, my Fountain screenplay parser written in Ruby. At this rate Iā€™ll have a usable version in a few years or so šŸ™‚. Iā€™m going to talk about it a little bit here and then talk about how a small refactor boosted my Code Climate GPA for the project from 1.9 to 3.56.

(For those who donā€™t know: Code Climate is a very neat website which analyzes your code and points out improvement areas. They provide free analysis to open source projects like smashcut and paid analysis of private projects. They also maintain a cool blog about code design and techniques at http://blog.codeclimate.com/.)

Today on a train ride I reorganized the smashcut codebase a bit. The heart of the project is a file called fountain_parser.rb which describes the grammar of a Fountain screenplay as a list of rules. The syntax for defining a rule uses a DSL provided by Parslet, a great Ruby gem for exactly this purpose. Hereā€™s the code example from their get started page:

require 'parslet'

class Mini < Parslet::Parser
  rule(:integer) { match('[0-9]').repeat(1) }
  root(:integer)
end

Mini.new.parse("132432")  # => "132432"@0

This is a very simple grammar with only one rule in addition to the required root (which names the rule that is expected to come first). If you were to define a grammar for something more complex, like a screenplay or even a programming language, you could expect there to be many, many more rules for defining specific, small things like operator characters and return charactersand then also abstract things like a characterā€™s monologue or a programā€™s function.

At some point, your parser class will get quite long. I think this is kind of to be expected and not necessarily a bad thing. But it sure hurts your Code Climate GPA, which drops at the sight of long and complex classes. It also balks at code outside of methods, which is I think unfairly punishing to projects using DSL-style libraries.

It took some figuring out, but it is possible to compose your parser from modules. That example above could be rewritten like this:

require 'parslet'

module NumberRules
  include Parslet
  rule(:integer) { match('[0-9]').repeat(1) }
end

class Mini < Parslet::Parser
  include NumberRules
  root(:integer)
end

Mini.new.parse("132432")  # => "132432"@0

This is pretty nice when you have more than a few rules, and Code Climate rewarded me with a coveted A grade: https://codeclimate.com/github/maxjacobson/smashcut/compare/0cd1d78b...c2668c0eā€¦ well, for some of the classes anyway.

EDIT 2015-01-08: Hrmph, that link is dead now. Suffice it to say that the changes from this pull request improved the GPA from 1.9 to 3.56.

An Alfred Workflow for adding the frontmost Firefox tab to OmniFocus with AppleScript

July 13, 2014

Saw a link about using tools to take long-lasting tabs out of your browser and put them somewhere useful like Evernote or OmniFocus rather than let them tax your mind and memory. I wanted in.

Sadly, there was only support for Chrome and Safari, not Firefox, which I continue to stubbornly prefer. I assumed at first this was simply a reflection of Firefox not being particularly popular among Mac users1 and resolved to patch the gap.

In order to interact with your running Mac applications, people often use AppleScript, a kind of strange programming language that comes with Macs and lets you script or automate user tasks. So whenever I want to close a tab without forgetting that it might matter somehow, I have to do these steps manually:

  • open the omnifocus quick entry panel with the global hotkey
  • write some kind of task title
  • go back to the browser
  • copy the URL
  • go back to the quick entry panel
  • type āŒ˜+', the keyboard shortcut to open the notes field
  • paste the URL
  • type āŒ˜+' again to return to the title field
  • press enter twice

Imagine having two dozen tabs open and kind of wanting to do that for each of them? Prime candidate for automation!

Given that this is my first AppleScript, Iā€™m bizarrely confident that I can figure this out. I assume I can just ask Firefox for the list of currently open URLs, write some kind of loop, and then send OmniFocus a bunch of messages (in the background maybe) and have it all just work easily. Pretty quickly I learn that, unlike Safari and Chrome, Firefox exposes nothing to AppleScript. Itā€™s scriptable insoafar as every app is scriptable ā€“ you can perform user actions like clicking and typing, but it doesnā€™t expose anything nicely, and Mozillaā€™s bugtracker has multiple tickets dating back several years of people saying they wish Firefox supported AppleScript without much movement as far as I can tell.

No worry! Iā€™ll find some clever solution. I open AppleScript Editor and start trying to figure out how to even do any of this.

tell application "FirefoxNightly" # I'm using the nightly build, and I have to specifically say so
  activate # this opens or switches to the application
end tell

a digression about running AppleScripts

You can write small things like this in the AppleScript Editor app and run them from there. This is what I was doing while writing the thing and tinkering. But itā€™s not a great interface, really, as far as text editors go. Another option is to use the texteditor of your choice and run it from the terminal by writing osascript your_file.scpt. Thereā€™s something kind of trippy about running something like this, and seeing your operating system react:

[hardscrabble] [hardscrabble.net] [my-first-applescript branch]
ā‡„ osascript -e 'display alert "hello world"'
button returned:OK

Later on you can use tools like Alfred to run your scripts from anywhere at any time.

back to struggling with this code

So if Firefox doesnā€™t expose anything to us, how can we get the list of tabs open? I went down a few dead ends. I spent several minutes trying to make a bookmarks group of the currently opened tabs, then export the bookmarks, then parse the exported file before I realized I was definitely going the wrong way and I definitely didnā€™t know how to do parse JSON in AppleScript.

After a little more googling I came upon a comment on Bugzilla which provides a way to get the current pageā€™s URL at least. Hereā€™s how:


tell application "FirefoxNightly"
  activate
  delay 2 # sleeps 2 seconds because idk... it doesn't work otherwise
  tell application "System Events"
    tell process "firefox"
      keystroke "l" using {command down} # āŒ˜+l is the keyboard shortcut to focus on the address bar
      keystroke "c" using {command down} # āŒ˜+c copies the current URL to the clipboard
      set tabUrl to get the clipboard    # stores the clipboard in a variable
    end tell
  end tell
end tell

display alert tabUrl

Yikesā€¦ AppleScript is interesting because itā€™s an awkward, not fun language but also super powerful if youā€™re a kind of nerdy Mac power user, or maybe even developer who wants to harness the power of GUI applications in their project. Fortunately the next major version of OS X, Yosemite, has a JavaScript API for doing all the same stuff. This might be my last AppleScript too, because of that.

Now that I have the URL I want to do something better than display an alert. Some googling points me to a 2012 MacSparky blog post about AppleScripting with OmniFocus. The language is still awkward (set theProject to first flattened project where its name = "Finance"), but this is significantly better than Firefox because it exposes an API at all. Since then, thereā€™s been a major 2.0 update to OmniFocus, but I guess they made an effort to maintain consistency because these examples still work. I donā€™t really blame Mozilla because theyā€™re maintaining applications across every operating sytem that will support them and are very consistent. In fact I wish there existed OmniFocus for Linux but, like, lol. Everyone compromises!

OK so I can get the current URL and add a task to OmniFocus. A little more digging and this is what I came up with:

tell application "FirefoxNightly"
  activate
  set taskTitle to name of front window

  tell application "System Events"
    tell process "firefox"
      keystroke "l" using {command down}
      keystroke "c" using {command down}
      set taskNote to get the clipboard
    end tell
  end tell
end tell

tell application "OmniFocus"
  tell quick entry
    open
    make new inbox task with properties {name:taskTitle, note:taskNote}
  end tell
end tell

Itā€™s kind of a dinky version of what I originally wanted to make. Itā€™s only for the current tab, and when itā€™s done the quick entry panel is still open (by design: so I can still edit the details).

I packaged it as an Alfred Workflow here so I can invoke it from wherever by typing āŒ˜+space and then just writing tab.

I wonder if this is useful to other people!

  1. Recently on the Accidental Tech Podcast I was surprised to hear the hosts be super harsh to Firefox. This tweet makes the argument that Firefox isnā€™t relevant anymore and I donā€™t really know if thatā€™s true, but I think it should be.Ā 

My New Computer

June 29, 2014

Hereā€™s a screenshot of my desktop as of right now:

My desktop

Itā€™s an Intel NUC. Itā€™s tiny. Itā€™s mounted to the back of my 23ā€ Monitor I bought like 4 years ago. Itā€™s really clever ā€“ those 4 standard screws that are meant for mounting the monitor to an arm or the wall can instead have the computer mounted to it. Itā€™s replacing an old 40 pound (maybe, Iā€™m totally guessing) Dell tower hand me down from my dadā€™s office.

Itā€™s running Ubuntu 14.04 LTS1 with the Gnome Metacity Flashback desktop. I really like this desktop because it leaves a ton of space for stuff on the screen, but has access to all the stuff you need. I havenā€™t used Linux very long, just as a secondary computer for two years or so, but nonetheless Iā€™m nostalgic for this desktop beacuse itā€™s the one I first used on a very underpowered netbook. I enjoy its multiple desktop indicators in the bottom right corner, which show the position of the windows in silhouette. I like pressing ctrl+alt+arrow to go between them, and ctrl+alt+shift+arrow to drag the active window with me.

I figured out today how to remove icons from the top left launcher panel. I could not figure it out at all, and was grateful to see others struggling with the same. I took the opportunity to add some nice web bookmarks.

I took a few minutes today to read about Mint Linux and considered switching, but I donā€™t really like how it looks. Iā€™m worried that this particular look that I use isnā€™t very popular and wonā€™t be maintained for long, so I want to share that I like it this way and I recommend it, especially for programmers and writers interested in a simple and clean user experience thatā€™s not plugged in to all of their existing notification-generating lives.

My new computer isnā€™t actually very new. I got it nearly two months ago. I havenā€™t given much thought to the idea of using Linux as a primary computer. I think that would be pretty hard given how used I am to OS X, but itā€™s a terrific secondary computer.

  1. Unlike most version numbers, this means it came out in April 2014. LTS stands for ā€œLong Term Supportā€Ā