Skip to content

Instantly share code, notes, and snippets.

@loganwright
Last active May 15, 2016 05:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loganwright/777d7c22ecce4009651f93d7afc23a30 to your computer and use it in GitHub Desktop.
Save loganwright/777d7c22ecce4009651f93d7afc23a30 to your computer and use it in GitHub Desktop.
A swift script to make dealing with new swift scripts a little easier :)
#!/usr/bin/env swift
#if os(OSX)
import Darwin
#else
import Glibc
#endif
import Foundation
// MARK: Failure
@noreturn func fail(_ msg: String) {
print("Error: \(msg)")
exit(1)
}
func run(_ command: String, allowFailure: Bool = false) {
let result = system(command)
if allowFailure { return }
else if result != 0 {
fail("error code \(result)")
}
}
func passes(_ command: String) -> Bool {
return system(command) == 0
}
func getInput() -> String {
return readLine(strippingNewline: true) ?? ""
}
func commandExists(_ command: String) -> Bool {
return system("hash \(command) 2>/dev/null") == 0
}
// MARK: Command
protocol Command {
static var description: String { get }
static func execute(with args: [String], in directory: String)
}
extension Command {
static var description: String {
return ""
}
}
// MARK: Tree
var commandTree: [String : Command.Type] = [:]
// MARK: Help
struct Help: Command {
static func execute(with args: [String], in directory: String) {
var help = "Available Commands:\n\n"
help += commandTree
.map { key, val in "\t\(key): \(val.description)"}
.joined(separator: "\n")
help += "\n"
print(help)
}
}
commandTree["help"] = Help.self
// MARK: Custom Commands
struct New: Command {
static func execute(with args: [String], in directory: String) {
guard commandExists("wget") else {
fail("wget required to create new script. Recommended to install through Homebrew: http://brew.sh/")
}
guard args.count == 1, let name = args.first else {
fail("Unexpected arguments: \(args). Expected single argument as name of script")
}
let templateUrl = "https://gist.githubusercontent.com/LoganWright/899acec46512a966653206f5dcc27d2a/raw/042f592b24a27f317d7c773fb750525e0a56bb98/swift-script-template.swift"
run("wget \(templateUrl) -O \(name)")
print("Successfully created swift script \(name)")
print("Use the following to run your script")
print()
print("xcrun")
print("\txcrun swift ./\(name)")
print()
print("xcrun: toolchain")
print("\txcrun --toolchain swift swift ./\(name)")
print()
print("run directly")
print("\tRun only once")
print("\t\tchmod +x ./\(name)")
print("\tThen call directly after that")
print("\t\t./\(name)")
print()
print("run from bin")
print("\trun only once")
print("\t\tchmod +x ./\(name)")
print("\t\tmv ./\(name) /usr/local/bin/\(name)")
print("\tnow call directly")
print("\t\t\(name)")
print()
}
}
struct AddToBin: Command {
static func execute(with args: [String], in directory: String) {
guard args.count == 1, let file = args.first else {
fail("Unexpected arguments: \(args). Expected single argument as file of script to move")
}
guard passes("test -f \"\(file)\"") else {
fail("Unable to find file \(file)")
}
guard let extractedName = file.components(separatedBy: "/").last else {
fail("Unable to find file name")
}
print("Custom name? (press return to use \(extractedName))")
var name = ""
if let input = readLine(strippingNewline: true) where !input.isEmpty {
name = input
} else {
name = extractedName
}
run("chmod +x \(file)")
run("mv \(file) /usr/local/bin/\(name)")
}
}
// MARK: Tree
commandTree["new"] = New.self
commandTree["add-to-bin"] = AddToBin.self
// MARK: Execution
var iterator = Process.arguments.makeIterator()
guard let directory = iterator.next() else {
fail("no directory")
}
guard let commandKey = iterator.next() else {
fail("no command")
}
guard let command = commandTree[commandKey] else {
fail("command \(commandKey) doesn't exist")
}
let arguments = Array(iterator)
command.execute(with: arguments, in: directory)
@loganwright
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment