Swift for Scripting
So Swift 1.0 has come and gone, and Swift 1.1 is just around the corner. As we’re getting closer to a more stable shape for the language, I’m interested in its potential as a scripting language for OS X. In case you missed it, Swift can be used as a scripting language by invoking it via the good old-fashioned shebang syntax:
#!/usr/bin/env xcrun swift import Foundation … // do the things
However, being able to invoke it and being able to do something useful with it are two very different issues. Swift is not yet ready for useful scripting — but I think it has the potential.
• • • • •
Brevity is the soul of scripting. There are a few things any scripting language needs to get right, to support out-of-the-box in a solid and reasonably intuitive sense. They are:
- File I/O (including file system traversal, permissions, and of course reading and writing)
- String manipulation (including sensible methods for trimming strings, as well as strong regular expression support)
- Option parsing — because any non-trivial script will take options
At this point, Swift is good at none of these. String manipulation is reasonably close, minus the complicated regex syntax, but file I/O is shackled to the NSFileManager API, which is powerful but insanely verbose, and Objective-C option parsing libraries are also not notable for pithiness.
So a good place to start to make Swift usable is to write a good library to support strings (ExSwift is already reasonable), a good library to do file I/O (preferably with strong defaults for line-by-line parsing of a file), and a good library for option parsing. With that, the foundation is laid.
• • • • •
That’s the language foundation. If Swift is to take off as a scripting language, it also needs infrastructure: a good framework management system. Apple does provide strong support for frameworks, with
/Library/Frameworks being reserved for third-party frameworks that the compiler automatically picks up. It also provides versioning guidelines that are very close to semantic versioning, minus the obligation that the main version identifier be a number.
However, this is short of what’s needed. What we really need is Homebrew for OS X modules. I would expect that CocoaPods is a better starting point than Homebrew for actual implementation purposes, of course, since it already addresses a similar problem for applications, but the general idea is there.
Irrespective of how it works, though, it brings up the problem of proper versioning. The most consistent and well-defined versioning scheme I’ve come across is Semantic Versioning, which is also the system used by CocoaPods. If the tools quickly emerge to support this standard, a lot of heartache, confusion, and dependency hell is going to be easily avoidable going forward.
Good versioning tools should support two main things:
- Consistent bumping of versions.
- Automated API diffing that determines whether a bump between two points in code should be a major, minor, or patch bump.
This would allow automated versioning, helping to reduce human error, and allowing versions to live up to their contract more consistently.
• • • • •
With this in mind, over the past few weeks, I’ve worked on two libraries that help a little bit with Swift’s command-line scripting.
The first and most complete is SemverKit. It’s a library for parsing version strings according to the semantic versioning spec, with additional support for bumping versions in a consistent manner. Applications include:
- Dependency resolution
- Automated versioning (coupled with some API diff tools)
- Stabilization of CocoaPod libraries (this can be useful if you use internal libraries with alpha/beta versions)
SemverKit is ready for general usage; it implements version equality and comparison in a spec-compliant manner and supports metadata as well.
The second, which is less feature-complete, is OptionKit, a library for parsing command-line options. It supports the most common scenarios (flags, named commands, required parameters), but does not have any advanced features (sub-parsers, for instance). Still, I believe it can be taken out for a spin, and will serve basic needs. As more advanced uses are needed, it can expand.
Incidentally, both of these depend on custom implementations of the
Result object, which has been implemented many times, most notably by Rob Napier’s LlamaKit. LlamaKit is a great example of what should be one of the foundational libraries of all Swift — including command-line Swift. It could then live in
/Library/Frameworks and would be easily imported into a project.
• • • • •
So there we have it. I believe Swift is an excellent candidate for scripting on OS X, being that it’s naturally pithier than Objective-C, and has strong type inferencing that reduces typing overhead. In addition, it’s more productive to be able to script and write application code in the same language.
However, we are not there yet. There is still a lot of work to do to set up the plumbing. I hope OptionKit and SemverKit help a little along the way. How about it? Want to join the fun?