Archive for the ‘Tricks of the Trade’ Category

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"

Converting spreadsheet data to Markdown

I find it’s a lot easier to prepare a table with Numbers than by hand. I was using this today and thought I’d share the how-to.

Step 1: Select the material you want to table-ize.

Step 2: Paste it into text edit. Numbers uses tab delimiters (at least it does for me).

Step 3: Use find/replace to replace all tabs with a vertical pipe symbol (|). Copy any of your tabs to populate the find field.

Step 4: Use find/replace to replace all newlines with the sequence pipe symbol – newline -pipe symbol. Copy a newline from your text to the find field and in the replace field type |, then paste the newline again, and then type | again.

Step 5: Add pipe signs to the start and end of your file. Before:

After:

Step 6: Duplicate the first line and replace all text between bars with dashes:

Step 7: If you have an empty left-top-corner like I do, add at least 3 dashes to the 2nd line between the first set of pipes:

And you’re done.

Pushing the gist envelope: gists with pics and zips

People often don’t realize how powerful GitHub’s gist pasting service is. It’s more than just a “paste” site. Gist offers a full version control system extension to GitHub’s main site. I’ve been working on developing version control training materials and gist is a great way to introduce the fundamentals.

Many gist users know that the site offers you pushbutton convenience to paste one or more files. You can create open gists and “secret” ones hidden from public view. Gist also lets you fork, revise, and explore diffs between revisions.

For example, you can work in groups when writing. Collaborators can fork and make changes to offer content feedback. You can then use diffs to see what edits were made.

Here are some diffs from a recent Raw String proposal I worked on:

And this is the corresponding “rich diff”, which is slightly prettier:

And there’s a lot more you can do with gist. That’s because gists, as version control repositories, can be cloned to your computer, modified, and pushed back to GitHub. This means you can, for example, set up albums of pictures or host an easy-to-distribute zip file.

Each gist URL is a repository’s address:

git clone https://gist.github.com/erica/7cd24c6ab2f737735a9ab2b95628c549

As a gist’s owner, you have commit privileges, allowing you to edit your gist from your computer.

The command line enables you to add binary files that you can’t from the web interface. I grabbed a bunch of kitten pictures from Pexels and added them to my gist. A nice way to create simple albums:

If you click “Download ZIP” at the top right, GitHub zips up the repository contents (in this case five kitten PNGs) and copies them to your computer. This is not cloning; the zip file just stores the source files, not the full git repo.

It’s just as easy to host an archive file. When you have an Xcode project or playground that you need to share, Gist provides a great intermediate service alternative to iCloud or Dropbox. If you need privacy, use the “secret gist”  button when creating the gist.

This isn’t, of course, the end of what you can do with gists. Because each gist is a git repository, you can perform all the same commands you would in any git repo. Gist, of course, has a limited interface, so you won’t be able to, for example, switch between branches from the gist website. On the other hand, you can perform other tasks that don’t depend on a GitHub UI like listing diffs:

% git diff cb9271da5070f11602d3ab436a05fb9705409fd2
diff --git a/raw.md b/raw.md
index 8ed7306..ea4b5ed 100644
--- a/raw.md
+++ b/raw.md
@@ -104,9 +104,8 @@ Escaping hinders readability and interferes with inspection, especially in the l
 
 ### Candidates
 
-A good candidate for raw strings:
+A good candidate for raw strings is non-trivial and is burdened by escaping because it:
 
-* Is non-trivial.
 * Is obscured by escaping. Escaping actively harms code review and validation.
 * Is already escaped. Escaped material should not be pre-interpreted by the compiler.
 * Requires easy transport between source and code in both directions, whether for testing or just updating source.

I think GitHub’s gists are pretty awesome. And now, at least for me, they’ve gone from handy but mindless pastes to something really special.

Do you have a special way to use gists? I’d love to hear about unconventional ways to use this utility site to push boundaries and introduce new functionality. Drop a comment or an email and let me know.

Forcing Compiler Errors in Swift

Thanks to SE-0196, Swift 4.2 introduces #warning() and #error() compiler directives. These will allow you to incorporate diagnostic messages and emit errors during compilation. Here are some examples from the proposal, which has already been accepted and implemented:

#warning("this is incomplete")

#if MY_BUILD_CONFIG && MY_OTHER_BUILD_CONFIG
  #error("MY_BUILD_CONFIG and MY_OTHER_BUILD_CONFIG cannot both be set")
#endif

The #error example uses conditional compilation flags (set with a -D option) to check whether conflicting configurations have been established for the build.

I’ve already written extensively about my dislike for screaming snake case (THINGS_LIKE_THIS) in Swift. Inevitably, it seems, devs use screaming snake case for their conditional compilation flags, whether MY_BUILD_CONFIGMY_OTHER_BUILD_CONFIG, or DEBUG. Although an industry standard, it feels like a clash with Swift’s aesthetics.

I’ve also written about my proposal for detecting debug conditions without having to supply an explicit DEBUG condition flag, so I’ll also leave that topic to the side for now. You can click on the link for more.

Back to topic, Swift’s newly adopted #error and #warning directives represents a big step up from current practices, which often rely on run-time rather than compile-time feedback.

#if !DEBUG
fatalError("This code is incomplete. Please fix before release.")
#endif

The unindented style in this snippet is now Swift default, avoiding minor doom pyramids for conditional compilation blocks. Even unindented, surrounding code with those conditional blocks is vertically expansive and subjectively ugly. To counter this, some coders have come up with in-line ways to force compilation (not run-time) errors with minimal condition blocks and a more succinct point-of-use approach.

Here’s an example I discovered from John Estropia. (He, in turn, cribbed it from one of  his co-workers.) He uses conditional compilation to set a TODO or FIXME (or whatever) typealias then uses it in-line at points where a debug build should compile and release builds should error:

#if DEBUG 
internal typealias TODO<T> = T
#endif

print("Remove this later") as TODO

It’s clever. Scoping the TODO typealias to debug builds allows lines annotated with as TODO to throw errors during release builds. This ensures compile-time feedback at all points where a TODO cast is performed:

error: ManyWays.playground:5:31: error: use of undeclared type 'TODO'
print("Remove this later") as TODO

It’s not beautiful but it’s effective. It carries information about the call site location and the message you want to emit. If I were applying this hack, I’d probably build an actual todo function rather than using the casting-gotcha. In the following example, I went with an upper camel case name to make the call look more directive-y and less like a standard global function. However, I drew the line at snake case:

#if DEBUG
internal enum IssueLevel {
    case
    mildImportance,
    moderateImportance,
    highImportance,
    criticalImportance
}

internal func ToDo(_ level: IssueLevel, _ string: String) {}
#endif

// The point of use offers a compilation error,
// a note, and a priority level
ToDo(.highImportance, "Remove this later")

// error: ManyWays.playground:13:1: error: use of unresolved identifier 'ToDo'
// ToDo(.highImportance, "Remove this later")

The nicest bit is that toggling from debug compilation to release is completely automatic and centralized to a single #if check.  It’s a fascinating approach if adopted consistently and ensures that all compilation message notes like this must be resolved and removed before release.

Right now, Swift does not support a #message directive, which performs a similar tasks. As many shops treat warnings as errors, they cannot establish a nuanced distinction between the two. If #warning were a thing, you could use #message to issue exactly this kind of “fix me” feedback. A further refinement, #messageOrDie (or something like that, because naming is hard)  could message for debug builds and error for release, going by whether assert statements would or would not fire.

Dave DeLong offers another approach for structural project semantics. His introduces a Fatal type to provide runtime cues for common development outcomes including notImplemented(), unreachable(), and mustOverride(). Nothing says “you need to remember to implement this” better than a spectacular runtime crash that explains itself with full position and function context. Another cue, brilliantly named silenceXcode() allows you to add methods that you never intend to implement and which should error if ever called.

There’s still space in Swift for expanding this metadevelopment support. I wouldn’t mind seeing both approaches added to the language: one for compile time (like #messageOrDie) and another for run time (like Fatal‘s namespaced static error members).

What do you think of these? And what parts of the metadevelopment process (like macros) are still MIA for you in Swift? Let me know. I’m curious to hear what else could be better established to support your development.