Making symlinks with LaunchBar

I always forget the exact syntax for making a symbolic link from the command line. It’s quick enough to look it up, especially when using Fish’s history search capabilities, but ever since I noticed you could make symlinks with LaunchBar, that has become my preferred method.

The animated GIF below shows making a symlink of a folder in my LaunchBar actions folder (~/Library/Application Support/LaunchBar/Actions/beats-x-launchbar-actions) in a subfolder in my Projects folder (~/projects/launchbar-actions).

The workflow goes like so:

  1. Select the folder you want the symlink to point to. In this case I selected it in the Finder and sent it to LaunchBar with Instant Send.
  2. Hit tab to invoke Send To…
  3. Select the target folder, where you want the new symlink to live. In this case I:
    • Navigated to my ~/projects folder by typing p
    • Tapped the right arrow key to navigate into the folder
    • Started typing the name of the target folder laun
    • Hit enter to get the list of actions
  4. Select “Make Symbolic Link (Absolute)” from the list of file actions.

LaunchBar: Quick Calculations In-Place

This is a real case I ran into the other day while posting to my blog. The image embed code generated by WordPress set the image dimensions to twice what I wanted them to be. My intellectual laziness (not wanting to do some simple math in my head) is your gain because you’re going to learn how to do some quick calculations “in-place” with LaunchBar’s calculator and Instant Send feature.

Method One

  1. Select the number you want to do a calculation on.
  2. Send that number to LaunchBar with Instant Send. In my case that’s done by double-tapping the Command (⌘) key.
  3. Type /2 to divide the number by two.
  4. Type ShiftEnter to paste the resulting number back into the app you initially copied from.

Method Two

  1. Type the math equation in place. In this case by turning 628 into 628/2.
  2. Select that equation and send it to LaunchBar with Instant Send (double-tap Command).
  3. LaunchBar automatically detects you gave it a math problem so it instantly solves it for you. So type ShiftEnter to paste the result back to where it came from.

`e` and `ee`

How many times have you typed something like atom .gitignore or code my-project to open a specific file or folder in your editor? And how many times have you typed code . to open the current folder in your editor? I personally do that one a ton.

Not only is that too many characters to type, what happens when you decide that Atom is slow and it’s time to move to Visual Studio Code? You’ve got to retrain yourself to use a different four character command each time you open a file or directory.

Screw that. Set up an alias:

Fish: alias e "code"
Bash: alias e="code"

Now you can type e my-project or e .gitignore to open a file or folder. And when you decide to give a new editor a try you can change your alias to point to you editor du jour and continuing just typing e at the command line. With this alias, opening your current directory is as easy as typing e .. But that’s not easy enough for me. It’s three whole characters when you count the space. And the E key and period key are on different sides of the keyboard! Wahhh! So set up a second alias:

Fish: alias ee "e ."
Bash: alias ee="e ."

Every time I type ee to open the current directory, I smile. At least on the inside. And you will, too.

Code Helper CPU Usage

Thanks to iStats Menus I noticed there was a process constantly using just enough CPU to attract attention. Activity Monitor showed that one of the VS Code helpers was hovering at around 7%. Not terrible, but it was annoying me.

After a little trial and error, disabling and reenabling extensions, I discovered it was the Settings Sync extension. Once that was disabled things calmed down. I dug a little deeper and discovered that it was turning on the sync.autoUpload setting (which is off by default) that was really doing it. With that set back to false the extension ran fine without using a bit too much CPU for my taste.

Switching Shells

I’m not sure how I made it this far into my career without knowing I could quickly switch between fish and bash and zsh and any other shell I have on my system by simply typing the name of the shell I want to use.

Since I switched from zsh to fish around a year and a half ago, I’ve kept the stock macOS Terminal app (I normally use iTerm) set up to use zsh just in case I wanted to test something in a POSIX-compatible shell. All this time I’ve thought I’d have to do the following if I wanted to switch from fish to zsh:

  1. Type chsh -s (which zsh)
  2. Enter my account password
  3. Open a new terminal tab

Nope.

Just type zsh. Done.

A Modest Proposal on Naming Files

Trying to decide if you should replace spaces in your files names with dashes or underscores? Choose dashes. Why? If you use dashes, when you are editing the file name you can jump from word to word by tapping the left or right arrow key while holding down Option. Said another way, macOS recognizes the dash as a word separator; not so with the underscore.

VS Code Quick Tip: Exit Preview Mode

If you’ve got VS Code’s enablePreview options turned on, and they are by default, you might like to know that you can just hit ⌘-S to take it out of “Preview Mode” to prevent it from being replaced by the next file you open. In my opinion this is better than the other methods to make a file stay open: double-clicking the file’s tab (eww, touching your mouse or trackpad) or making the file “dirty” by entering some text and immediately deleting it.

I’ve never used this “preview” feature in any editor. I’ve recently gotten sick of ending up with dozens of tabs open in a project so I’ve been giving it a shot. This little tip is making me actually enjoy the feature.

Speaking of preview modes in text editors, I’d kill for Sublime Text’s legit preview mode the would instantly show you the contents of the file you had selected in the Quick Open menu. So good!

Global npm Module Weirdness

I just installed node 8.9.1 with nodenv. Then I wanted to get my global packages installed to more-or-less match what I had with my previous version of node (v6.11.3).

Running npm list -g --depth=0 with node 6.11.3 active gives me:

❯ npm list -g --depth=0
/Users/erikhansen/.nodenv/versions/6.11.3/lib
├── eslint@4.7.1
├── eslint-config-airbnb-base@12.0.0
├── eslint-config-prettier@2.5.0
├── eslint-plugin-import@2.7.0
├── eslint-plugin-json@1.2.0
├── eslint-plugin-prettier@2.3.1
├── generator-code@1.1.20
├── gulp@3.9.1
├── npm@3.10.10
├── prettier@1.7.3
├── prettier-eslint@8.2.0
├── vsce@1.31.1
└── yo@2.0.0

So with node 8.9.1 active I ran npm i -g eslint gulp prettier prettier-eslint yo generator-code to start installing a bunch of — but not all of — the global packages that I wanted.

Now for the weird part: Running npm list -g --depth=0 to see the current state of the world gives me this:

❯ ng # <-- a handy alias for `npm list -g --depth=0`
/Users/erikhansen/.nodenv/versions/8.9.1/lib
├── generator-code@1.1.22
├── gulp@3.9.1
├── npm@5.5.1
├── prettier-eslint@8.2.2
└── yo@2.0.0

eslint isn’t listed as a global package! But I have it installed:

❯ which eslint; and eslint -v
/Users/erikhansen/.nodenv/shims/eslint
v4.11.0

I looked a little deeper and found eslint installed as a dependency of prettier-eslint (which, by the way, is not a module that I actually wanted to have installed globally):

❯ npm list -g --depth=1
...
├─┬ prettier-eslint@8.2.2
│ ├── ...
│ ├── eslint@4.11.0
...

And further, digging into where nodenv actually stores the globally installed modules, in this case ~/.nodenv/versions/8.9.1/lib/node_modules, I see that eslint is indeed there at the top level!

Questions…

So the question is:

Why doesn’t npm list eslint as a top-level globally installed module when it seems as though it is one?

The follow up question is: Why does it bother me as much as it does that eslint doesn’t show up in that list of global modules even though everything works as though it is a top-level global module?

The Fix

How to fix this “problem”? One option is to just blow away all of the globally installed packages by running this a couple of times:

npm ls -gp --depth=0 | awk -F/ '/node_modules/ && !/\/npm$/ {print $NF}' | xargs npm -g rm

That’s extreme and is likely something that you wouldn’t want to do in most situations.

The other option is to remove the package that has eslint as a dependency, which is a package I didn’t want to have installed in the first place: npm -g rm prettier-eslint

Now the world is happy again:

❯ ng
/Users/erikhansen/.nodenv/versions/8.9.1/lib
├── eslint@4.11.0
├── generator-code@1.1.22
├── gulp@3.9.1
├── npm@5.5.1
├── prettier@1.8.2
└── yo@2.0.0

Final Note

At this point reinstalling prettier-eslint works and eslint still shows up as a global package.

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.