Skip to content

Commit

Permalink
Fixing Tests and Cleaning up swift documentation (#130)
Browse files Browse the repository at this point in the history
* Fixing Tests and updating the example

* Cleaning up some of the documentation.

* Adding a build command to CI to catch example failures
  • Loading branch information
KyleLeneau authored and calebkleveter committed Jan 20, 2020
1 parent 535874e commit c525884
Show file tree
Hide file tree
Showing 15 changed files with 79 additions and 59 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery --sanitize=thread
- run: |
swift build
swift test --enable-test-discovery --sanitize=thread
bionic:
container:
image: swift:5.1-bionic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery --sanitize=thread
- run: |
swift build
swift test --enable-test-discovery --sanitize=thread
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ let package = Package(
targets: [
.target(name: "ConsoleKit", dependencies: ["Logging"]),
.testTarget(name: "ConsoleKitTests", dependencies: ["ConsoleKit"]),
.target(name: "ConsoleKitExample", dependencies: ["ConsoleKit"]),
]
)
1 change: 0 additions & 1 deletion Sources/ConsoleKit/Activity/ActivityBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ extension ActivityBar {
}
}


/// Defines the width of all `ActivityBar`s in characters.
private var _width: Int = 25

Expand Down
1 change: 0 additions & 1 deletion Sources/ConsoleKit/Activity/ActivityIndicator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Glibc
import Darwin.C
#endif


extension ActivityIndicatorType {
/// Creates a new `ActivityIndicator` for this `ActivityIndicatorType`.
///
Expand Down
2 changes: 1 addition & 1 deletion Sources/ConsoleKit/Command/Argument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public final class Argument<Value>: AnyArgument

/// Creates a new `Argument`
///
/// @Argument(help: "The number of times to run the command")
/// @Argument(name: "count", help: "The number of times to run the command")
/// var count: Int
///
/// - Parameters:
Expand Down
44 changes: 26 additions & 18 deletions Sources/ConsoleKit/Command/Command.swift
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
/// A command that can be run through a `Console`.
///
/// Both `Command` and `CommandGroup` conform to `CommandRunnable` which provides the basic requirements
/// Both `Command` and `CommandGroup` conform to `AnyCommand` which provides the basic requirements
/// all command-like types need. In addition to those types, a `Command` requires zero or more `CommandArgument`s.
///
/// Below is a sample command that generates ASCII picture of a cow with a message.
///
/// struct CowsayCommand: Command {
/// var arguments: [CommandArgument] {
/// return [.argument(name: "message")]
/// }
/// public struct Signature: CommandSignature {
/// @Argument(name: "message")
/// var message: String
///
/// @Option(name: "eyes", short: "e")
/// var eyes: String?
///
/// @Option(name: "tongue", short: "t")
/// var tongue: String?
///
/// var options: [CommandOption] {
/// return [
/// .value(name: "eyes", short: "e"),
/// .value(name: "tongue", short: "t"),
/// ]
/// public init() { }
/// }
///
/// var help: [String] {
/// return ["Generates ASCII picture of a cow with a message."]
/// var help: String {
/// "Generates ASCII picture of a cow with a message."
/// }
///
/// func run(using context: CommandContext) throws -> Future<Void> {
/// let message = try context.argument("message")
/// let eyes = context.options["eyes"] ?? "oo"
/// let tongue = context.options["tongue"] ?? " "
/// public init() { }
/// public func run(using context: CommandContext, signature: Signature) throws {
/// let eyes = signature.eyes ?? "oo"
/// let tongue = signature.tongue ?? " "
/// let padding = String(repeating: "-", count: message.count)
/// let text: String = """
/// \(padding)
Expand All @@ -37,14 +39,20 @@
/// || ||
/// """
/// context.console.print(text)
/// return .done(on: context.container)
/// }
/// }
///
/// Meanwhile you can use the Command in an executable target like:
///
/// let console: Console = Terminal()
/// var input = CommandInput(arguments: CommandLine.arguments)
/// var context = CommandContext(console: console, input: input)
///
/// try console.run(CoswayCommand(), with: context)
///
/// Use `CommandConfig` to register commands and create a `CommandGroup`.
/// Use `Commands` to register commands and create a `CommandGroup`.
///
/// - note: You can also use `console.run(...)` to run a `CommandRunnable` manually.
/// - note: You can also use `console.run(...)` to run an `AnyCommand` manually.
///
/// Here is a simple example of the command in action, assuming it has been registered as `"cowsay"`.
///
Expand Down
15 changes: 9 additions & 6 deletions Sources/ConsoleKit/Command/CommandGroup.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/// A group of named commands that can be run through a `Console`.
///
/// Usually you will use `CommandConfig` to register commands and create a group.
/// Usually you will use `Commands` to register commands and create a group.
///
/// var env = Environment.testing
/// let container: Container = ...
/// var config = CommandConfig()
/// let console: Console = ...
/// var input = CommandInput(arguments: CommandLine.arguments)
/// var context = CommandContext(console: console, input: input)
///
/// var config = Commands()
/// config.use(CowsayCommand(), as: "cowsay")
/// let group = try config.resolve(for: container).group()
/// try console.run(group, input: &env.commandInput, on: container).wait()
///
/// let group = config.group(help: "Some help for cosway group...")
/// try console.run(group, with: context)
///
/// You can create your own `CommandGroup` if you want to support custom `CommandOptions`.
public protocol CommandGroup: AnyCommand {
Expand Down
20 changes: 9 additions & 11 deletions Sources/ConsoleKit/Command/Commands.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/// Represents a top-level group of configured commands. This is usually created by calling `resolve(for:)` on `CommandConfig`.
/// Represents a top-level group of configured commands. This is usually created by calling `resolve(for:)` on `Commands`.
public struct Commands {
/// Top-level available commands, stored by unique name.
public var commands: [String: AnyCommand]

/// If set, this is the default top-level command that should run if no other commands are specified.
public var defaultCommand: AnyCommand?

/// Creates a new `ConfiguredCommands` struct. This is usually done by calling `resolve(for:)` on `CommandConfig`.
/// Creates a new `ConfiguredCommands` struct. This is usually done by calling `resolve(for:)` on `Commands`.
///
/// - parameters:
/// - commands: Top-level available commands, stored by unique name.
Expand All @@ -18,12 +18,11 @@ public struct Commands {

/// Adds a `Command` instance to the config.
///
/// var commandConfig = CommandConfig.default()
/// commandConfig.use(barCommand, as: "bar")
/// services.register(commandConfig)
/// var config = Commands()
/// config.use(barCommand, as: "bar")
///
/// - parameters:
/// - command: Some `CommandRunnable`. This type will be requested from the service container later.
/// - command: Some `AnyCommand`. This type will be requested from the service container later.
/// - name: A unique name for running this command.
/// - isDefault: If `true`, this command will be set as the default command to run when none other are specified.
/// Setting this overrides any previous default commands.
Expand All @@ -36,12 +35,11 @@ public struct Commands {

/// Creates a `CommandGroup` for this `Commands`.
///
/// var env = Environment.testing
/// let container: Container = ...
/// var config = CommandConfig()
/// var config = Commands()
/// config.use(CowsayCommand(), as: "cowsay")
/// let group = try config.resolve(for: container).group()
/// try console.run(group, input: &env.commandInput, on: container).wait()
/// let group = config.group(help: "Some help for cosway group...")
///
/// try console.run(group, with: context)
///
/// - parameters:
/// - help: Optional help messages to include.
Expand Down
22 changes: 15 additions & 7 deletions Sources/ConsoleKit/Command/Console+Run.swift
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
/// Adds the ability to run `Command`s on a `Console`.
extension Console {

/// Runs an `AnyCommand` (`CommandGroup` or `Command`) of commands on this `Console` using the supplied `CommandInput`.
///
/// try console.run(group, input: commandInput)
///
/// The `CommandInput` will be mutated, removing any used `CommandOption`s and `CommandArgument`s.
/// If any excess input is left over after checking the command's signature, an error will be thrown.
///
/// - parameters:
/// - command: `CommandGroup` or `Command` to run.
/// - input: `CommandInput` to parse `CommandOption`s and `CommandArgument`s from.
public func run(_ command: AnyCommand, input: CommandInput) throws {
// create new context
try self.run(command, with: CommandContext(console: self, input: input))
}
/// Runs a `CommandRunnable` (`CommandGroup` or `Command`) of commands on this `Console` using the supplied `CommandInput`.
///
/// try console.run(group, input: &env.commandInput, on: container).wait()

/// Runs an `AnyCommand` (`CommandGroup` or `Command`) of commands on this `Console` using the supplied `CommandContext`.
///
/// The `CommandInput` will be mutated, removing any used `CommandOption`s and `CommandArgument`s.
/// If any excess input is left over after checking the command's signature, an error will be thrown.
/// try console.run(group, with: context)
///
/// - parameters:
/// - runnable: `CommandGroup` or `Command` to run.
/// - input: Mutable `CommandInput` to parse `CommandOption`s and `CommandArgument`s from.
/// - returns: A `Future` that will complete when the command finishes.
/// - input: `CommandContext` to parse `CommandOption`s and `CommandArgument`s from.
public func run(_ command: AnyCommand, with context: CommandContext) throws {
// make copy of context
var context = context
Expand Down
2 changes: 1 addition & 1 deletion Sources/ConsoleKit/Command/Flag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public final class Flag: AnyFlag {

/// Creates a new `Option` with the `optionType` set to `.value`.
///
/// @Option(short: "v", help: "Output debug logs")
/// @Option(name: "verbose", short: "v", help: "Output debug logs")
/// var verbose: Bool?
///
/// - Parameters:
Expand Down
2 changes: 1 addition & 1 deletion Sources/ConsoleKit/Command/Option.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public final class Option<Value>: AnyOption

/// Creates a new `Option` with the `optionType` set to `.value`.
///
/// @Option(short: "v", help: "Output debug logs")
/// @Option(name: "verbose", short: "v", help: "Output debug logs")
/// var verbose: Bool?
///
/// - Parameters:
Expand Down
1 change: 0 additions & 1 deletion Sources/ConsoleKit/Command/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ extension Console {
}
}


private extension String {
func leftPad(to padding: Int) -> String {
return String(repeating: " ", count: padding) + self
Expand Down
6 changes: 3 additions & 3 deletions Sources/ConsoleKitExample/DemoCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import ConsoleKit

final class DemoCommand: Command {
struct Signature: CommandSignature {
@Flag(short: "c", help: "Enables colorized output")
@Flag(name: "color", short: "c", help: "Enables colorized output")
var color: Bool

@Option(help: "Custom frames for the loading bar\nUse a comma-separated list")
@Option(name: "frames", help: "Custom frames for the loading bar\nUse a comma-separated list")
var frames: String?

init() { }
Expand All @@ -15,7 +15,7 @@ final class DemoCommand: Command {
"A demonstration of what ConsoleKit can do"
}

func run(context: CommandContext, signature: Signature) throws {
func run(using context: CommandContext, signature: Signature) throws {
let funDemoText: ConsoleText
if signature.color {
funDemoText = [
Expand Down
9 changes: 5 additions & 4 deletions Sources/ConsoleKitExample/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import Foundation

let console: Console = Terminal()
var input = CommandInput(arguments: CommandLine.arguments)
var context = CommandContext(console: console, input: input)

var config = CommandConfiguration()
config.use(DemoCommand(), as: "demo", isDefault: true)
var commands = Commands()
commands.use(DemoCommand(), as: "demo", isDefault: false)

do {
let commands = try config.resolve()
let group = commands
.group(help: "An example command-line application built with ConsoleKit")
try console.run(commands, input: input)
try console.run(group, input: input)
} catch let error {
console.error(error.localizedDescription)
exit(1)
Expand Down
4 changes: 2 additions & 2 deletions Tests/ConsoleKitTests/CommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ class CommandTests: XCTestCase {
func testShortFlagNeedsToMatchExactly() throws {
struct Signature: CommandSignature {
@Option(name: "x-short", short: "x")
var xShort: String
var xShort: String?

@Option(name: "y-short", short: "y")
var yShort: String
var yShort: String?

init() { }
}
Expand Down

0 comments on commit c525884

Please sign in to comment.