Skip to content

Commit

Permalink
Merge pull request #29 from jakeheis/swiftcli
Browse files Browse the repository at this point in the history
Use SwiftCLI
  • Loading branch information
yonaskolb authored Jun 1, 2018
2 parents 0390743 + eef3bd0 commit b540e66
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 243 deletions.
41 changes: 16 additions & 25 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/norio-nomura/Clang_C.git",
"state": {
"branch": null,
"revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e",
"version": "1.0.2"
"revision": "7b7d3eed8080d14ba39c50e29fa8c7b051bcf969",
"version": "1.0.3"
}
},
{
Expand All @@ -24,8 +24,8 @@
"repositoryURL": "https://github.com/Quick/Nimble.git",
"state": {
"branch": null,
"revision": "22800b0954c89344bb8c87f8ab93378076716fb7",
"version": "7.0.3"
"revision": "21f4fed2052cea480f5f1d2044d45aa25fdfb988",
"version": "7.1.1"
}
},
{
Expand All @@ -42,8 +42,8 @@
"repositoryURL": "https://github.com/Quick/Quick.git",
"state": {
"branch": null,
"revision": "0ff81f2c665b4381f526bd656f8708dd52a9ea2f",
"version": "1.2.0"
"revision": "3e3023569c8d4c4a0d000f58db765df53041117f",
"version": "1.3.0"
}
},
{
Expand All @@ -69,8 +69,8 @@
"repositoryURL": "https://github.com/jpsim/SourceKitten",
"state": {
"branch": null,
"revision": "e06eb730499439ae32c5fbb6f72809ebec2371fd",
"version": "0.19.1"
"revision": "7c09176766d4bbc5da377ad857953fb49510a6aa",
"version": "0.21.0"
}
},
{
Expand All @@ -83,39 +83,30 @@
}
},
{
"package": "SwiftPM",
"repositoryURL": "https://github.com/apple/swift-package-manager",
"package": "SwiftCLI",
"repositoryURL": "https://github.com/jakeheis/SwiftCLI",
"state": {
"branch": null,
"revision": "63a01220e93271dc3bf204b9e13dd1aeb2beefee",
"version": "0.2.0"
}
},
{
"package": "SwiftShell",
"repositoryURL": "https://github.com/kareman/SwiftShell.git",
"state": {
"branch": null,
"revision": "b9fd06798993153bc57cde10ee6c75ddc55c2dbd",
"version": "4.0.2"
"revision": "995f5966072bded933400bbe77ad24914f01d0c0",
"version": "5.1.1"
}
},
{
"package": "SWXMLHash",
"repositoryURL": "https://github.com/drmohundro/SWXMLHash.git",
"state": {
"branch": null,
"revision": "17d992beb3aaeda403fd35f8d5e70ab1a8124f35",
"version": "4.6.0"
"revision": "2211b35c2e0e8b08493f86ba52b26e530cabb751",
"version": "4.7.0"
}
},
{
"package": "Yams",
"repositoryURL": "https://github.com/jpsim/Yams.git",
"state": {
"branch": null,
"revision": "95f45caf07472ec78223ebada45255086a85b01a",
"version": "0.5.0"
"revision": "6652aa7b793d3c8a075db0614acb575fcaecf457",
"version": "0.7.0"
}
}
]
Expand Down
6 changes: 2 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ let package = Package(
.package(url: "https://github.com/jpsim/SourceKitten", from: "0.19.1"),
.package(url: "https://github.com/kylef/PathKit.git", from: "0.8.0"),
.package(url: "https://github.com/kylef/Spectre.git", from: "0.8.0"),
.package(url: "https://github.com/apple/swift-package-manager", from: "0.2.0"),
.package(url: "https://github.com/kareman/SwiftShell.git", from: "4.0.0"),
.package(url: "https://github.com/jakeheis/SwiftCLI", from: "5.1.0"),
],
targets: [
.target(
Expand All @@ -26,8 +25,7 @@ let package = Package(
dependencies: [
"SourceKittenFramework",
"PathKit",
"Utility",
"SwiftShell",
"SwiftCLI",
]),
.testTarget(name: "BeakTests", dependencies: [
"BeakCore",
Expand Down
18 changes: 4 additions & 14 deletions Sources/Beak/main.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import BeakCore
import Foundation
import PathKit
import Utility

do {
let options = BeakOptions()
let beak = Beak(options: options)
try beak.execute(arguments: Array(ProcessInfo.processInfo.arguments.dropFirst()))
} catch {
if error._domain == NSCocoaErrorDomain {
print("⚠️ \(error.localizedDescription)")
} else {
print("⚠️ \(error)")
}
exit(1)
}
let options = BeakOptions()
let beak = Beak(options: options)
let result = beak.execute()
exit(result)
40 changes: 12 additions & 28 deletions Sources/BeakCore/Beak.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import Basic
import Foundation
import PathKit
import SourceKittenFramework
import SwiftShell
import Utility
import SwiftCLI

public struct BeakOptions {

Expand All @@ -25,31 +21,19 @@ public class Beak {
self.options = options
}

public func execute(arguments: [String]) throws {

let parser = ArgumentParser(commandName: "beak", usage: "[--path] [subcommand]", overview: "Beak can inspect and run functions in your swift scripts")
let versionArgument = parser.add(option: "--version", shortName: "-v", kind: Bool.self, usage: "Prints the current version of Beak")
_ = parser.add(option: "--path", shortName: "-p", kind: String.self, usage: "The path to a swift file. Defaults to beak.swift", completion: .filename)

let commands = [
"list": ListCommand(options: options, parentParser: parser),
"function": FunctionCommand(options: options, parentParser: parser),
"run": RunCommand(options: options, parentParser: parser),
"edit": EditCommand(options: options, parentParser: parser),
public func execute(arguments: [String]? = nil) -> Int32 {
let cli = CLI(name: "beak", version: version, description: "Beak can inspect and run functions in your swift scripts")
cli.globalOptions.append(GlobalOptions.path)
cli.commands = [
ListCommand(),
FunctionCommand(),
RunCommand(options: options),
EditCommand(options: options)
]

let parsedArguments = try parser.parse(arguments)

if let printVersion = parsedArguments.get(versionArgument), printVersion == true {
print(version)
return
}

if let subParser = parsedArguments.subparser(parser),
let command = commands[subParser] {
try command.execute(parsedArguments: parsedArguments)
if let arguments = arguments {
return cli.go(with: arguments)
} else {
parser.printUsage(on: stdoutStream)
return cli.go()
}
}
}
17 changes: 14 additions & 3 deletions Sources/BeakCore/BeakError.swift
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import Foundation
import SourceKittenFramework
import SwiftCLI

public enum BeakError: Error, CustomStringConvertible {
public enum BeakError: ProcessError, CustomStringConvertible {
case fileNotFound(String)
case compileError(String)
case invalidFunction(String)
case missingRequiredParam(Function.Param)
case parsingError(SwiftStructure)

case conversionError(Function.Param, String)

public var description: String {
switch self {
case let .fileNotFound(file): return "File not found: \(file)"
case let .compileError(error): return "File could not be compiled: \(error)"
case let .invalidFunction(function): return "Function \(function) was not found"
case let .missingRequiredParam(param): return "Missing required param \(param.name)"
case let .parsingError(structure): return "Could not parse Beak file structure:\n\(toJSON(structure))"
case let .conversionError(param, value): return "'\(value)' is not convertible to \(param.type.string) for argument \(param.name)"
}
}

public var message: String? {
return "⚠️ \(description)"
}

public var exitStatus: Int32 {
return 1
}

}
34 changes: 17 additions & 17 deletions Sources/BeakCore/Commands/BeakCommand.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import Foundation
import PathKit
import Utility
import SwiftCLI

class BeakCommand {
struct GlobalOptions {
static let path = Key<String>("-p", "--path", description: "The path to a swift file. Defaults to beak.swift")
private init() {}
}

let parser: ArgumentParser
let options: BeakOptions
let pathArgument: OptionArgument<String>
protocol BeakCommand: Command {
func execute(path: Path, beakFile: BeakFile) throws
}

init(options: BeakOptions, parentParser: ArgumentParser, name: String, description: String) {
self.options = options
parser = parentParser.add(subparser: name, overview: description)
pathArgument = parser.add(option: "--path", shortName: "-p", kind: String.self, usage: "The path to a swift file. Defaults to beak.swift", completion: .filename)
extension BeakCommand {

var path: Key<String> {
return GlobalOptions.path
}

func execute(parsedArguments: ArgumentParser.Result) throws {
let path = Path(parsedArguments.get(pathArgument) ?? "beak.swift").normalize()
func execute() throws {
let path = Path(self.path.value ?? "beak.swift").normalize()
let beakFile = try BeakFile(path: path)
try execute(path: path, beakFile: beakFile, parsedArguments: parsedArguments)
}

func execute(path: Path, beakFile: BeakFile, parsedArguments: ArgumentParser.Result) throws {
try execute(path: path, beakFile: beakFile)
}

}
48 changes: 23 additions & 25 deletions Sources/BeakCore/Commands/EditCommand.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import Foundation
import Utility
import PathKit
import SwiftShell
import SwiftCLI

class EditCommand: BeakCommand {

let name = "edit"
let shortDescription = "Edit the Swift file in an Xcode Project with imported dependencies"

let options: BeakOptions

init(options: BeakOptions, parentParser: ArgumentParser) {
super.init(
options: options,
parentParser: parentParser,
name: "edit",
description: "Edit the Swift file in an Xcode Project with imported dependencies"
)
init(options: BeakOptions) {
self.options = options
}

override func execute(path: Path, beakFile: BeakFile, parsedArguments: ArgumentParser.Result) throws {


func execute(path: Path, beakFile: BeakFile) throws {
let directory = path.absolute().parent()

// create package
Expand All @@ -24,27 +21,28 @@ class EditCommand: BeakCommand {
try packageManager.write(filePath: path)

// generate project
var packageContext = CustomContext(main)
packageContext.currentdirectory = packagePath.string
let buildOutput = packageContext.run(bash: "swift package generate-xcodeproj")
if let error = buildOutput.error {
print(buildOutput.stdout)
print(buildOutput.stderror)
do {
_ = try capture("swift", arguments: ["package", "generate-xcodeproj"], directory: packagePath.string)
} catch let error as CaptureError {
stderr <<< error.captured.rawStdout
stderr <<< error.captured.rawStderr
throw error
}
print("Generating project...")
stdout <<< "Generating project..."

// run package
try packageContext.runAndPrint(bash: "open \(options.packageName).xcodeproj")
print("Edit the file \"Sources/\(options.packageName)/main.swift\"")
print("When you're finished type \"c\" to commit the changes and copy the file back to \(path.string), otherwise type anything else")
try run("open", arguments: ["\(options.packageName).xcodeproj"], directory: packagePath.string)

stdout <<< "Edit the file \"Sources/\(options.packageName)/main.swift\""
stdout <<< "When you're finished type \"c\" to commit the changes and copy the file back to \(path.string), otherwise type anything else"

let line = readLine()
if line?.lowercased() == "c" {
try path.delete()
try packageManager.mainFilePath.copy(path)
print("Copied edited file back to \(path.string)")
stdout <<< "Copied edited file back to \(path.string)"
} else {
print("Changes not copied back to \(path.string)")
stdout <<< "Changes not copied back to \(path.string)"
}
}
}
33 changes: 12 additions & 21 deletions Sources/BeakCore/Commands/FunctionCommand.swift
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
import Foundation
import PathKit
import Utility
import SwiftCLI

class FunctionCommand: BeakCommand {

let name = "function"
let shortDescription = "Info about a specific function"

let functionName = Parameter()

var functionArgument: PositionalArgument<String>!

init(options: BeakOptions, parentParser: ArgumentParser) {
super.init(
options: options,
parentParser: parentParser,
name: "function",
description: "Info about a specific function"
)
functionArgument = parser.add(positional: "function", kind: String.self, optional: false, usage: "The function to get info about", completion: ShellCompletion.none)
}

override func execute(path: Path, beakFile: BeakFile, parsedArguments: ArgumentParser.Result) throws {
let functionName = parsedArguments.get(functionArgument)!
guard let function = beakFile.functions.first(where: { $0.name == functionName }) else {
throw BeakError.invalidFunction(functionName)
func execute(path: Path, beakFile: BeakFile) throws {
guard let function = beakFile.functions.first(where: { $0.name == functionName.value }) else {
throw BeakError.invalidFunction(functionName.value)
}
let params = function.params.map { param in
"\(param.name): \(param.optionalType)\(param.defaultValue != nil ? " = \(param.defaultValue!)" : "")\(param.description != nil ? " - \(param.description!)" : "")"
stdout <<< "\(function.name):\(function.docsDescription != nil ? " \(function.docsDescription!)" : "")"
function.params.forEach { param in
stdout <<< " \(param.name): \(param.optionalType)\(param.defaultValue != nil ? " = \(param.defaultValue!)" : "")\(param.description != nil ? " - \(param.description!)" : "")"
}
print("\(function.name):\(function.docsDescription != nil ? " \(function.docsDescription!)" : "")\n \(params.joined(separator: "\n "))")
}
}
Loading

0 comments on commit b540e66

Please sign in to comment.