Archive for the ‘Tricks of the Trade’ Category

“mint” (a simple SwiftPM installer) has improved my command line life

SwiftPM’s lack of an easy install feature has long been an issue of mine and for other people too. As the linked forums thread suggests, to accomplish this for a general audience requires some careful thinking: adding to /usr/local/bin is not always the best solution for every user.

Still, it’s a feature whose absence is notable. To fill the gap, I’ve discovered Yonas Kolb’s mint. Thank you to Leo Dion, who introduced this to me. It is ridiculously simple to use. Could it get easier than mint install erica/now? Admittedly my github id is short and so is my project name, but I think my point stands…

Yesterday, I hastily added a SwiftPM project to remind so it too could be installed via mint. Suddenly, adding the project specification is no longer an afterthought but a driving feature. It’s made SwiftPM support far more valuable to me for executables.

Make sure you name your primary file main.swift, your product to .executable, and if you’re developing in Xcode, override your path to point to the Xcode-project-style folder for the source files, usually the same name as the project itself. I mention this because Xcode by default (File > New > Swift Package) builds library projects, not executable ones. At the command-line use swift package init --type executable.

// swift-tools-version:5.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "remind",
    platforms: [
        .macOS(.v10_12)
    ],
    products: [
        .executable(
            name: "remind",
            targets: ["remind"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser", from: "0.0.6"),
    ],
    targets: [
        .target(
            name: "remind",
            dependencies: [.product(name: "ArgumentParser", package: "swift-argument-parser")],
            path: "remind/"
        ),
    ],
    swiftLanguageVersions: [
        .v5
    ]
)

As for mint itself, you can build it or install it via HomeBrew: brew install mint.

If you have any suggestions on how I can improve my SwiftPM work, better integrate tagging, or any other tips, please let me know. Thanks!

Broken App Store downloads on Mojave: We could not complete your purchase

This has been happening to a lot of people recently. You open App Store and try to update apps or download new ones. Instead:

And if you have 48 apps to update, you have to click OK 48 times. Argh.

I spent nearly two hours with Apple yesterday trying to resolve.

Instead, I should have just tweeted because when I did Bas Broek had the answer almost immediately:

I had already rebooted, reset NVRAM/PRAM, cleaned out my Application Support for the App Store, and, get this, at the advice of Apple itself, reinstalled freaking Mojave to try to resolve it.

What a waste of time.

I hope this may come up in someone’s Google search to save them time.

  1. Quit App Store
  2. At the terminal: open $TMPDIR/../C/com.apple.appstore/
  3. In Finder: trash everything in that folder including any pending updates / stuck items.
  4. Relaunch App Store
  5. Done

Update: Gwynne Raskind adds: “$TMPDIR/../C is confstr(_CS_DARWIN_USER_CACHE_DIR)”.

So you’re going to teach remotely…

Remote meetings and teaching are an unfortunate necessity of the times. For those of us already using these platforms in positive ways, perhaps we can share some lessons on how to enhance your toolset.I thought I’d put together a quick post to address some of the ways things the classroom experience changes and suggest some technology support  for online classes.

I apologize for the stream of thought and incompleteness of this post. I wanted to put something out there right away. I’ll try to add, edit, and revise when time allows.

All Cameras On

I found the biggest struggle was my inability to wander through the classroom, peek over shoulders, and talk quietly to individual participants. I’m a walker and the online classroom is very much one of staying still.

My first rule is all cameras on with a further all cameras on faces. People are often uncomfortable with this, either switching their cameras off or pointing them up to the ceiling, essentially isolating themselves as students in a way they cannot do in a normal classroom, even by sitting at the very back with a phone in their lap. Push back and be insistent.

This rule goes a long way towards bringing the classroom together and making up for the fact that so much of the teaching experience is limited to a single viewpoint. The teleconferencing Zoom site offers a camera grid feature, which displays all participants at once (although not necessarily on the same screen, you will have to page through for large gatherings). This feature is especially important when you give in-class exercises, allowing you to keep track of the emotional temperature and find students who may be struggling.

Unfortunately, Zoom does provide an equivalent “screen peek”, so you cannot look over shoulders. Each screen must be shared and viewed individually.

As you teach, make sure you encourage participation, even more than you would in a normal classroom as there is always a danger of getting lost in your monotone without the immediate ability to “read the room” as you teach. Be extra conversational with give and take, much more than you would in a traditional class or seminar. This helps offset the technology and creates a warmth and inclusivity that otherwise would be missing.

Take Breaks

If you’re teaching extended classes, workshops, or labs, make sure to offer regular breaks to stretch and hit the bathroom. Put a timer onscreen. Most search engines allow you to enter “5 minute timer” and produce that timer for you automatically. Teaching, even remotely, is much more physically active a task than learning so remember your student’s endurance will be less than yours.

Prepare

Create a preflight list to ensure you’ve hit all the setup points before you go live teaching, including testing your camera and microphone and cleaning up your teaching platform. Don’t overshare. Depersonalize your desktop and your workspace.

Where possible, use a second unshared screen for teaching notes, outlines, and coordination. It’s far easier to lose track of time and go on tangents in a remote classroom because of the immediacy of the face-to-face conversation. Make sure you know what time it is, and what you have to cover in your lesson plan.

Have on hand a list of teaching objectives, scripts for live coding demos, working and starting code configurations. Don’t forget wrap-ups, next steps, and so forth. If you can, rehearse before you teach.

  • GitHub Place shareable starting source on GitHub or another publicly available site so students can follow along with minimal setup time. I use GitHub’s gist a lot.
  • Snippetty: Minimize typing with Snippetty. This menu-bar-sourced utility collects, orders, and offers the code or text snippets you’ll need during your session. Snippetty also lets you add presenter notes to those snippets. The less you type directly, the fewer typos you’ll encounter directly, and you limit long pauses during your lesson.
  • Snippety is end-of-life’d, sadly. I love this tool.

Display Tools

When displaying slides, whether from a second screen or a tablet, use the presenter notes feature to remind yourself of important topics.

A highlighting tool such as ScreenBrush (ScreenBrush for Mac and ScreenBrush for iOS) is great for circling, underlining, and drawing arrows to onscreen information.

I’m particularly fond of LargeType from Gold Mountain Software, which enables you to emphasize text or code at a readable huge size. This is a great way to call out key information. I’ve customized System Preferences > Keyboard > Shortcuts > Services > Text > LargeType to add a custom keyboard combination to perform selection enlargement without using menus. I currently have it set to Command-Control-Option-L, but you can pick whatever keyboard shortcut best works for you.

Don’t forget that your screen will be hard to read. macOS’s accessibility features enable you to use the mouse, trackpad, and keyboard to zoom parts of the screen. This allows you to zoom in on code and other important details that could be missed by showing an entire large screen. The zoom centers around your cursor by default, so it tracks your interest point and allows that field of vision to be shared with others. Visit System Preferences > Accessibility > Zoom to set your preferences

Demoing

Reflector 3 wirelessly mirrors an iOS screen, enabling you to load, launch, and demo apps from your deployment device. I also use Reflector 3 as a wireless screen-mirroring app from my iOS device.

If you don’t mind being tethered, QuickTime allows you to present your device screen for a connected iOS device.

Whiteboarding

On my iPad, I use Linea Sketchto draw. It has a present mode that hides all the normal iOS app details and just shows a plain whiteboard drawing screen. I recently upgraded to a lastest-gen iPad mini with 1st gen pencil and that has been fantastic. I also got good results before my upgrade with the rubber tipped Heiyo stylus. Use a firm stylus for writing. Most stylii are designed for drawing and to simulate brushes.  The Heiyo doesn’t scratch the screen like the metal-tipped ones, is easy to charge (microUSB), and works with older iPads.

Zoom

Zoom offers a number of great built-in features for questions, messaging, raising hands, and so forth. I particularly like using it to know when students are done with a particular task: clear the participant list and have them use a check mark or thumbs up when they have finished. This way you can continue the class without having to wait a full number of minutes.

The same tool is great for “Who thinks that X is Y” style questions. Always encourage the student to answer before looking at what others have voted.

If you can, supplement Zoom with Slack. It’s much better for creating a record of q&a (start a thread specifically for that), and for when you need to distribute text/code from teacher to students. In terms of q&a, a great approach is to allow 3-5 minutes where everyone can add their questions and then you review the questions and choose which ones you wish to answer. I got this technique from Andrew Madsen and it’s terrific. He also recommends using sli.do for audience participation.

Taking charge of those xips

Apple adopted the digitally-signed xip format for Xcode downloads a few years ago. It’s basically a signed version of zip archives. Most commonly, you download a xip and double-click. Archive Utility will open the file, verify its signature, and expand its contents.

In its default settings, Archive Utility always expands files to the same folder you download to. With Xcode, this is a big pain as moving the app with its thousands and thousands of tiny subfiles and embedded executables takes forever. Alternatively, moving the xip file from one location on your system to another can be painfully slow.

Fortunately, Archive Utility does allow you to specify where to unpack. Launch the Application using spotlight (or /System/Library/CoreServices/Applications/Archive Utility.app) and open preferences.

Although there’s no “Ask” option for “Save expanded files”, you can select where you want items to be stored using “into” from the pop-up:

Once set, you have to unset it for general use, because the location persists between launches. This is, needless to say, a big pain when you use archives for non-Xcode purposes on a regular basis:

Fortunately, you can unxip more effectively by using the command-line xip utility located in /usr/bin/xip without having to mess with Archive Utility or its preferences:

% xip
Usage: xip [options] --sign <identity> <input-file> [ <input-file> ... ] <output-xip-file>

Usage: xip --expand <input-file>

99.9% of everything you do with xip is that last “Usage” example. Still, as xip doesn’t offer a --help option, if you want to know what those interesting [options] are, you’ll need to read the man page (man xip). I prefer to open man pages in Preview instead of the command line, using this little trick:

man -t xip | open -f -a /System/Applications/Preview.app

Notice two things here:

  • First, the -t flag tells man to use the Groff typesetter (no relation) to format the page to postscript. This presents as a PDF in Preview. (Specifically, it uses /usr/bin/groff -Tps -mandoc -c if that kind of detail intrigues you.)
  • Second, the path for Preview has changed in Catalina to /System/Applications. If you want to do this on Mojave or earlier, adjust the path accordingly.

(Isn’t that a neat way to view man pages?)

While the man page suggests you can sign your own xip archives and provide your own identities, don’t bother. This format is exclusive to Apple, starting  from macOS Sierra. Only xip archives signed by Apple can be expanded in modern macOS releases. (See Tech note TN 2206 for details.)

Since --expand cannot be used with any other arguments, hop over to /Applications, and expand from there:

% cd /Applications/
% time xip --expand /Volumes/Kiku/xips/Xcode_11.2.1.xip 

Adding the time command at the start of the line lets you know how long it took to unxip, which is deeply satisfying to those of pedantic bent like myself. For those playing along, it was

xip: expanded items from "/Volumes/Kiku/xips/Xcode_11.2.1.xip"
1109.625u 275.408s 10:58.85 210.2%	0+0k 0+0io 167pf+0w

Update:

Xcode: Basics of the four-block wonder

The official name is “Navigate to Related Items” but to me, it’s the four block wonder, a menu button that sits at the top left of the Xcode editor. With this menu, you can hop between file counterparts (for example, .m/.h, or .swift/generated interface, which is what a lot of people use it for). But there’s so much more.

Set the cursor on a type, and you can view or navigate its superclass, subclasses, or siblings, as well as the protocols, extensions, and categories it connects to. A single click navigates you to the interface or implementation in question:

Use the cursor to establish the context for the menu, otherwise you’ll only see a smaller subset menu options, such as recent files. The callers option shows you your clients, and callees the items your code is calling — all specific to the current cursor context.

One of my favorite tools in the four-block menu is Generated Interfaces, which allows you to view an item’s Swift interface or see how it translates to Objective-C. For example, if you use an obvious preposition label, the ObjC generated interface subsumes it into its selector:

With this, you don’t have to wonder if your selector is specified right and you don’t have to override the selector with objc. You just look up the definition and you’re good to call.

In addition to contextual helpers, the four-block lets you select recently viewed files and, when using version control, recent files that have been locally modified and not yet committed (basically the ones showing the “M”-for-modified).

The four little squares may be tiny but it is a powerful tool in your Xcode arsenal.

Update: Lilly reminds me that you can bind the related items menu. I have mine bound to ^1 but I don’t remember if that’s something I did or something that is default. If you want to add or change, visit Preferences > Key Bindings and search for “related”.

How I got Rust working in Xcode

A while ago, I posted about how I set up Xcode to work with Python. Yesterday, I was taking a class on Rust and decided to use my friendly neighborhood (sp)IDE(rman) coding environment, namely Xcode.

I’m not going to say it was a stunning success but there was enough interest that I thought I’d share the steps so you too could embrace Rust through Xcode.

Install Rust. You start, as one does, by installing Rust. Hop over to https://www.rust-lang.org/tools/install to grab a copy of the tools. They install to ~/.cargo, for whatever reason. I put a link in to / usr/local/bin.

Create a Project. Create an external build system Xcode project by choosing File > New > Project > Cross-platform > External Build System > Next. Enter a product name (I called mine “Rust” because that’s exactly how creative I am.) and set your build tool (in my case, /usr/local/bin/rustc because of the link). Save it somewhere convenient.

Create a source file. Apparently “rs” (rust source?) is the proper extension. I went with “test” as my name. File > New > Empty > test.rs

fn main() {
    println!("hello world");
}

Don’t forget to add some code.

Compile. Edit your scheme.  Choose Run > Info > Build Executable > Other and select your compiler. Adding it to /usr/local/bin made it easier to select rustc for me. Then uncheck Debug executable because you’re not debugging the Rust compiler.

At this point you can click Run and you’ll see the standard option message because you haven’t specified what it should run.

Back in the scheme editor select Run > Arguments and add the source file and output file. Unfortunately, I could not get this to work with SRCROOT at all, so here it is in all its glory with complete paths.

The Pre-action removes any build product from a previous run:

So here we are. With luck, it compiles. If not, the errors appear in pretty horrible form in the Xcode console, where curses is what we do, not how the console interprets pretty text output.

You can get slightly less horrible feedback by adding the launch argument: –error-format=json

Yeah, it’s wordy but it’s slightly less awful.

Pick a path. Unlike python, rust is just a compiler. If you build, and then add a step execute, the execution output (unlike compiler errors) will not normally print at the Xcode console. The challenge is to get that information in some form where you can access it.

At first I went with a little post-action osascript and threw up the output in a separate window:

But I really wanted to make it work with the console So back I went to Applescripting. Instead of rustc, I changed my build tool to osascript:

I added this instead to my run scheme arguments.

Yep, I’m using osascript to run a shell script that just compiles with rust and then runs it, passing the output through back to Xcode.

I know this is bad. I know I should be ashamed. I hang my head.

But you know what? It works. Stray osascript-crud and all:

I’m not sure how much this makes me a programming outcast but it was kind of fun to figure out how far I could push my beloved enemy Xcode.

SwiftUI: Modified Content, Type Erasure, and Type Debugging

When working with declarative views, you should be able to reach for a full tool suite of functional application. In a typesafe language like Swift, things can prove more difficult than you’d might first think. Consider the following code:

What is core‘s type? It isn’t Text. It’s actually an application of modified content, specifically Text passed through a rotation effect:

Just add a background color and a shadow and the type jumps to this:

You might ask: why is this a problem? After all, Swift is doing all the heavy lifting, right? In my case, the answer lies in my struggle to incorporate this core image into a multi-stage bit of text art using reduce. Paul Hudson tweeted a step-by-step approach to this and I was sure I could make it simpler and more elegant.

And that’s where I started throwing myself against what at first seemed like an impenetrable wall for a couple of hours. Between SwiftUI’s stroke-style Dysarthria error messages and the typesafe system, my attempt at creating a solution along these lines felt doomed:

[Color.red, .orange, .yellow, .green, .blue, .purple].reduce(core) { view, color in
  view.padding()
    .background(color)
    .rotationEffect(theta)
}

The code wouldn’t compile and the error messages couldn’t tell me why. The problem? Each stage created a new layer of modified content, changing the type and rendering reduce  unable to do the work. It was only with the help of some deep-dives into the docs and advice from colleagues that I was able to arrive at a solution.

Type erasure, using SwiftUI’s AnyView struct enables you to change the type of a given view, destroying the nested hierarchy. Importantly, it creates a single type, allowing a reduce operation to proceed.

At first, I used AnyView the way you’d typecast in Swift, namely:

AnyView(view.padding()
  .background(color)
  .rotationEffect(theta))

But I hated that. It sticks out as so Un-SwiftUI-y, with the parentheses spanning multiple lines and throwing off the clear logical flow. If you’re going to go fluent, just go fluent. So, eventually, I decided to create a View type extension to handle this:

extension View {
  /// Returns a type-erased version of the view.
  public var typeErased: AnyView { AnyView(self) }
}

The result looks, instead, like this:

view.padding()
  .background(color)
  .rotationEffect(Angle(radians: .pi / 6))
  .typeErased

And yes, I went with a property and not a function as I felt this was expressing a core characteristic inherent to each View. I can probably argue it the other way as well.

From there, it wasn’t much of a leap to ask “what other fluent interface tricks can I apply”, and I ended up putting together this little View extensions for inline peeks:

extension View {
    /// Passes-through the view with debugging output
  public func passthrough() -> Self {
    print("\(Self.self): \(self)")
    return self
  }
}

This prints out an instance’s type and a rendering of the instance, which will vary depending on whether there’s a custom representation, passing the actual instance through to whatever the next stage of chaining is. I don’t use it much but when I do, it’s been pretty handy at taking a peek where Xcode’s normal QuickLook features hit the edge.

In any case, I thought I’d share these in case they’re of use to anyone else. Drop me a note or a tweet or a comment if they help. Cheers!

Update: It suddenly occurred to me that I could make this a lot more general:

extension View {
  /// Passes-through the view with customizable side effects
  public func passthrough(applying closure: (_ instance: Self) -> ()) -> Self {
    closure(self)
    return self
  }
}

Isn’t that nicer? The equivalent is now:

struct MyView: View {
  var body: some View {
    [Color.red, .orange, .yellow, .green, .blue, .purple]
      .reduce(Text("👭")
        .font(.largeTitle)
        .rotationEffect(Angle(radians: .pi))
        .typeErased)
      { view, color in
        view.padding()
          .background(color)
          .rotationEffect(Angle(radians: .pi / 6))
          .passthrough { print("\(type(of: $0)), \($0)") }
          .typeErased
    }
  }
}

And I can put any behavior in from printouts to timing to any other side effect I desire. To all the functional purists out there, I sincerely apologize. 🙂

ISO-8601, YYYY, yyyy, and why your year may be wrong

The end of the year is rolling around and it’s time to remind everyone about that yyyy works the way you think it does and YYYY does not. Here’s a quick example to start:

Just because you test a format quickly with the current date and get back the result you expect, does not mean you’ve constructed your date format correctly.

Speaking of which, BJ Homer points out that you can just use “y”, as “yyyy” pads to 4 digits which doesn’t usually matter but isn’t always needed. Olivier Halligon adds, further, that not all calendars use 4 digit years. “For example the Japanese start a new era every time the emperor changes, resetting to year 1 in that era; we’re currently in year Heisei 30.”

To quote The Dave™: “Nooooooo…. Please use “y”, not “yyyy”. “yyyy” zero-pads years that aren’t four digits, and there are multiple calendars w/ 2 or 3-digits years (Japanese, Chinese, Republic of China). “y” is the natural length of the year: “30” for Japanese cal, “2018” for Gregorian, etc”

What you’re actually seeing with “Dec 24, 2017” is the first day of the last full week of the preceding year. It doesn’t matter what numbers you plug into the month (“MM”) or day (“dd”). The presence of YYYY in the date format without its expected supporting information reduces to “start of year, go back one week, report the first day”. (I’ll explain this more in just a little bit.)

Here are some examples, which you can check from the command line using the cal utility:

As Apple’s 2014-era date formatting guide points out:

A common mistake is to use YYYY. yyyy specifies the calendar year whereas YYYY specifies the year (of “Week of Year”), used in the ISO year-week calendar. In most cases, yyyy and YYYY yield the same number, however they may be different. Typically you should use the calendar year.

Unicode.org’s Unicode Technical Standard #35, Date Format Patterns goes into a little more depth:

[“Y” is] Year (in “Week of Year” based calendars). This year designation is used in ISO year-week calendar as defined by ISO 8601, but can be used in non-Gregorian based calendar systems where week date processing is desired. May not always be the same value as calendar year.

ISO 8601 uses a 4-digit year (YYYY) for “week of year” calendars from 0000 to 9999. If you’re into trivia, the years before 1583 are technically excluded except by special agreement between sending and receiving parties.

Anyway, if you’re going to use YYYY formats, you’ll want to use additional format elements that support “week of year” date construction. For example, consider the calendar for this upcoming January, which starts on Tuesday the 1st:

    January 2019      
Su Mo Tu We Th Fr Sa  
       1  2  3  4  5  
 6  7  8  9 10 11 12  
13 14 15 16 17 18 19  
20 21 22 23 24 25 26  
27 28 29 30 31

This year, January first can be considered as the first week of 2019 or the 53rd week of 2018, as the weeks overlap in the middle. Using e (the numeric day of the week) and ww (the ordinal week to count from), you can represent both dates correctly using the oddball YYYY formatting token.

Here are examples that use the week-of-year approach counting from both 2018 and 2019:

As you can see from this, when you use YYYY and do not supply an ordinal week or day, they both default to zero, which is why you get the behavior of the zeroth week (that is, the week before the first week) on the zeroth day (also, the first day of that week) for that calendar year, which is the week before the first week that overlaps the stated year. This explains the results of all those otherwise random late-December dates from earlier.

ISO 8601 should be updated in a few months, with a release somewhere around February.

From what I can tell, the first part revises the current standard and the second expands it. The only freely accessible human-viewable material I could find were the five-page TOC previews for 8601-1 and 8601-2.

(Hat tip: Thanks, Robin Malhotra)

Better table processing

Thanks to Andy Lester:

#! /bin/sh

# Process pasteboard contents to md table. Thanks, Andy Lester.
# Copy table from Numbers or other tab-delimited spreadsheet.
pbpaste | perl -le'$_=<>;&x;s/[^|]/-/g;&x;for(<>){&x}sub x{chomp;s/\t/|/g;print"|$_|";}' | pbcopy

# Done.
echo "Styled pasteboard to table"