BTT: Three Finger Swipes

This is a quickie. One of my most-used BetterTouchTool configurations is setting up three finger swipes. Three of my most used global shortcuts are:

  • Three finger swipe left — ⇧⌘[ (Show Previous Tab)
  • Three finger swipe right — ⇧⌘] (Show Next Tab)
  • Three finger swipe down — ⌘W (Close Current Tab (or Window))

Being able to use three fingers to swipe between an app’s tabs, and then quickly close a tab with a swipe down, feels like an entirely new way to casually do light work.

`git push` Without Complaints

On my work computer, I can make a new git branch and push it up to GitHub with a simple git push. I don’t need to manually set or create the upstream branch. Not so on my home computer. At least not when working on my dotfiles repo. When I try to push up a new branch, I get this error:

fatal: The current branch new-branch has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin new-branch

It didn’t take too long to figure out the problem. Somewhere along the line I’d renamed the default remote from origin to github. I saw this by looking at the repo’s .git/.gitconfig file, which had the following lines:

[remote "github"]
    url = git@github.com:erikphansen/bin.git
    fetch = +refs/heads/*:refs/remotes/github/*
[branch "master"]
    remote = github
    merge = refs/heads/master

I changed github to origin on the first and fifth lines, so it read:

[remote "origin"]
    url = git@github.com:erikphansen/bin.git
    fetch = +refs/heads/*:refs/remotes/github/*
[branch "master"]
    remote = origin
    merge = refs/heads/master

After that, no more complaints when trying to push up a branch that didn’t yet exist on GitHub.

I’m pretty sure that tomorrow’s post will be a follow up explaining how I could keep my remote branch named github and still allow for auto-creation of remote branches. Stay tuned for that excitement.

P.S. You might also need to check the value of git’s push.default setting with $ git config --global push.default. It it’s not current, then run git config --global push.default current. In my case, this was already set, but I don’t believe it’s like this out of the box.

Faster GitHub PRs, Take 2

I just updated the function I wrote about yesterday, making two big changes:

  • Vim is no longer opened just so that I can reuse the last commit message for the PR Message
  • The browser no longer opens the PR page; instead the URL for the PR is copied to the clipboard so that I can paste it into Slack.

The new usage is simply $ pr if I want to PR into develop or $ pr target-branch if I want to PR into target-branch.

Here is the new version, which can also be found on GitHub:

function pr -d 'Quickly make a PR of the current branch into `develop` or the branch of your choosing'
  # Reuse the last commit message as the PR message
  git log -1 --pretty=%B > msg.txt
  set targetbranch 'develop'
  if test -n "$argv"
    set targetbranch $argv[1]
  end
  git push; and git pull-request -b $targetbranch -F msg.txt | pbcopy
  rm msg.txt
  echo 'You can find your PR at' (pbpaste)
  echo ' (That URL has been copied to your clipboard, as well)'
end

I’m outputting the last commit message to a temp file, msg.txt, because this seems like a good way to support multi-line messages. The message is then used with the pull-request -F flag. In my first attempt I stored the value of git log -1 --pretty=%B in a var to then pass to pull-request -m but that choked on commits that were more than a single line.

Faster GitHub PRs

NOTE: The day after writing this, I made it better

After some setup, I can create a GitHub PR with two commands in the terminal: Entering pr at the command line followed by :x in Vim. After that I’m staring at the webpage for the PR in my browser.

How? With a command line function that leverages Hub for GitHub.

Want to do the same?

First, install Hub for GitHub. With Homebrew it’s as simple as $ brew install hub. You’ll also want to follow the simple instructions to alias git to hub. In effect this just gives git some extra powers.

Now you can type $ git pull-request -b develop -o which will:

  1. Prompt you to enter a message for the PR in whatever editor you’ve told Git to use
  2. Open the webpage for the newly created PR in your browser

But who wants to type that much? The logical next step is to make a shell function so you can just type pr. In Fish, it looks like this:

function pr
  set targetbranch 'develop'
  if test -n "$argv"
    set targetbranch $argv[1]
  end
  git push; and git pull-request -b $targetbranch -o
end

Now creating PRs into develop is as simple as $ pr and making PRs into my-big-feature can be done with $ pr my-big-feature. And with Fish’s autosuggestions you likely won’t even have to type more than a letter or two of your target branch’s name.

Wishlist

One way this could be better is if the URL for the PR page on GitHub could be copied to my clipboard so I could easily paste it into my team’s Slack channel. In fact, the only reason I want to open the PR page at all is so that I can grab its URL. It doesn’t seem like the pull-request command has a way to just give me the URL. Let me know if I missed that. But since this process ends with me looking at the page I want to share it just takes a quick ⌘L ⌘C to get the URL on my clipboard. Not too shabby.

Run ffmpeg On a Folder of Videos

The Problem:

I had roughly fifty video files across four different folders that I wanted to extract the audio from. You can use ffmpeg to pull the audio out of a single video file, but I didn’t want to type in a slightly different ffmpeg command fifty times.

The Solution:

Write a Node.js script that loops over all the files in a directory and runs the correct ffmpeg command to attempt to extract the audio from each file. And, of course, spend more time writing the script than it would have taken to just manually run the command dozens of times.

You can grab the script from GitHub. It was a fun learning experience. When you run the ffmpeg command, you need to make sure that the file extension for the audio file matches the format that’s actually in the movie file. This is kind of a drag. It would be nice if ffmpeg was smart enough to extract whatever audio was in the video, in whatever format it was in. It’s entirely possible it is that smart, I’m just not smart enough to know how to make it do what I want. At any rate, my script allows you to pass in an argument to set what format the audio is in.

Oh, all you care about is the ffmpeg command that’ll pull the existing audio out of a video file? No problem: ffmpeg -i input-video.avi -vn -acodec copy output-audio.mp3

Rails 5 Installation Woes

I ran into issues installing Rails 5 today. It was blowing up trying to install the Nokogiri gem. The full error message is at the bottom of this post, if you’re curious (and for the benefit of SEO).

The fix was to install the Xcode Command Line tools. This, despite the fact that I have the latest version of Xcode installed. So after running:

$ xcode-select --install

I could run gem install rails without issue. Weird.

FWIW, I’m running OS X 10.11.5 and Ruby 2.3.1 installed via rbenv.

Full output of the errors thrown when trying to install Nokogiri:

$ gem install nokogiri
Building native extensions.  This could take a while...
ERROR:  Error installing nokogiri:
    ERROR: Failed to build gem native extension.

    current directory: /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8/ext/nokogiri
/Users/erikhansen/.rbenv/versions/2.3.1/bin/ruby -r ./siteconf20160703-99836-186h6s0.rb extconf.rb
Using pkg-config version 1.1.7
checking if the C compiler accepts ... yes
checking if the C compiler accepts -Wno-error=unused-command-line-argument-hard-error-in-future... no
Building nokogiri using packaged libraries.
Using mini_portile version 2.1.0
checking for iconv.h... yes
checking for gzdopen() in -lz... yes
checking for iconv... yes
************************************************************************
IMPORTANT NOTICE:

Building Nokogiri with a packaged version of libxml2-2.9.4.

Team Nokogiri will keep on doing their best to provide security
updates in a timely manner, but if this is a concern for you and want
to use the system library instead; abort this installation process and
reinstall nokogiri as follows:

    gem install nokogiri -- --use-system-libraries
        [--with-xml2-config=/path/to/xml2-config]
        [--with-xslt-config=/path/to/xslt-config]

If you are using Bundler, tell it to use the option:

    bundle config build.nokogiri --use-system-libraries
    bundle install

Note, however, that nokogiri is not fully compatible with arbitrary
versions of libxml2 provided by OS/package vendors.
************************************************************************
Extracting libxml2-2.9.4.tar.gz into tmp/x86_64-apple-darwin15.5.0/ports/libxml2/2.9.4... OK
Running 'configure' for libxml2 2.9.4... OK
Running 'compile' for libxml2 2.9.4... ERROR, review '/Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8/ext/nokogiri/tmp/x86_64-apple-darwin15.5.0/ports/libxml2/2.9.4/compile.log' to see what happened. Last lines are:
========================================================================
    unsigned short* in = (unsigned short*) inb;
                         ^~~~~~~~~~~~~~~~~~~~~
encoding.c:815:27: warning: cast from 'unsigned char *' to 'unsigned short *' increases required alignment from 1 to 2 [-Wcast-align]
    unsigned short* out = (unsigned short*) outb;
                          ^~~~~~~~~~~~~~~~~~~~~~
4 warnings generated.
  CC       error.lo
  CC       parserInternals.lo
  CC       parser.lo
  CC       tree.lo
  CC       hash.lo
  CC       list.lo
  CC       xmlIO.lo
xmlIO.c:1450:52: error: use of undeclared identifier 'LZMA_OK'
    ret =  (__libxml2_xzclose((xzFile) context) == LZMA_OK ) ? 0 : -1;
                                                   ^
1 error generated.
make[2]: *** [xmlIO.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
========================================================================
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/Users/erikhansen/.rbenv/versions/2.3.1/bin/$(RUBY_BASE_NAME)
    --help
    --clean
    --use-system-libraries
    --enable-static
    --disable-static
    --with-zlib-dir
    --without-zlib-dir
    --with-zlib-include
    --without-zlib-include=${zlib-dir}/include
    --with-zlib-lib
    --without-zlib-lib=${zlib-dir}/lib
    --enable-cross-build
    --disable-cross-build
/Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:366:in `block in execute': Failed to complete compile task (RuntimeError)
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:337:in `chdir'
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:337:in `execute'
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:111:in `compile'
    from /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mini_portile2-2.1.0/lib/mini_portile2/mini_portile.rb:150:in `cook'
    from extconf.rb:364:in `block (2 levels) in process_recipe'
    from extconf.rb:257:in `block in chdir_for_build'
    from extconf.rb:256:in `chdir'
    from extconf.rb:256:in `chdir_for_build'
    from extconf.rb:363:in `block in process_recipe'
    from extconf.rb:262:in `tap'
    from extconf.rb:262:in `process_recipe'
    from extconf.rb:555:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/nokogiri-1.6.8/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/nokogiri-1.6.8 for inspection.
Results logged to /Users/erikhansen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/nokogiri-1.6.8/gem_make.out

Better LaunchBar Arrow Keys

launchbar-alternative-arrow-keys

I like the “Vim Mode” option in LaunchBar that allows you to use the H-J-K-L keys as arrows keys if you hold down CONTROL. But, on a MacBook keyboard at least, I still find it a little awkward to press the CONTROL key. It’s not the worst thing in the world, but I figured there’s a key I can remap to CONTROL using our good friend Karabiner. Here are the things I tried, from worst to best.

The Bad Ideas

First, I tried remapping my Hyper Key to CONTROL when LaunchBar is active. It’s much easier to reach over and hold down the CAPS LOCK key with my left pinky than it is to reach down for the CONTROL key with my left pinky. I used this for a day or two but got annoyed because I found that it was pretty common for me to want to use app launching shortcuts while LaunchBar was active. But if LaunchBar was active I couldn’t use HYPER-A to switch to iTerm or HYPER-E to switch to my editor.

So I realized that simply holding down the A key could be remapped to holding down CONTROL.

<item>
  <name>Hold A to Control in LaunchBar</name>
  <appendix>Tap to enter an A character</appendix>
  <identifier>private.a_control_launchbar</identifier>
  <only>LAUNCHBAR</only>
  <autogen>
    --KeyOverlaidModifier--
    KeyCode::A,
    KeyCode::CONTROL_L,
    KeyCode::A,
  </autogen>
</item>

That’s actually easier than reaching all the way over to the CAPS LOCK key with my pinky. The problem is that I found that if I was typing fast enough LaunchBar would lose keystrokes. For example, if I typed “kar” to launch Karabiner, the only thing that would get entered into LaunchBar was a single K.

The Good Idea

How about if I have to hold down two characters at once to simulate CONTROL? Sounds great! If I hold down D and F together, that will act like I’m holding down CONTROL:

<item>
  <name>D+F together to Control in LaunchBar</name>
  <identifier>private.df_together_to_control_launchbar</identifier>
  <only>LAUNCHBAR</only>
  <autogen>
    __SimultaneousKeyPresses__
    @begin
    KeyCode::D, KeyCode::F,
    @end

    @begin
    KeyCode::CONTROL_L | ModifierFlag::NONE,
    @end
  </autogen>
</item>

This seems to work great. I can’t find a problem with it. But there’s an even better way.

The Best Solution

There’s a built-in Karabiner option called Simultaneous Vi Mode.

karabiner-vi-mode

When you turn it on, you can hold down S and D together so that you can use the H-J-K-L keys as arrows keys anywhere in the system. Brilliant. I’ve had this turned on for a few minutes and have already found it useful.1 I also like that with this option, Karabiner pops up a little notification-style HUD in the bottom-right corner of the screen to let you know that this mode is active.

Karabiner HUD
Karabiner HUD


  1. I did notice that very rarely I’d type an “s” and “d” fast enough that Karabiner would turn on Vi Mode and my keystrokes didn’t register. To fix this I adjusted the Simultaneous Key Presses > Delay Threshold of Key in the Parameters tab. Its default value is 50ms. Turning it down to 40ms seems to prevent the accidental triggering. 

iTerm2 v3 and LaunchBar

If you are running the iTerm2 v3 beta and have iTerm set as your preferred terminal application in LaunchBar’s preferences, you may have noticed that LaunchBar’s terminal commands will not work. For example, selecting a path in LaunchBar and then choosing the Open Terminal Here command (or simply hitting ⌘T), fails silently. Read more here or check out this Twitter conversation.

I came up with two different ways to deal with this.

First, here are two LaunchBar actions you can install. One is used to open a path in a new iTerm tab and the other is to open a path in a new iTerm window.

Second, if you really want LaunchBar’s ⌘T shortcut to open the selected directory in iTerm2 v3, I put together a hack that will do just that. Getting that all set up is more involved than just installing a LaunchBar action but it’s not that bad.

The LaunchBar team has known about this issue for some time now. I suspect that they haven’t changed things on their end because iTerm2 v3 has been in beta. Looks like iTerm2 v3 will be “official” very soon and when that happens, I suspect that LaunchBar with be updated. At that point, these actions and hacks won’t be needed. Until then, they should fill the gap for you well enough.

Karabiner + LaunchBar

I’ve been digging into Karabiner over the past couple of days. It’s been bending my mind a little bit. One thing I wanted to do was assign a key-for-key remap, but only when LaunchBar has focus. This was problematic because LAUNCHBAR never became the active app as far as Karabiner was concerned.1 So any <item> that you create that contains <only>LAUNCHBAR</only> will never fire because Karabiner never knows that LaunchBar is active. Then I stumbled across the built-in options for LaunchBar in Karabiner’s Change Key pane. If you check the Open LaunchBar by command-space option, Karabiner will recognize when LaunchBar is active so you can write remaps that work only with LaunchBar.2 Sweet. That’s exactly what I’m looking for.3 The trick seems to be explicitly opening LaunchBar with KeyCode::VK_OPEN_URL_APP_Launchbar.

karabiner-launchbar

As an added note, there’s a built in rule you can turn on that’ll remap hitting F and J together to invoke LaunchBar. Or, more specifically, it just remaps a simultaneous press of the F and J keys to ⌘-SPACE. But this will invoke LaunchBar without Karabiner knowing that it’s active. So here’s a rule you can add to your custom.xml that’ll activate LaunchBar and work with Karabiner remaps that target LaunchBar.

<item>
  <name>Press F+J Together to Invoke LaunchBar</name>
  <appendix>Invoke LaunchBar and make it the active app</appendix>
  <appendix>so that Karabiner remaps that target LB work</appendix>
  <identifier>private.f_j_together_to_launchbar</identifier>
  <autogen>
    __SimultaneousKeyPresses__
    KeyCode::F, KeyCode::J,

    KeyCode::SPACE, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_COMMAND | ModifierFlag::NONE,
    Option::KEYTOKEY_AFTER_KEYUP,
    KeyCode::VK_OPEN_URL_APP_Launchbar,
  </autogen>
</item>

  1. You can observe this by opening the Karabiner EventViewer from the menubar item and switching to the App tab. 
  2. By the way, choosing the option to map the semicolon key to return when LaunchBar is active might be something that I can really get used to. 
  3. Okay, maybe this isn’t exactly what I want. I’ve noticed that with this option enabled, it takes an extra tap of the space bar to activate LaunchBar’s app switcher. Normally, you could invoke LaunchBar, hit space, and you’d be at the previously used app. It’s pretty quick. But now you need to invoke LaunchBar and hit the space bar TWO times to get back to the previous app. Kind of a pain in the ass, but it’s really one of my own creation since I’ve temporarily disabled the built-in ⌘-Tab app switcher

Disabling Command-Tab on Mac OS X

NOTE: This experiment only lasted a couple weeks before I re-enabled cmd-tab. Also, Karabiner does not work with macOS 10.12 Sierra so you won’t be able to implement this hack if that’s your OS.

I’m trying an experiment. I’ve disabled ⌘-Tab on my computer. I wanted to try using LaunchBar’s app switcher in place of it, but there’s no way that I can override nearly twenty-five years worth of muscle memory1 without a little brute force. Karabiner to the rescue. Here is my entry in custom.xml to make it happen:

<item>
  <name>Disable Command-Tab</name>
  <identifier>private.disable_command_tab</identifier>
  <autogen>
    --KeyToKey--
    KeyCode::TAB, VK_COMMAND | ModifierFlag::NONE,
    KeyCode::VK_NONE
  </autogen>
  <autogen>
    --KeyToKey--
    KeyCode::TAB, VK_COMMAND | VK_SHIFT | ModifierFlag::NONE,
    KeyCode::VK_NONE
  </autogen>
</item>

If you wanted to remap ⌘-Tab to actually do something, such as Escape, this would do the job:

<item>
  <name>Remap Command-Tab to Escape</name>
  <identifier>private.command_tab_to_escape</identifier>
  <autogen>
    --KeyToKey--
    KeyCode::TAB, VK_COMMAND | ModifierFlag::NONE,
    KeyCode::ESCAPE
  </autogen>
</item>

I’m not sure if this will stick. Giving up ⌘-Tab in favor of the LaunchBar way, I mean. ⌘-Tab and ⌘-Space are probably the two key-combos I hit more than any on my computer. Day in and day out I’m living in LaunchBar and switching between apps. I figure if I can just use ⌘-Space for both things, it will eventually be a net win. Also, in the few minutes I’ve had this set up, I can already feel things happening to my brain. ⌘-Tab is something I trigger without thinking. And I truly mean that it can be mindless in the worst way. Sometimes it makes me feel like a rat in a cage, hitting the lever to get a drug hit.2 The fact that my old ⌘-Tab habit no longer has any effect is making me act in a more mindful manner. Before I leave the current app to move to a new app, I have to think for a split second about where I want to go and what I want to do. It’s a subtle change that makes me feel more focused. The downside is that occasionally it adds friction that wasn’t there before.


  1. I started using Alt-Tab way back with Windows 3.1 in the early/mid 1990’s! 😱 
  2. But I don’t blame the poor rats for getting addicted to drugs while they were forced to live alone in miserable conditions.