Hardscrabble šŸ«

By Max Jacobson

See also: the archives and an RSS feed

terminal multiplexing with tmux

January 3, 2015

I made this video a few months back with my friend Alex Au. Itā€™s a crash course in how to use tmux. We made another, shorter, video about why you might want to use tmux as well:

If you find yourself with more than a couple of terminal tabs or windows open all the time, I think you should consider using tmux instead. In the last few months I feel like Iā€™ve hit a sweet groove with my terminal use, where I pretty much never have more than one tab or window open. Instead, I have one tmux session per project, and several virtual tabs (ā€œwindowsā€ in tmux parlance) per project. The thing I learned most recently that makes this really fly is the keyboard shortcut for switching from one tmux session to another without ever leaving tmux. I only ever really leave tmux to navigate to a different directory and start a new tmux session.

Hereā€™s what that looks like:

tmux flow

(I gotta look back into those failing tests in film snobā€¦)

The keyboard shortcut that takes you to the session switcher is ctrl+b s (s for switch). For me, itā€™s super useful. Hopefully youā€™ll find it useful, too.

A cleaner file browsing interface for vim

January 2, 2015

TLDW: add this to your ~/.vimrc:

" hide the giant banner at the top of netrw
let g:netrw_banner=0
" hide gitignored files from netrw
let g:netrw_list_hide=netrw_gitignore#Hide()

And then use netrw instead of NERDTree.

useful tool: storm

January 1, 2015

Iā€™ve been sort of passively looking out for something like this for a while. Hereā€™s the problem: there are a lot of remote servers I may want to SSH into at any given time, and I am not going to remember all of their usernames or IP addresses. Not gonna happen.

Iā€™ve been dealing with this by creating custom aliases. So I put something like this in my ~/.bash_profile:

alias 'eug'='ssh pair@some.ip.address'

Then, whenever I want to connect to Eugeneā€™s server so we can pair program, I just type eug and hit enter, and Iā€™m there. Not bad! It even tab-completes.

Not great either. Itā€™s hard to keep track of them. I can type alias at any time to list all of the defined aliases, and thatā€™s pretty sweet, but it includes several things, not just ssh aliases. Iā€™ve kind of wanted a tool that was more tailored to this job.

Sooo, enter storm. I found it via one thing well, a sweet blog for nerdy stuff like this.

Storm lets you define aliases to remote servers like this:

storm add eug pair@some.ip.address

Once you do that, you just type ssh eug to connect. It has some other helpful subcommands like storm list to tell you all of your aliases even storm web to spin up a nice local web server to provide a web interface for managing your aliasesā€¦

Hey, wait a second. Somehow itā€™s hooking into the normal main ssh command!

After some poking around, I found that itā€™s saving the information in ~/.ssh/config as a plain text configuration file that looks like this:

Host eug
    hostname some.ip.address
    user pair
    port 22

And that I couldā€™ve been using a similarly-structured file all along, and didnā€™t really need storm at all!

Hot dog.

Well, Iā€™m going to use it anyway because it has a sweet interface and Iā€™m kind of just grateful to have learned something from it? Iā€™m guilt-tripping myself into using it.

don't let me modify my laptop any more please

December 16, 2014

Iā€™m writing this on a sticker-covered MacBook Pro my Grandma bought me 3.5 years ago. Itā€™s a pretty powerful Mac. I thought I wanted to be a freelance video editor then. I bought the controversial Final Draft X around that time too.

I havenā€™t edited more than few personal videos, but Iā€™ve used this to write a lot of code and I think Iā€™ve benefited from it having a powerful processor1

I donā€™t really know anything about hardware, but Iā€™ve nonetheless made a few hardware upgrades over the years. Less than a year after getting the computer, I upgraded the RAM from 4 to 8 GB:

RAM upgrade photo from Jan 1, 2012

(Photo via my my instagram from January 1, 2012)

That was pretty easy. You just have to unscrew the bottom off, pull out the old RAM, and add the new RAM (which you bought from Amazon or Newegg or something) and then screw the back on again. It uses normal little phillips head screws.

That worked out for a few years. Then it starts feeling slow again. Iā€™ve come to understand that SSDs are faster than HDDs and decide to remove the optical drive in my laptop, move the HDD into that position, and add a new SSD in the position of the original HDD, and then use the SSD as my primary drive.

I order the parts from the internet and buy a screwdrive set from TekServe and feel very confident. Ultimately I was too confident. This was a super advanced thing to do! I almost ruined my computer.

Upgrading hard drive photo from Jun 6, 2014

(Photo via my my instagram from June 6, 2014)

Basically: stripped screws are the bane of my hardware existence. What do you do when you need to remove a screw so you can remove an optical drive, but the screwdrive spins and the screw stays put? What the hell do you do?

On some level I believe thereā€™s a solution to every problem. Sometimes the solution is more dramatic. When I canā€™t remove a screw from some fixture, I do the next best thing and destroy the fixture. In that picture you can see the optical drive on the right, and a plastic-looking arm holdig it in place. It turns out thereā€™s metal underneath the plastic.

Fast forward to tonight and I have forgotten how bad I am at this stuff and I have a new mac upgrade mission. Iā€™ve been getting little warnings in the status bar that my battery needs attention. Iā€™m worried the Apple Store wonā€™t service it because of the previous modifications I made, but I find a straightforward replacement instruction set online that makes it seem pretty doable, and I order a replacement battery from Amazon that is half the price of the one Apple sells and Iā€™m preparing to open it up again.

Honestly, I should have heeded the first signal, which was that one of the screws holding the bottom plate in place was slightly stripped and didnā€™t want to come out easily. I stayed patient and tried a few different screw drivers and ultimately managed to slip it out. Iā€™m feeling pretty good. The bottom plate comes off.

The battery has a sticker on it warning not to try to replace it yourself. I ignore the sticker. The instructions online tell me there are only three screws to remove, but theyā€™re not a typical kind of screw. Luckily, the battery came with a special screwdriver for this purpose. The first two screws come off easily. The third is hidden under the sticker. I have never even lifted this sticker in my life, I swear, but somehow this last screw is pretty stripped, and thereā€™s nothing for me to do. I either have to give up or resort to drastic action. Thereā€™s no coaxing this one out.

So what do I do? I find the power drill my dad left at my apartment a few months ago and start fucking up this fixture:

(Video via my instagram from December 12, 2014)

I try prodding and poking and sawing at it with a drill, a pocket knife, with various screw drivers, for well over an hour. I learn more about how the power drill works when suddenly its mouth opens and the drillbit falls out and I have to figure out why.

Something like an hour and a half later the fixture is sufficiently destroyed that I can remove the battery. Iā€™m pretty nervous that Iā€™ve more or less destroyed the entire computer. I figure thereā€™s a good enough chance that the drill would poke through the machine and screen, or I sever the strip that connects the SSD drive to the computer or who even knows?

Because I never really removed the old screw, I just forcefully ripped the old battery from it, the new battery doesnā€™t really fit. It has a little ear that wants to be fastened down in that same place, but that place is occupied by an old screw fastening nothing. So I ply away the ear, and position the battery fastened by only two screws.

I hold my breath and turn it on. It actually kind of works. The warning light is gone. The ā€œbattery healthā€ is 101% now, whatever that means. The estimated duration is still terrible, less than an hour on a brand new battery, but I kind of donā€™t care. Actually that number is going up as I type this šŸŽø.

I feel like I need to wear a promise ring not to ever try and open up this computer again, for my sake and its. It just wonā€™t be a happy thing to do. I hope writing this makes me remember that.

Although, now the HDD isnā€™t showing up in the list of drivesā€¦ maybe I should just open it one more time and take a lookā€¦

  1. Or whatever. Honestly, I donā€™t really know anything about hardware.Ā 

more film snob updates

December 14, 2014

Since my last post, in which I announced version v0.4.0 of film snob and kind of agonized over the decision to mark it as a minor release, Iā€™ve gone ahead and made two more minor releases. I have much less anxiety about it now. In fact, I wish I had been doing that earlier.

I decided to do some release notes on the release section of the GitHub repo, instead of here: https://github.com/maxjacobson/film_snob/releases.

While adding release notes for the very oldest versions, from April, I laughed seeing how stuck I was on v0.3.x, not sure when I was allowed to move forward, and just continuing to add these patch level releases for things that were totally new functionality.

Hereā€™s whatā€™s new in v0.5.0: https://github.com/maxjacobson/film_snob/releases/tag/v0.5.0.

And hereā€™s whatā€™s new in v0.6.0: https://github.com/maxjacobson/film_snob/releases/tag/v0.6.0.


The next big thing Iā€™ll need to decide be when to mark the major release of v1.0.0. I had some ideas about breaking changes that I would like to make, so I thought I would save those for the first major release, but then a very generous stranger implemented those ideas and made some pull requests, so I have to decide if Iā€™m ready to make it happen now. Why not, I guess? šŸ˜Ø

film snob 0.4.0

December 6, 2014

Today Iā€™m happy to release film snob v0.4.0.

I first wrote about film snob in April, when I extracted it from my old web app Layabout.

None of the changes add new functionality, so maybe it was wrong to call this a minor release. They also donā€™t fix any bugs. Theyā€™re all to do with making small stylistic changes that make the code easier to read or more consistent. I havenā€™t been releasing those changes because I havenā€™t been sure what the point is ā€“ why release an update that doesnā€™t change anything?

If someone is using film snob, and itā€™s not behaving how they expect, they might check the source code to help them understand and debug their problem. With that scenario in mind, I definitely want to release these changes.

Also, today I merged an awesome pull request which renames a method and emits a deprecation warning for the old method name. Thanks to Wil Chandler for making that change.

Ever since Anton Davydov added support for embedding photos and videos from Instagram, itā€™s been kind of weird that one of the main public interfaces for film snob has been the watchable? method. Instagram photos arenā€™t really watchable, right? Theyā€™re look-at-able, I suppose, but not watchable. Soon weā€™ll be adding support for embedding Rdio playlists & songs too, and itā€™ll be even more semantically unsettling.

The experience now looks something like this:

15:22:33 tralfamadore-5 hardscrabble.net:master
ā‡„ irb
>> require 'film_snob'
=> true
>> FilmSnob.new('http://instagram.com/p/sw4RThIctq/').watchable?
WARNING: #watchable? is deprecated and will be removed in v1.0.0. Please use #embeddable? instead.
=> true
>> FilmSnob.new('http://instagram.com/p/sw4RThIctq/').embeddable?
=> true

Embeddable feels more right to me.

So even though thereā€™s no new functionality, there is more clarity, and maybe clarity counts as a feature? šŸƒ

git repl

November 30, 2014

The other day I mentioned coming upon a neat set of git extensions called ā€˜git extrasā€™ by TJ Holowaychuk. Since then Iā€™ve become slightly obsessed with it. Itā€™s so useful, including as a terrific learning tool. Take ā€˜git replā€™ as an example.

First of all, what is it?

allow me to answer with a GIF:

vim auto indent gif

In short: if youā€™re gonna be doing a bunch of git operations in a row, why keep typing git over and over when you can go into a git repl and just let it assume that everything youā€™re doing is going to be a git command?

It plays well with vim, too ā€“ the commit message editor seamlessly pops into vim and then back into the git repl on quit.

So how does it work? I looked at it and assumed that it must be so much code and way beyond my understanding. But thatā€™s totally wrong! Itā€™s just 43 lines of bash and itā€™s fairly readable.

The really interesting part is read, which has a comment indicating that itā€™s powered by Readline, which is one of those words that Iā€™ve seen fly around while existing in the world of software, but have never heard defined. Well, hereā€™s the wikipedia page for it: GNU Readline. It was originally written by Brian Fox, who also created bash. Rubyā€™s various REPLs (eg rails console, irb, pry) are probably using it under the hood via Rubyā€™s standard Readline library, which makes writing a REPL super simple, while maintaining the behaviors you may be used to. For example, I compulsively press control+l to clear the screen; this works in a readline REPL but not in something like this:

loop do
  print "> "
  input = gets.chomp
  puts input
end

Filename tab completion works as well! Whoa!

Hereā€™s my first readline program, inspired by the git repl code:

function extensions {
  read -e -r -p "find files with extension: " extension
  find . -name "*.$extension"
}

Try pasting that into your terminal then entering extensions to run it and to explore your projects. It should prompt you for a file extension (try entering rb in a Ruby project, for example) and then spit out the list of files with that extension in the current directory (and its subdirectories).

Not a particularly great program! Iā€™m mostly just happy to see how simple and demonstrative the git extras code was.

idempotent

November 29, 2014

HTTP GET requests are supposed to be idempotent, but they often have the side effect of appending some request details to a log file, which can eventually grow so large that it fills the disk and takes down the server.

git fresh branch

November 28, 2014

Tonight while clicking around the web I discovered tj/git-extras, a set of useful git tools maintained by TJ Holowaychuk1. Once installed, your git command is overloaded with a bunch of new, useful commands.

Itā€™s easy to install, but it does add quite a lot of stuff, and I was worried for a moment that it would clobber some existing aliases of my own. One, git squash, comes dangerously close to my beloved git squasher, but doesnā€™t actually conflict.

If you are worried about it, you can safely pick and choose which extras you want by saving individual scripts and just making sure theyā€™re all on your PATH and executable.

The readme explains their purposes nicely, but I want to emphasize one in particular: git fresh-branch <branch name> which does stuff I didnā€™t know was possible.

Letā€™s say youā€™re maintaining an open source library that has existed long enough to accumulate many commits and files. Letā€™s say you want to create a github page for that library to explain what itā€™s all about and how to use it. The way github pages works, you should create a new branch in the same repo with the branch name gh-pages, and on that branch you keep a set of assets that will become a static website. But when you create a new branch, it will have all of the code from your open source library, and an entire history of commmits. I can imagine doing something like this:

# create a new branch
git checkout -b gh-pages
# delete all of the existing files
git ls-files | xargs rm
# stage those deletes
git add -A
# commit the change
git commit -m 'BURN IT DOWN'

# create the first version of the site
echo 'hello! use my gem!' > index.html
git add index.html
git commit -m 'gh-pages init'
git push origin gh-pages

And then Iā€™d wait for GitHub to do its magic and expect to see my great page online in a few minutes.

Itā€™s kind of awkward having a ā€˜BURN IT DOWNā€™ commit, but I didnā€™t know there was an alternative. With git extras, that could look more like this:

# create a new branch WITH NO HISTORY AT ALL
# NOT ONE COMMIT
git fresh-branch gh-pages

# create the first version of the site
echo 'hello! use my gem!' > index.html
git add index.html
git commit -m 'gh-pages init'
git push origin gh-pages

How the heck does it work? We can look at the fresh-branch script online, but Iā€™ll include the latest version here for reference:

#!/bin/sh

branch=$1

test -z $branch && echo "branch required." 1>&2 && exit 1

git symbolic-ref HEAD refs/heads/$branch
rm .git/index
git clean -fdx

I guess a lot of the work is being done by symbolic-ref.

While researching this post, I noticed that git-extras also offers a gh-pages script that is even more tailored to the use case from my example. Of course! šŸƒ


edit: I probably should have slept on this post and actually explored more how itā€™s working under the hood. But I did not.

  1. Formerly ā€˜visionmediaā€™ on GitHubĀ 

ruby-build, chruby, and yosemite

October 19, 2014

A few months ago I stopped using rvm to install and manage my ruby installations on my computers. I donā€™t have a great reason, other than reading that Steve Klabnik uses something else and I felt like trying it one day.

What I use now:

ruby-build

This is how I install rubies:

  • brew install ruby-build ā€“ get ruby-build
  • mkdir ~/.rubies ā€“ this is where rubies and gems will go
  • ruby-build --definitions ā€“ shows you a list of all the available rubies. When new ones come out, you should be able to just brew update and brew upgrade ruby-build to get access to those new definitions
  • ruby-build 2.1.3 ~/.rubies/2.1.3 ā€“ first argument is the name of the definition from the previous step, and the second argument is where to install all the code
  • watch it install

chruby

This is how I switch between versions of ruby.

setup

The instructions in the readme are good. The gist is that you install a script and then source it from your ~/.bashrc so it will be included in your shell sessions. This exposes a chruby bash function, which you can thereafter reference from the shell to switch between rubies (eg chruby 2.1.2) or even later in your ~/.bashrc, to choose a ruby immediately upon starting a shell session. This will look in the ~/.rubies folder by default, which is why I install my rubies there.

Yosemiteā€¦

So this all stopped working on my laptop yesterday when I upgraded to Mac OS X 10.10 (Yosemite). I couldnā€™t run bundle install without getting a nasty error, and I became convinced that I needed to rebuild all of my rubies. So I thought ā€œOK, I know how to do thatā€ and ran rm -rf ~/.rubies and set about following those steps under ā€œruby-buildā€ above.

It didnā€™t work, so I went to sleep.

Long story short, this fix worked: https://github.com/sstephenson/rbenv/issues/610#issuecomment-58804829

Where before you would have run ruby-build 2.1.3 ~/.rubies/2.1.3, now (until ruby-build makes a fix) you can run CC=clang ruby-build 2.1.3 ~/.rubies/2.1.3.

I donā€™t know if rvm had this problem. I wouldnā€™t be surprised if they did, and it was fixed quickly. But like. Itā€™s kind of cool to use smaller tools sometimes.