Archive for the ‘Various Frustrations’ Category

Announcing tmdiff

For all I know this already exists and I just was unable to google it up. Assuming it doesn’t, tmdiff allows you to perform a command line diff on a text file against a time machine version.

Repo: https://github.com/erica/tmdiff

Usage:

Usage: tmdiff (--list)
       tmdiff [offset: 1] path

The list option just lists the dates for the backups in reverse chronological order. Supply a path to diff, e.g.

tmdiff Style600-Control\ Flow.md

It defaults to using the “but last” backup offset of 1. If you want to use the most recent backup, use 0 instead, or any number moving further back in time as the value increases:

tmdiff 0 Style600-Control\ Flow.md
tmdiff 3 Style600-Control\ Flow.md

I hope this is handy for someone out there on the opposite side of the Intertube, especially since version control is baked into stuff like TextEdit. Do let me know if you use it.

Update: See also github.com/erica/tmls and github.com/erica/tmcp. The former runs ls, complete with arguments. The latter performs a nondestructive copy with the Time Machine date appended.

How to add a bookmark in Sierra Safari

I’ve been super-frustrated trying to use ⌘-D to add bookmarks ever since I installed Sierra. The browser only wants to add my bookmarks to existing folders. I, on the other hand, want my bookmarks to go to the main list until I have time to weed and sort them.

This morning, I finally found out how to save bookmarks to the Bookmarks list in Sierra:

  1. Hover your mouse over the left side of the URL bar (aka the smart search field). A circled ⊕ appears.
  2. Do not click it. If you do, you’ll just add the page to the reading list. Instead, click-and-hold until a contextual menu appears.
  3. Now move the cursor down to “Bookmarks” and click there.

safariscreensnapz001

Yeah, it’s a lot stupider than just typing ⌘-D, but at least it works the way you expect. If bookmarks and ⌘-D are working right for you, please let me know. I can’t think of anything I might have done to mess up Safari but at least it will be a data point to help.

The unbearable Swiftness of web search

Swift proposal SE-0086 removed the NS prefix from many types in the Swift Foundation library. In doing so, it moves Swift away from its Cocoa roots to establish a cleaner language palette to work with. Swift adheres to a philosophy that type names should be clear, consise, and without needless prefixes.

The result are names that are intuitively obvious, easy to understand, and a real pain to search for. If you thought tracking down information on Swift filters, conversions, mapping, strides, streaming, and notifications was hard, then you may appreciate what it’s like to search for Swift Bundle, Operation, Process, or Thread.

Swift (the language) is now gaining sufficient traction that searches are far more responsive for programming than they used to be. Still, it  helps to throw in an extra word or two like codesample, or type to focus your search. You may also want to limit searches to, for example, “site:apple.com”.

And, yes, you can always pick up one of those Swift Calendars and read about Swift Dates. Swift wasn’t named after a certain pop star. It just sometimes acts like it was.

p.s. For Dave Abrahams: COW optimization.

When did Ikea ditch the sunshine, rainbows, and unicorns?

The new Ikea catalog arrived yesterday. Is it me or have they turned over their design to some crazed Swedish goth intern? My new catalog feels more Hitchcock and “Vogue Editorial” than “Affordable purchases for people who wish they could fix their out-of-control lives.”

Ikea’s gone from cute girls in a colorful apartment (top, 2015) to psychotic butcher knives that think they’re actually vegetables (check out that shadow) and this recurring weird backdrop thing, which makes me think they couldn’t afford an editor to crop the photos properly (bottom, 2016).IMG_1527

Suddenly, they’ve transitioned from simple product images inspiring you to simplify and organize  your life to a kind of nightmare clutter scenario where all reason has fled and you apparently must buy every product available from the company and store them in the open without drawers, cupboard doors, or any break in sanity.

IMG_1521

Look at that poor woman standing at that kitchen island. Her entire body communicates the tenseness from barely having a spare inch of counter space, banging her knees against all the junk on the two shelves, the shame of putting your dishes out for public viewing. Inside, she’s screaming “I will never get my life under control and it’s all IKEA’s fault! For just $499!”

(By the way, I love the LED light at the middle of the right page of the 2015 catalog. Mine is black, not red, and it’s perfect between my two computer monitors. Folds up out of the way when not in use.)

IMG_1526

Apparently 2016 is the year of dark spaces, drawn blinds, and Carmen cosplay. You can pretend to die of consumption in the gloomy shadows of your living room, while dressed in red and practicing ballroom in the  (perhaps) 2 square meters of space between couches.

And can you think of anything scarier than your sofa actually being your home. Last year, a beautiful, open plan living room, with a family happily getting work done on the laptop and reading to a kid. They seem happy, their plants seem happy, the lightness and brightness no doubt makes them feel free and open and relaxed. Compare that to this year.IMG_1525

No, Ikea, a sofa is not the home. And who are all those strange people who wandered into this poor woman’s life just to stare at and harass her?

Here’s Elsa. Elsa thought she’d have a lovely relaxing time, putting up her feet before picking up the kids and stopping by an organic locally sourced market for take out to eat while perched on a variety of ottomans and sleeper couches.

Who would ever have expected an entire gang from Twitter to take up residence on the other side of her monster sofa, laughing at her, mocking her, and critiquing her lounging style. That gang of four sure think Elsa is a hoot. And all at the same time, creepy Helmut from down the road just stares at Elsa with unrequited longing. I think perhaps he’s humming ska songs from the 1980s to her.

Poor Elsa. This is what comes of living in the middle of a photographic studio, without doors to keep out strangers, no storage for clothing, a ragtag group of floating sofas for the young ones to sleep upon, and three mysterious remote controls to remind her a time when she had a real house to call home.

Oh Ikea. It’s time to say goodbye to 2015, with its misty bright hopes for a world of knotty pine. 2016 has arrived with its dark bleak dystopian furniture and a bookshelf that looks like an insurance liability court case ready to happen.

IMG_1523

(As a side note, I had no idea that sleeper sofas crept out of their homes while we were at work to embrace that secret 24-hour life. It must get crowded at the bowling alley and at the local microbrewery when affordable furniture sits around, drinking lager, and sharing the stories you thought were kept secret.)

iOS Playgrounds: Where is my print output?

Nate writes: “I can’t figure out how to show console output/print in the Swift Playgrounds app for iOS.”

All print output appears in the “sidebar” to the right of the code as little pop-ups:

Screen Shot 2016-06-22 at 1.11.56 PM

Embed the viewer by tapping “Add viewer” so you don’t have to keep popping up the quick view.

The hint box shown (for example “123”, or “?”, or “abc”, etc) depends on the type of item produced. The tiny cube represents an class instance.

Screen Shot 2016-06-27 at 11.40.51 AM

Like desktop playgrounds, you can view a single value at a time or tap the embedded display to select other views like List view:

Screen Shot 2016-06-24 at 12.15.27 PM

Compilation errors appear in-line for main playground code:

http://ericasadun.com/wp-content/uploads/2016/06/Screen-Shot-2016-06-21-at-11.51.25-AM.png

Sources-based errors (which  you cannot yet fix in the app) are shown as popups. When these issues occur, debug back on  your Mac before trying again on iOS.

http://ericasadun.com/wp-content/uploads/2016/06/Screen-Shot-2016-06-21-at-11.29.05-AM-535x401.png

It’s important to remember that the iOS Playgrounds app almost never is running the same version of Swift as you are on the desktop and won’t be until both Swift 3 and iOS 10 go gold.

Want to learn more about iOS Playgrounds? Read Playground Secrets and Power Tips.

Messing with Extensions: Describing color literals for the color blind

As the latest nightly build of Swift refuses to link on my system, I put together a new source editor extension. Developing these is still about as fun as having wisdom teeth pulled (actually the dental surgery would be more fun) but I’ve learned to keep a terminal window open so I can repeatedly delete derived data between builds:

Screen Shot 2016-08-03 at 11.41.33 AM

The new extension looks for a color literal on the cursor line and uses the XKCD color library to describe it.

Explorations into the Xcode Source Editor Extensions underbelly: Part 1

Xcode source extensions are wildly exciting, surprisingly limited, and infuriatingly frustrating to work with. So I thought I’d share some experiences so you don’t have to suffer through some of my issues.

There are bunches of posts around the web on how to create extensions and I really don’t want to dupe their effort. In a nutshell, create a new Cocoa app. Then create a new macOS > Application Extension > Xcode Source Editor Extension target in that app. You’re ready to code.

If you watched the WWDC video, you’ll have seen the whole process of “run the target in Xcode and a new version of Xcode pops up with a darkened label and then you can test your extension”. I’m here to tell you that this approach is a huge steaming pile of crap doesn’t work as well as I’d hoped. What you really want to do is this:

In AppDelegate.swift of your extension/app project, add the following method. It lets you launch the app, install the latest extension and get the hell out of Dodge without using the “Xcode with the darkened label”.

func applicationDidFinishLaunching(_ aNotification: Notification) {
    let alert = NSAlert(); alert.messageText = "Extension installed! Click OK to quit."
    alert.beginSheetModal(for: window) { _ in
        exit(0)
    }
}

In your main extension Swift file (the class defined for XCSourceEditorExtensionPrincipalClass), add this. It lets you watch the OS X console and ensure that your extensions loaded the way you expected them to. Notice that I use NSLog and not print. Always use NSLog, so your output and debug info goes to the system console.

func extensionDidFinishLaunching() {
    NSLog("NAMEOFMYTARGET extensions did finish launching")
}

Set up your Info.plist in a separate editor pane or even a separate window. If you intend to create a multi-part extension (and most people will), you’ll want to build that extension incrementally and slowly add items to your XCSourceEditorCommandDefinitions dictionary. A typical entry looks like this:

Screen Shot 2016-07-21 at 10.20.38 AM

Also, don’t do what I did here. I used “sadun.ExtensionTestbed” because I know this is a throwaway. Assume you may write multiple extension groups and reverse namespace them properly, e.g. “org.sadun.ExtensionName.CommandName”.

Each time you want to test do this:

  1. Build your target.
  2. Open Products, right-click the .app file and show in Finder.
  3. Quit Xcode and run the app.
  4. Launch Xcode.
  5. Open any project that isn’t a playground because Xcode hates me and doesn’t want to properly load extensions for playgrounds. Always start with a non-playground project and *then* open a playground if you want to work with playgrounds.
  6. If the extension is greyed out (and if you follow these instructions they usually aren’t because this is the sequence for El Capitan that appears to be super reliable), check the OS X console. Look for assertion failures, XPC connection failures, and invalidated connections. If you see these, quit Xcode and relaunch. What you want to see there is the “did finish launching” log line.

I know this workflow is a super pain, especially given Apple’s promotion about in-Xcode testing without quitting and relaunching (let alone running the standalone app), but it’s transformed my source editor extension duty cycle from impossible to annoying. A huge win.

Notes:

  • Don’t “clean” your Xcode extension project while running the extension. Ooops.
  • Once the extension crashes, you need to re-run the installer app.
  • I can’t seem to grab a single cursor position, there has to be an actual selection, so my extensions for adding and removing “/// ” for doc comment markup mean you have to select a line, not just move the cursor there. Or maybe there’s a bug that’s screwing this up. I haven’t quite figured this out yet.
  • A lot of my code is super redundant: operate on all lines, operate on all selection lines, operate on selected text. I really need to re-architect a common subclassable system because the actual logic for most plugins is only a few lines or a call-out to another class.
  • Any extension that works on all lines rather than individual selections seems to be more stable in my experience.
  • My experiments trying to create interactive UI elements with extensions hasn’t been going very well, they run in the original application and not in Xcode, the window is behind xcode, they can’t be interacted with while Xcode is running, and you inevitably have to force quit something.

Screen Shot 2016-07-21 at 10.39.39 AM

Here are some things I’ve been messing with. Let me know how your extensions are going for you.

https://gist.github.com/erica/2e6cecf5fae2a206faed440539c514c4

The names of things

Last night, someone was asking what you call the things created by types. My take on the subject is this: Classes, structures, and enumerations are constructs. You create new instances by calling a constructor, even when building things that aren’t reference types.

I avoid calling reference types “objects”. I stick with instances, following the Swift Programming Language’s lead, e.g. “Use the init?(rawValue:) initializer to make an instance of an enumeration from a raw value.” and “Create an instance of a class by putting parentheses after the class name.”

A big naming challenge derives from what do you call the thing that stores a value. The Swift Programming Language has this to say: “Use let to make a constant and var to make a variable”, which is not at all helpful because you end up saying “Declare a variable or constant”, “use the variable or constant as a parameter to the function”, etc, etc.

While constants and variables are “bound symbols”, “value bindings”, or just “bindings”, those are hard names to use in writing. “Create a value binding of 5” doesn’t communicate the way “create a new variable or constant and set its value to 5” does.

This is why, I prefer to stick with variable to describe both in any indeterminate situation. Constants are really immutable variables, egregious oxymoron and all. And, as Joe Groff points out, constants are still variables according to the mathematical meaning of the term.  It’s not a great solution but nearly everyone gets it.

So unless you’re going for precision, go ahead and declare a variable to store that value. If you don’t or won’t mutate it, the compiler will remind you to mark it as a constant. Long live “let variables“. It may not be technically precise but it does communicate expressively.

 

Updating OSX beta: Lessons Learned

I wasted a lot of time yesterday and today until Mark Knopper pointed me to a solution for updating my beta by hand. Like others, my download had stalled at 151MB (of a 1+GB update) and I needed to just get the update done.

That solution thread linked to another developer forums post here. This thread contains links to manual downloads. Once you download the component pieces directly, you can move them into the stalled download in /Library/Updates, and then reboot and click Update in App Store.

I decided to complete all downloads, although some report you only have to install three of the four links. App Store sees the completed downloads, and installs and updates. I am now running Beta 2.

Some in that discussion thread have reported unstable systems after performing a manual upgrade. “I may have jinxed myself by asking, but after attempting to apply the packages willy nilly, it seems that my environment (16A201w on pro 3,1) is very unstable.  Safari is now crashing all the time.”

My A/C is broken and the repair person is about to arrive so I won’t have time to test my upgrade until later today or maybe early next week. If you do go this route, do so with extreme caution.