MP

How to Create a Hotkey That Selects the Current Word (OS X)

One of my favorite features in Sublime Text is the Cmd+D keyboard shortcut that selects the word nearest to your text cursor. Multiple presses select other instances of the word allowing you to edit them simultaneously, but I mostly use it to select the word I just typed.1 A similarly helpful feature has come to the iPad and iPhone 6S in iOS 9.2

Since most of my day is spent in Sublime Text, pressing Cmd+D quickly made its way into my muscle memory, and I started attempting to use it in other programs to no avail. A little bit of searching led me to the discovery that OS X has a similar feature built-in, but it’s not easily assigned to a hotkey.

You’ll need to create ~/Library/Keybindings/DefaultKeyBinding.dict and add the following lines to it, then restart any open applications you want to use the hotkey in:

{
  // ^ for Control, ~ for Option, $ for Shift, @ for Command
  "^w" = (selectWord:);
}

The example above uses Ctrl+W, but you can customize it to your liking. For instance, swapping ^w for @d would match Sublime Text’s key combination.3

Any application that uses native text fields will now allow you to quickly select the current word. Have fun editing!

  1. If you’re interested in editing every instance of the current word, there’s a better way: Cmd+Ctrl+G

  2. iPad: Tap the keyboard with two fingers.
    iPhone 6S: Press down hard on the keyboard. 

  3. Be careful. Unfortunately Cmd+D is set to other actions in a lot of applications, and this won’t override it. For instance, Safari uses it to create a bookmark. You might want to pick something else. 

Zsh PATH Issues in OS X 10.11, El Capitan

I immediately ran into problems with my PATH after upgrading to El Capitan. Instead of using my custom version of Ruby, El Capitan was using the system version. It was easy to spot why: OS X was reordering $PATH.

If you’re having the same problem, I suspect we have similar setups: I set $PATH in ~/.zshenv so Pow and GoSublime have access to it; I configure aliases and functions in ~/.zshrc since it’s more efficient to only load them for interactive sessions.

As it happens, El Capitan introduced a global Zsh profile at /etc/zprofile that calls /usr/libexec/path_helper, a utility which adds system directories to $PATH, reorders it, and then removes duplicates.1 Our customizations are being overwritten because Zsh calls /etc/zprofile after ~/.zshenv.

Solution 1: Disable Loading Global Profiles

If you don’t want to load /etc/zprofile or other global settings, there’s a command to disable them. All you do is add this line somewhere in your ~/.zshenv file:

setopt no_global_rcs

There are two things to be aware of with this fix although I find it highly unlike either will affect you:

  1. Future OS versions may modify these files with changes you need.
  2. If you’re on a multiuser system, your system administrator could be using the global files to configure settings and functions related to your job.

Since I find it unlikely OS X will change these files and since I am my own system administrator, this is the solution I’ve personally enacted.

Solution 2: Don’t Set $PATH in Zshenv

The biggest reason I set my PATH in zshenv is so Pow and GoSublime will have access to it, but most programs have multiple ways to set their search locations. For instance, Pow checks ~/.powconfig for exported variables. Likewise, GoSublime has a settings file where you can set $PATH and $GOPATH. Just move your PATH setup to ~/.zshrc or ~/.zprofile and configure your tools using their custom methods.

For instance, a Pow config for use with rbenv might look like this:

export PATH=/Users/$(whoami)/.rbenv/shims:$PATH

The downside is you will need to update multiple files if you ever change your Ruby, Go, or similar setup.

  1. OS X has always done this for Bash (in /etc/profile) and Csh (in /etc/csh.login). While an annoying change, it appears to have been made for consistency. 

A Fix for Safari Forgetting Your History

For the last few months, Safari would forget bits of my browsing history every time I closed it. After around 24 hours only one or two items would be left listed for the previous day of browsing. There was no logic to what was being remembered or how quickly history items would disappear.

I upgraded OS X; I disabled all my Safari extensions; I cleared out the cache, cookies, and the few items left in History; I turned off syncing Safari to iCloud in System Preferences; I closed every application and background process I found running; I checked to make sure that “remove history items” wasn’t set to “after one day”1 and I even changed it to “manually” to see if there was a bug. Nothing worked.

Screenshot of Safari's preferences

If you’re here it probably means googling hasn’t been helpful: most search results are for people who want to disable history tracking. I feel your pain, but hopefully you’re in luck.

Solution

My problem stemmed from a corrupted database in ~/Library/Safari/. There are four or five files in that folder related to storing your history, depending on your OS version. You should close Safari and then delete all of them: History.db, History.db-lock, History.db-shm, History.db-wal, and HistoryIndex.sk (if it exists).2

Screenshot of Safari's Library folder

With any luck, you should now be able to open Safari, load a website, and then close Safari without it losing your history.

Updates

  • Screenshots and instructions updated for macOS 10.15 (Catalina), although I haven’t needed to do this again since publishing the article. — 31 May 2020
  1. This was officially the most common suggestion, and it started to become infuriating. That said: go check it just to be safe. It’s the most common for a reason. 

  2. The easiest way to open that folder is:

    1. Open Finder
    2. Press Cmd+Shift+G
    3. Type ~/Library/Safari/
    4. Press Go

Standing Still

There is nothing inherently wrong with nostalgia or tradition, but there’s a point where it can go dreadfully wrong, where we can get trapped in it. Our past starts to clutter our present. Eventually we reach a point where we can’t move forward with our lives because we’re too afraid of upsetting the past.

Life is one big, grand experiment. It’s also short. We’re doing ourselves and humanity a disservice by pushing the status quo.

Where we go next may not necessarily be better or worse than where we are now, but sometimes you have to move on anyway. If we don’t push forward, constantly testing and expanding our limits, we risk stagnating.

No great period in history ever got started by standing still.

Greatness

When asked how they capture such stunning photos, professional photographers tell the same story: film is cheap. Take a lot of photos with the understanding that you’ll throw almost all of them away. For every masterpiece you see, there were hundreds of photos that weren’t good enough, but it’s better to waste some film than to miss a once-in-a-lifetime opportunity.

Your opportunity could be right around the corner—you could be on the verge of creating a masterpiece—but only if you keep trying.

Don’t give up. Life is too short to worry about the obstacles in your way.

The State of Music Streaming Services

With Apple’s developer conference kicking off tomorrow and rumors swirling about a new Apple music service, I thought now would be a good time to finally write up my thoughts on the current state of music streaming services.

(Disclaimer: I do not attempt to extensively cover music streaming services. I only discuss a few specific features—or lack of features—in Spotify and Rdio that bug me, with some postulations about how Apple’s service might improve them. That said, I did try to pick things I hadn’t heard other people talk about before.)

Bring Your Own Music

It’s imperative that users have a way to easily play songs they’ve bought elsewhere; no matter how hard music companies try to sign-up artists, there will always be some that aren’t on their service—artists like Taylor Swift, who pulled her albums from Spotify last year.

While Spotify lets you add local audio files to your library and sync them to your devices, the files are exiled to their own section of the app. If you like curating playlists manually, you’ll love Spotify: that’s the only way you can listen to a contiguous mix of streamed music and local audio tracks. You can forget about plugging in your headphones and just pressing shuffle.

Sadly, the Spotify experience is still better than Rdio, which doesn’t offer any way to play local files. Like some indie songs that aren’t on Rdio? Get ready to swap back-and-forth between music apps.

If there’s one thing I expect Apple to get correct, it’s this. In fact, that’s what we already see happening with iTunes Match: if a local song can’t be matched with one on their server, your copy gets uploaded and then synced to all your devices, and it shows like normal alongside all your iTunes Store purchases. I don’t expect any of this to change as Apple begins their foray into music streaming.

Importing Your Existing Library

If streaming services would let you bring your own music, importing your existing library wouldn’t be necessary, but we’ve already seen how well that works.

In a past life, Spotify let you drag songs it recognized from your “Local Files” view to your Spotify library, but it won’t let you anymore. The artist name and album title of recognized songs are clickable within the Local Files view, but there’s no easy way to add them to your library. Your options are to load each album page and manually save them, or you can use a third-party service that’s likely to break.1

Rdio does have a way to automatically add songs from your iTunes library to your Rdio library. It’s not perfect (some songs aren’t matched even though they’re on Rdio), but adding a handful of leftover songs is easier than manually importing an entire library worth.

Again, iTunes Match already handles this. You can easily important any DRM-free audio files you want. It’s not always perfect when matching songs, but that’s a non-issue since unmatched files get uploaded and synced to all your devices anyway.

Playlists, Radio, and Moods

I think a lot of people still discover new artists and songs through radio and radio-like sources, but that’s completely anecdotal. Sure, you can follow artists you already know on social networks, or your friends may post links to songs they love, but what if your friends share a different taste in music?

Trusting someone else to filter the bad songs for you is relaxing. When I listen to music, I want to hear a mix of current songs I love, older songs I love, and new songs I haven’t heard before. This is where playlists and radio stations shine, and I’m not the only one who thinks so: Spotify added playlists handpicked by experts a few years ago and just recently announced Spotify Running, a feature that picks songs based on their tempo and your running speed; Beats Music built their entire business around curated playlists, and Apple thought it was such a good idea that they decided to acquire Beats Music last year.

This is, thankfully, the one thing that almost every music streaming service gets correct, although Pandora has a tendency to tilt too heavily toward older songs. Almost all streaming music services seem to believe that discovery is one of the most important things they can provide, or else there’s really nothing separating them from their competitors, and nothing keeping you interested enough to come back.

Spotify has recently stated they believe music genres are dying and that most people will start listening based on the mood of the music rather than the genre. It’s certainly an interesting proposition. I’ve been in dilemmas where an artist like Adelle would surface during the middle of a happy mix of songs. I love Adelle—she has an amazing voice—but I don’t want to hear a breakup song while I’m tired and driving in traffic; I want to hear breakup songs when I’m coming off a bad relationship, but I don’t want to make a playlist called “Music For When I’ve Been Dumped” and another playlist for songs I like when I haven’t recently been dumped.

This is the area I am most excited about as I watch Spotify and Beats battle it out for dominance in the playlist field.2 I’m very interested to see how good curated playlists are at Apple’s scale. I have nothing against Spotify’s playlists and radio stations, but they’re not perfect. iTunes Radio feels about the same right now whenever it works: there’s a bug where liking/disliking too many songs will result in a station being perpetually “Unavailable.”

Radio Edits, and Songs in Multiple Albums

Two thing that none of these services get correct is radio edits and songs that can be found in multiple albums. iTunes tries to tell you if you’ve bought a song already, even if it’s from another album, but only in the iTunes app; iTunes Radio for iOS, Mac, and AppleTV don’t recognize if you already own a song unless it’s exactly the song and album you purchased it from.

Buy it from another album? Purchase it from somewhere like Amazon? Even if it’s recognized by iTunes Match, iTunes Radio will try to sell you the song all over again.

If you think Spotify and Rdio are in the clear, think again. The same thing happens if you’re listening to a song on one of their playlists or radio stations. I have accidentally added a song to my library multiple times because it couldn’t tell I had already saved that song from a different album.

Which brings me around to radio edits: where’s the option to prefer radio/full edits of songs? I’ve also accidentally added both a radio and full edit of a song to my library, which all three services will occasionally play back-to-back just to screw with me. Remixes share a similar problem.

Across the board, all services fall flat in this area. I’d love to see some improvements.

  1. At publishing, Unify’s website displayed this message: “Unify is no longer compatible with the current version of Spotify. We’re working on an update. Please come back soon.” 

  2. Pandora, I think, has stagnated: their algorithms have not gotten better at detecting what I enjoy, and they have a huge tendency to resurface tired, old songs. Likewise, I haven’t heard any new movement from Rdio in this area. 

Apple Watch: Third-Party Complications

There are two ways the Apple Watch can convey information: it can “push” information to you when it thinks you’ll need it, or you can seek out and “pull” information when you want it. Of the two methods, it’s quicker for the Watch to push you information, but what happens when it can’t read your mind?

What if you could preemptively tell it 3–4 pieces of information you need most, so it can display them every time you lift your wrist?

Consider the attention hierarchy laid out by Horace Dediu:

The Apple Watch offers a hierarchy of surfaces onto which software can compete for attention:

  1. The Complication Layer
  2. The Notification Layer
  3. The Glances Layer
  4. The App Screen

These surfaces are arranged in a hierarchy where the highest is the most accessible and the lowest is the least accessible.

It’s safe to say that Apple is investing efforts in smarter notifications, à la Google Now, but complications will always be the quickest way to pull information from the Watch since they don’t require you to touch the screen.1

If Apple’s goal is to make your experience with the Watch as quick as possible, to help you grab information in a matter of seconds instead of minutes, then allowing third-party apps to make complications is an appealing solution. I have a suspicion we’ll eventually see them.

  1. Ben Thompson expounds upon this idea, adding Siri to the mix. But no matter how fast Siri responds, you always have the delay of talking to it—at least until computers can literally read our minds. 

Apple Watch: First Impressions

The Apple Watch try-ons have officially begun, and yours truly was one of the first to check it out. James and I discussed this a little bit on episode two of Refactor, but I’ve written my full first impressions below. The list isn’t written in any particular order, but it is from the viewpoint of a casual watch wearer.1

Screen & Software

  • The retina display is gorgeous. I didn’t see any “air gap” on the units I played with, although I did see the screen edges at certain angles and lighting. That’s disappointing, but it’s not a deal-breaker.
  • While some people are reporting the demo units are laggy, the applications and animations I experienced ran smoothly. Data loaded from an iPhone over bluetooth will certainly be a different experience, but my impression of the built-in software was good.
  • I enjoyed using the digital crown. It’s a little awkward to use on the demo/table units but not on the units that you wear. I think I’ll prefer using it since you don’t have to stop and lift your finger to look at the screen—just keep on scrollin’.
  • If you’re used to mashing your finger on the screen, it might take you some time to adjust to Force Touch. When I first tried to interact with the Watch, a lot of my presses were registering as a Force Touch instead of a regular touch. Until I figured that out, I thought the software was buggy.

Models & Sizes

  • Both size watches are smaller than I expected. I went in thinking the 42mm would be too large for my wrist, but it’s actually smaller than my current watch. I suspect the size people choose will be much more about personal preference than a size “required” by their wrist.
  • Both size watches are simultaneously lighter and heavier than other watches I’ve worn, so you need to try one on in person if you’re worried about the weight. Overall, all models and sizes are light enough that I don’t think weight is a good primary reason to avoid buying one.
  • The silver Sport lived up to my expectations. It looks very similar to a MacBook or iPhone, but it’s not something I would feel proud wearing on my wrist each day since my current watch is stainless steel. If you can’t afford the stainless steel, the space gray is definitely more elegant, and it looks perfect with a black Leather Loop if you can afford to upgrade the band.

Bands

  • The Sport band is definitely softer and smoother than I expect of rubber watch bands. I didn’t notice a difference between the different colors, but some people have.
  • The Classic Buckle is amazingly soft leather, especially for its position in the pricing lineup. You won’t be disappointed if you’re looking for a simple, standard band.
  • The Leather Loop is a harder leather, probably because the magnets inside force it to be both thin and durable. It still feels great against your wrist, and I didn’t have any problems adjusting it to different sizes. I thought it was much easier to put on and adjust than the Sport and Classic Buckle.
  • The Milanese Loop was very smooth and bends more like a fabric than a metal.
  • The magnetic clasp in all the applicable bands was stronger than I expected, especially on the Milanese Loop. I feel confident they won’t accidentally come undone throughout the day.
  • I don’t care for link watch bands, so I don’t have a huge opinion on the Link Bracelet; however, it does seem much nicer than other link bands I’ve worn. If you like that kind of band, it’s worth the cost.

Discipline: Breaking the Cycle of Guilt

I often find myself caught in an unhealthy cycle. I’ll start feeling guilty about not being productive, which inevitably leads to less productivity and even more guilt—rinse and repeat as things slowly spiral out of control. If your income depends on these tasks, you can’t wait on motivation to dig yourself out of the hole you’ve created. The only way to reenter the world of the living is through pure grit.

So how do you discipline yourself in the face of no motivation?

By building habits – starting as small as you can manage, even microscopic, and gathering momentum, reinvesting it in progressively bigger changes to your routine, and building a positive feedback loop.

Discipline is a muscle, just like your attention span. The more you exercise that muscle, even on a small scale, the better you get. Like I’ve discussed before, tackling small tasks helps generate confidence and momentum. The key to breaking the guilt cycle is just to make progress on something. Little wins are still wins. If you try and fail, start smaller next time.

To quote Avery Edison:

When it comes to school, I don’t miss the people, or the rules, or the cafeteria food. But I do miss the clear sense of progression, of getting an assignment and completing it, of filling something out and receiving a grade. I miss the clear journey from the start of the path to the end, moving your feet and making your way.

I’m sure a lot of us feel that way, and there’s nothing stopping us from recreating that clear sense of progression in our adult lives. It all starts with discipline and little wins. Try a Seinfeld-style calendar or keep a list of your everyday chores so that you can experience the rewarding task of marking them complete.

iBeacon Delegates Not Being Called

There are a lot of glamorous iBeacon problems out there. This post doesn’t contain any of them. Instead, this is a post about two embarrassingly simple errors and how I fixed them.

Your CLLocationManager Must Be Recreated When You Return from Backgrounding

I read the documentation for CLLocationManager and its delegate methods, implemented them, and then thought I was done. Unfortunately, hidden away in the documentation for a related class, CLRegion, is something important (emphasis mine):

If the app is not running when a boundary crossing occurs, the system launches the app into the background to handle it. Upon launch, your app must configure new location manager and delegate objects to receive the notification. The notification is sent to your delegate’s locationManager:didEnterRegion: method.

My application was launching in the background correctly, but I wasn’t configuring a new location manager and delegate objects whenever the application launched. It’s a quick fix, and it makes sense in retrospect, but that note isn’t where I would expect to find it in the documentation.

CLRegion Doesn’t Notify When Individual Beacons Change

A CLRegion can contain zero or more beacons using the same UUID. While the didEnterRegion delegate method is called as soon as it spots a single beacon, the didExitRegion method is only called when there are no more beacons in range that match the region’s UUID. Don’t confuse didExitRegion with didExitBeaconRange (which doesn’t exist) or you’ll wear a hole in your floor running back and forth between rooms trying to figure out why your app is never notified.1

If you need to detect when you’ve left the range of one particular beacon, you need to actively scan for beacons (battery intensive) or give each beacon a different UUID so you can create and monitor multiple CLRegion’s.

  1. Hat tip to James Barrow for helping me figure this out. I had an idea for how I thought things should work in my head, and it took James to bring me back to reality.