Swift’s Scripting Is Not Magical

Ever since Swift has debuted, there's been a bit of a fuss about how it can be used for scripting. Yes, yes it can, but so can every other language that has an interpreter, or more accurately, a binary that can do something with the input file.

In fact, we can even make such a thing for C.

Here is what our little "c script" will look like.

#!/path/to/cscript

#include <stdio.h>

int main() {
    printf("I want to be a cool kid too!\n");
}

Now, the astute among you may have noticed something… the magic SHEBANG (#!) is, well, it is currently pointing to some magic place.

I've actually created a little tool to help us out (of course it's in Swift!).

import Foundation

let path = NSProcessInfo.processInfo().arguments[1]
let code = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)

let newCode = code
    .componentsSeparatedByString("\n")
    .filter { $0.rangeOfString("#!/") == nil }
    .reduce("") { $0 + $1 + "\n" }

try newCode.writeToFile("_script.c", atomically: true, encoding: NSUTF8StringEncoding)

var task = NSTask()
task.arguments = [ "_script.c", "-o", "_script" ]
task.launchPath = "/usr/bin/clang"
task.standardOutput = NSFileHandle.fileHandleWithStandardOutput()
task.standardError = NSFileHandle.fileHandleWithStandardError()

task.launch()
task.waitUntilExit()

var script = NSTask()
script.launchPath = "_script"
script.standardOutput = NSFileHandle.fileHandleWithStandardOutput()
script.standardError = NSFileHandle.fileHandleWithStandardError()
script.launch()
script.waitUntilExit()

try NSFileManager.defaultManager().removeItemAtPath("_script.c")
try NSFileManager.defaultManager().removeItemAtPath("_script")

First, compile that Swift code into an executable cscript. Next, modify the #! reference in your C source to point to this new cscript tool. Finally, be sure to chmod +x on the

"c script" file.

Then, it's simply a matter of running it like any other script:

> ./script.c
I want to be a cool kid too!

Anyhow, I just wanted to point out that this is not some black-magic that Swift is doing; it is simply a by-product of the Swift REPL environment. This is just one of the great things about our lovely OS X being backed by a unixy foundation.

Swift’s Scripting Is Not Magical