diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
deleted file mode 100644
index f37da6eb..00000000
--- a/.github/CONTRIBUTING.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Maintainers
-
-- [@calebkleveter](https://github.com/calebkleveter)
-
-See the [Vapor maintainers doc](https://github.com/vapor/vapor/blob/main/Docs/maintainers.md) for more information.
diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml
index 0d22cfd0..bd47e95b 100644
--- a/.github/workflows/api-docs.yml
+++ b/.github/workflows/api-docs.yml
@@ -10,5 +10,5 @@ jobs:
secrets: inherit
with:
package_name: console-kit
- modules: ConsoleKit
- pathsToInvalidate: /consolekit/*
+ modules: ConsoleKit ConsoleKitTerminal ConsoleKitCommands
+ pathsToInvalidate: /consolekit/* /consolekitterminal/* /consolekitcommands/*
diff --git a/Package.swift b/Package.swift
index 00038618..dcfffdd4 100644
--- a/Package.swift
+++ b/Package.swift
@@ -11,34 +11,62 @@ let package = Package(
],
products: [
.library(name: "ConsoleKit", targets: ["ConsoleKit"]),
+ .library(name: "ConsoleKitTerminal", targets: ["ConsoleKitTerminal"]),
+ .library(name: "ConsoleKitCommands", targets: ["ConsoleKitCommands"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.3"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.56.0"),
],
targets: [
- .target(name: "ConsoleKit", dependencies: [
- .product(name: "Logging", package: "swift-log"),
- .product(name: "NIOConcurrencyHelpers", package: "swift-nio")
- ]),
- .testTarget(name: "ConsoleKitTests", dependencies: [
- .target(name: "ConsoleKit"),
- ]),
- .testTarget(name: "AsyncConsoleKitTests", dependencies: [
- .target(name: "ConsoleKit"),
- ]),
- .testTarget(name: "ConsoleKitPerformanceTests", dependencies: [
- .target(name: "ConsoleKit")
- ]),
- .executableTarget(name: "ConsoleKitExample", dependencies: [
- .target(name: "ConsoleKit"),
- ]),
- .executableTarget(name: "ConsoleKitAsyncExample", dependencies: [
- .target(name: "ConsoleKit")
- ]),
- .executableTarget(name: "ConsoleLoggerExample", dependencies: [
- .target(name: "ConsoleKit"),
- .product(name: "Logging", package: "swift-log")
- ])
+ .target(
+ name: "ConsoleKit",
+ dependencies: [
+ .target(name: "ConsoleKitCommands"),
+ .target(name: "ConsoleKitTerminal"),
+ ]
+ ),
+ .target(
+ name: "ConsoleKitCommands",
+ dependencies: [
+ .product(name: "Logging", package: "swift-log"),
+ .product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
+ .target(name: "ConsoleKitTerminal"),
+ ]
+ ),
+ .target(
+ name: "ConsoleKitTerminal",
+ dependencies: [
+ .product(name: "Logging", package: "swift-log"),
+ .product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
+ ]
+ ),
+ .testTarget(
+ name: "ConsoleKitTests",
+ dependencies: [.target(name: "ConsoleKit")]
+ ),
+ .testTarget(
+ name: "AsyncConsoleKitTests",
+ dependencies: [.target(name: "ConsoleKit")]
+ ),
+ .testTarget(
+ name: "ConsoleKitPerformanceTests",
+ dependencies: [.target(name: "ConsoleKit")]
+ ),
+ .executableTarget(
+ name: "ConsoleKitExample",
+ dependencies: [.target(name: "ConsoleKit")]
+ ),
+ .executableTarget(
+ name: "ConsoleKitAsyncExample",
+ dependencies: [.target(name: "ConsoleKit")]
+ ),
+ .executableTarget(
+ name: "ConsoleLoggerExample",
+ dependencies: [
+ .target(name: "ConsoleKit"),
+ .product(name: "Logging", package: "swift-log"),
+ ]
+ ),
]
)
diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift
index 301b65d9..43937c18 100644
--- a/Package@swift-5.9.swift
+++ b/Package@swift-5.9.swift
@@ -1,6 +1,14 @@
// swift-tools-version:5.9
import PackageDescription
+let swiftSettings: [PackageDescription.SwiftSetting] = [
+ .enableExperimentalFeature("StrictConcurrency=complete"),
+ .enableUpcomingFeature("ExistentialAny"),
+ .enableUpcomingFeature("ForwardTrailingClosures"),
+ .enableUpcomingFeature("ConciseMagicFile"),
+ .enableUpcomingFeature("DisableOutwardActorInference"),
+]
+
let package = Package(
name: "console-kit",
platforms: [
@@ -11,39 +19,71 @@ let package = Package(
],
products: [
.library(name: "ConsoleKit", targets: ["ConsoleKit"]),
+ .library(name: "ConsoleKitTerminal", targets: ["ConsoleKitTerminal"]),
+ .library(name: "ConsoleKitCommands", targets: ["ConsoleKitCommands"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.3"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.56.0"),
],
targets: [
- .target(name: "ConsoleKit", dependencies: [
- .product(name: "Logging", package: "swift-log"),
- .product(name: "NIOConcurrencyHelpers", package: "swift-nio")
- ], swiftSettings: [
- .enableExperimentalFeature("StrictConcurrency=complete"),
- .enableUpcomingFeature("ExistentialAny"),
- .enableUpcomingFeature("ForwardTrailingClosures"),
- .enableUpcomingFeature("ConciseMagicFile"),
- ]),
- .testTarget(name: "ConsoleKitTests", dependencies: [
- .target(name: "ConsoleKit"),
- ], swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")]),
- .testTarget(name: "AsyncConsoleKitTests", dependencies: [
- .target(name: "ConsoleKit"),
- ], swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")]),
- .testTarget(name: "ConsoleKitPerformanceTests", dependencies: [
- .target(name: "ConsoleKit")
- ], swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")]),
- .executableTarget(name: "ConsoleKitExample", dependencies: [
- .target(name: "ConsoleKit"),
- ], swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")]),
- .executableTarget(name: "ConsoleKitAsyncExample", dependencies: [
- .target(name: "ConsoleKit")
- ], swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")]),
- .executableTarget(name: "ConsoleLoggerExample", dependencies: [
- .target(name: "ConsoleKit"),
- .product(name: "Logging", package: "swift-log")
- ])
+ .target(
+ name: "ConsoleKit",
+ dependencies: [
+ .target(name: "ConsoleKitCommands"),
+ .target(name: "ConsoleKitTerminal"),
+ ],
+ swiftSettings: swiftSettings
+ ),
+ .target(
+ name: "ConsoleKitCommands",
+ dependencies: [
+ .product(name: "Logging", package: "swift-log"),
+ .product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
+ .target(name: "ConsoleKitTerminal"),
+ ],
+ swiftSettings: swiftSettings
+ ),
+ .target(
+ name: "ConsoleKitTerminal",
+ dependencies: [
+ .product(name: "Logging", package: "swift-log"),
+ .product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
+ ],
+ swiftSettings: swiftSettings
+ ),
+ .testTarget(
+ name: "ConsoleKitTests",
+ dependencies: [.target(name: "ConsoleKit")],
+ swiftSettings: swiftSettings
+ ),
+ .testTarget(
+ name: "AsyncConsoleKitTests",
+ dependencies: [.target(name: "ConsoleKit")],
+ swiftSettings: swiftSettings
+ ),
+ .testTarget(
+ name: "ConsoleKitPerformanceTests",
+ dependencies: [.target(name: "ConsoleKit")],
+ swiftSettings: swiftSettings
+ ),
+ .executableTarget(
+ name: "ConsoleKitExample",
+ dependencies: [.target(name: "ConsoleKit")],
+ swiftSettings: swiftSettings
+ ),
+ .executableTarget(
+ name: "ConsoleKitAsyncExample",
+ dependencies: [.target(name: "ConsoleKit")],
+ swiftSettings: swiftSettings
+ ),
+ .executableTarget(
+ name: "ConsoleLoggerExample",
+ dependencies: [
+ .target(name: "ConsoleKit"),
+ .product(name: "Logging", package: "swift-log"),
+ ],
+ swiftSettings: swiftSettings
+ ),
]
)
diff --git a/README.md b/README.md
index cffc5304..c608c6e6 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,16 @@
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Sources/ConsoleKit/Command/Utilities.swift b/Sources/ConsoleKit/Command/Utilities.swift
deleted file mode 100644
index af6c8f59..00000000
--- a/Sources/ConsoleKit/Command/Utilities.swift
+++ /dev/null
@@ -1,47 +0,0 @@
-extension Array {
- /// Pops the first element from the array.
- mutating func popFirst() -> Element? {
- guard let pop = first else {
- return nil
- }
- self = Array(dropFirst())
- return pop
- }
-}
-
-extension Array where Element == String {
- var longestCount: Int {
- var count = 0
-
- for item in self {
- if item.count > count {
- count = item.count
- }
- }
-
- return count
- }
-}
-
-extension Console {
- func outputHelpListItem(name: String, help: String?, style: ConsoleStyle, padding: Int) {
- self.output(name.leftPad(to: padding - name.count).consoleText(style), newLine: false)
- if let help = help {
- for (index, line) in help.split(separator: "\n").map(String.init).enumerated() {
- if index == 0 {
- self.print(line.leftPad(to: 1))
- } else {
- self.print(line.leftPad(to: padding + 1))
- }
- }
- } else {
- self.print(" n/a")
- }
- }
-}
-
-private extension String {
- func leftPad(to padding: Int) -> String {
- return String(repeating: " ", count: padding) + self
- }
-}
diff --git a/Sources/ConsoleKit/Docs.docc/images/article.svg b/Sources/ConsoleKit/Docs.docc/images/article.svg
deleted file mode 100644
index 3dc6a66c..00000000
--- a/Sources/ConsoleKit/Docs.docc/images/article.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
index 98730e7d..f3b1e796 100644
--- a/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
+++ b/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
@@ -1,40 +1,21 @@
diff --git a/Sources/ConsoleKit/Docs.docc/index.md b/Sources/ConsoleKit/Docs.docc/index.md
index 77c4a8a6..e7883f93 100644
--- a/Sources/ConsoleKit/Docs.docc/index.md
+++ b/Sources/ConsoleKit/Docs.docc/index.md
@@ -4,10 +4,6 @@
@TitleHeading(Package)
}
-ConsoleKit provides utilities for interacting with a console via a Swift application. It provides:
+Utilities for interacting with a terminal and the commandline in a Swift application.
-* A ``Command`` type for writing commands with arguments and flags
-* Utilities for sending and receiving text to a terminal
-* A [Swift Log](https://github.com/apple/swift-log) implementation for a ``Logger`` that outputs to the console
-
-> Note: At this time, the argument handling capabilities of ConsoleKit are considered obsolete; using [ArgumentParser](https://github.com/apple/swift-argument-parser.git) instead is recommended where practical.
+`ConsoleKit` is an umbrella module, exporting [ConsoleKitTerminal](./ConsoleKitTerminal) and [ConsoleKitCommands](./ConsoleKitCommands). It has no separate functionality of its own.
diff --git a/Sources/ConsoleKit/Docs.docc/theme-settings.json b/Sources/ConsoleKit/Docs.docc/theme-settings.json
index 5fd33462..fdbbdb1e 100644
--- a/Sources/ConsoleKit/Docs.docc/theme-settings.json
+++ b/Sources/ConsoleKit/Docs.docc/theme-settings.json
@@ -1,46 +1,21 @@
{
- "theme": {
- "aside": {
- "border-radius": "6px",
- "border-style": "double",
- "border-width": "3px"
- },
- "border-radius": "0",
- "button": {
- "border-radius": "16px",
- "border-width": "1px",
- "border-style": "solid"
- },
- "code": {
- "border-radius": "16px",
- "border-width": "1px",
- "border-style": "solid"
- },
- "color": {
- "fill": {
- "dark": "rgb(20, 20, 22)",
- "light": "rgb(255, 255, 255)"
- },
- "dim-purple": "#392048",
- "documentation-intro-fill": "radial-gradient(circle at top, var(--color-documentation-intro-accent) 30%, #1f1d1f 100%)",
- "documentation-intro-accent": "var(--color-dim-purple)",
- "documentation-intro-accent-outer": {
- "dark": "rgb(255, 255, 255)",
- "light": "rgb(0, 0, 0)"
- },
- "documentation-intro-accent-inner": {
- "dark": "rgb(0, 0, 0)",
- "light": "rgb(255, 255, 255)"
- }
- },
- "icons": {
- "technology": "/consolekit/images/vapor-consolekit-logo.svg",
- "article": "/consolekit/images/article.svg"
- }
+ "theme": {
+ "aside": { "border-radius": "6px", "border-style": "double", "border-width": "3px" },
+ "border-radius": "0",
+ "button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+ "code": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+ "color": {
+ "consolekit": "#392048",
+ "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
+ "documentation-intro-accent": "var(--color-consolekit)",
+ "logo-base": { "dark": "#fff", "light": "#000" },
+ "logo-shape": { "dark": "#000", "light": "#fff" },
+ "fill": { "dark": "#000", "light": "#fff" }
},
- "features": {
- "quickNavigation": {
- "enable": true
- }
- }
+ "icons": { "technology": "/consolekit/images/vapor-consolekit-logo.svg" }
+ },
+ "features": {
+ "quickNavigation": { "enable": true },
+ "i18n": { "enable": true }
+ }
}
diff --git a/Sources/ConsoleKit/Exports.swift b/Sources/ConsoleKit/Exports.swift
new file mode 100644
index 00000000..572aed37
--- /dev/null
+++ b/Sources/ConsoleKit/Exports.swift
@@ -0,0 +1,2 @@
+@_exported import ConsoleKitCommands
+@_exported import ConsoleKitTerminal
diff --git a/Sources/ConsoleKit/Utilities/ConsoleError.swift b/Sources/ConsoleKit/Utilities/ConsoleError.swift
deleted file mode 100644
index 5586d9fc..00000000
--- a/Sources/ConsoleKit/Utilities/ConsoleError.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-/// Errors working with the `Console` module.
-public struct ConsoleError: Error {
- /// See `Debuggable`.
- public let identifier: String
-
- /// See `Debuggable`.
- public let reason: String
-
- /// Creates a new `ConsoleError`
- internal init(identifier: String, reason: String) {
- self.identifier = identifier
- self.reason = reason
- }
-}
diff --git a/Sources/ConsoleKitAsyncExample/DemoCommand.swift b/Sources/ConsoleKitAsyncExample/DemoCommand.swift
index fac7343c..721a4bef 100644
--- a/Sources/ConsoleKitAsyncExample/DemoCommand.swift
+++ b/Sources/ConsoleKitAsyncExample/DemoCommand.swift
@@ -8,7 +8,7 @@ final class DemoCommand: AsyncCommand {
@Option(name: "frames", help: "Custom frames for the loading bar\nUse a comma-separated list")
var frames: String?
- init() { }
+ init() {}
}
var help: String {
@@ -39,18 +39,16 @@ final class DemoCommand: AsyncCommand {
context.console.print("Here's an example of loading")
}
- if let frames = signature.frames {
- let loadingBar = context.console.customActivity(frames: frames.split(separator: ",").map(String.init))
+ func run(loadingBar: ActivityIndicator) {
loadingBar.start()
-
context.console.wait(seconds: 2)
loadingBar.succeed()
- } else {
- let loadingBar = context.console.loadingBar(title: "Loading")
- loadingBar.start()
+ }
- context.console.wait(seconds: 2)
- loadingBar.succeed()
+ if let frames = signature.frames {
+ run(loadingBar: context.console.customActivity(frames: frames.split(separator: ",").map(String.init)))
+ } else {
+ run(loadingBar: context.console.loadingBar(title: "Loading"))
}
context.console.output("Now for secure input: ", newLine: false)
diff --git a/Sources/ConsoleKitAsyncExample/entry.swift b/Sources/ConsoleKitAsyncExample/entrypoint.swift
similarity index 90%
rename from Sources/ConsoleKitAsyncExample/entry.swift
rename to Sources/ConsoleKitAsyncExample/entrypoint.swift
index ab6a4b66..5467a4b8 100644
--- a/Sources/ConsoleKitAsyncExample/entry.swift
+++ b/Sources/ConsoleKitAsyncExample/entrypoint.swift
@@ -4,7 +4,7 @@ import Foundation
@main
struct AsyncExample {
static func main() async throws {
- let console: Console = Terminal()
+ let console = Terminal()
let input = CommandInput(arguments: ProcessInfo.processInfo.arguments)
var commands = AsyncCommands(enableAutocomplete: true)
@@ -16,7 +16,6 @@ struct AsyncExample {
try await console.run(group, input: input)
} catch let error {
console.error("\(error)")
- exit(1)
}
}
}
diff --git a/Sources/ConsoleKit/Command/Async/AnyAsyncCommand.swift b/Sources/ConsoleKitCommands/Async/AnyAsyncCommand.swift
similarity index 98%
rename from Sources/ConsoleKit/Command/Async/AnyAsyncCommand.swift
rename to Sources/ConsoleKitCommands/Async/AnyAsyncCommand.swift
index 5df3f6c0..884fddcc 100644
--- a/Sources/ConsoleKit/Command/Async/AnyAsyncCommand.swift
+++ b/Sources/ConsoleKitCommands/Async/AnyAsyncCommand.swift
@@ -22,6 +22,6 @@ extension AnyAsyncCommand {
}
public func renderCompletionFunctions(using context: CommandContext, shell: Shell) -> String {
- return ""
+ ""
}
}
diff --git a/Sources/ConsoleKit/Command/Async/AsyncCommand.swift b/Sources/ConsoleKitCommands/Async/AsyncCommand.swift
similarity index 90%
rename from Sources/ConsoleKit/Command/Async/AsyncCommand.swift
rename to Sources/ConsoleKitCommands/Async/AsyncCommand.swift
index 166edbc0..eabce96c 100644
--- a/Sources/ConsoleKit/Command/Async/AsyncCommand.swift
+++ b/Sources/ConsoleKitCommands/Async/AsyncCommand.swift
@@ -1,3 +1,5 @@
+import ConsoleKitTerminal
+
/// A command that can be run through a `Console`.
///
/// Both `AsyncCommand` and `AsyncCommandGroup` conform to `AnyAsyncCommand` which provides the basic requirements
@@ -87,21 +89,20 @@ extension AsyncCommand {
public func run(using context: inout CommandContext) async throws {
let signature = try Signature(from: &context.input)
guard context.input.arguments.isEmpty else {
- let input = context.input.arguments.joined(separator: " ")
- throw ConsoleError.init(identifier: "unknownInput", reason: "Input not recognized: \(input)")
+ throw CommandError.unknownInput(context.input.arguments.joined(separator: " "))
}
try await self.run(using: context, signature: signature)
}
public func outputAutoComplete(using context: inout CommandContext) {
var autocomplete: [String] = []
- autocomplete += Signature.reference.arguments.map { $0.name }
- autocomplete += Signature.reference.options.map { "--" + $0.name }
+ autocomplete += Signature().arguments.map { $0.name }
+ autocomplete += Signature().options.map { "--" + $0.name }
context.console.output(autocomplete.joined(separator: " "), style: .plain)
}
public func outputHelp(using context: inout CommandContext) {
context.console.output("Usage: ".consoleText(.info) + context.input.executable.consoleText() + " ", newLine: false)
- Signature.reference.outputHelp(help: self.help, using: &context)
+ Signature().outputHelp(help: self.help, using: &context)
}
}
diff --git a/Sources/ConsoleKit/Command/Async/AsyncCommandGroup.swift b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift
similarity index 96%
rename from Sources/ConsoleKit/Command/Async/AsyncCommandGroup.swift
rename to Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift
index 759e9ba7..e43254db 100644
--- a/Sources/ConsoleKit/Command/Async/AsyncCommandGroup.swift
+++ b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift
@@ -1,3 +1,5 @@
+import ConsoleKitTerminal
+
/// A group of named commands that can be run through a `Console`.
///
/// Usually you will use `AsyncCommands` to register commands and create a group.
@@ -20,7 +22,7 @@ public protocol AsyncCommandGroup: AnyAsyncCommand {
extension AsyncCommandGroup {
public var defaultCommand: (any AnyAsyncCommand)? {
- return nil
+ nil
}
}
@@ -60,8 +62,8 @@ extension AsyncCommandGroup {
context.console.print(self.help)
}
- let padding = self.commands.map { $0.key }.longestCount + 2
- if self.commands.count > 0 {
+ let padding = (self.commands.map(\.key.count).max() ?? 0) + 2
+ if !self.commands.isEmpty {
context.console.print()
context.console.output("Commands:".consoleText(.success))
for (key, command) in self.commands.sorted(by: { $0.key < $1.key }) {
diff --git a/Sources/ConsoleKit/Command/Async/AsyncCommands.swift b/Sources/ConsoleKitCommands/Async/AsyncCommands.swift
similarity index 100%
rename from Sources/ConsoleKit/Command/Async/AsyncCommands.swift
rename to Sources/ConsoleKitCommands/Async/AsyncCommands.swift
diff --git a/Sources/ConsoleKit/Utilities/GenerateAsyncAutocompleteCommand.swift b/Sources/ConsoleKitCommands/Async/GenerateAsyncAutocompleteCommand.swift
similarity index 100%
rename from Sources/ConsoleKit/Utilities/GenerateAsyncAutocompleteCommand.swift
rename to Sources/ConsoleKitCommands/Async/GenerateAsyncAutocompleteCommand.swift
diff --git a/Sources/ConsoleKit/Command/AnyCommand.swift b/Sources/ConsoleKitCommands/Base/AnyCommand.swift
similarity index 98%
rename from Sources/ConsoleKit/Command/AnyCommand.swift
rename to Sources/ConsoleKitCommands/Base/AnyCommand.swift
index 57f64eb6..28fbe8f1 100644
--- a/Sources/ConsoleKit/Command/AnyCommand.swift
+++ b/Sources/ConsoleKitCommands/Base/AnyCommand.swift
@@ -22,6 +22,6 @@ extension AnyCommand {
}
public func renderCompletionFunctions(using context: CommandContext, shell: Shell) -> String {
- return ""
+ ""
}
}
diff --git a/Sources/ConsoleKit/Command/Command.swift b/Sources/ConsoleKitCommands/Base/Command.swift
similarity index 91%
rename from Sources/ConsoleKit/Command/Command.swift
rename to Sources/ConsoleKitCommands/Base/Command.swift
index b141954e..f293331b 100644
--- a/Sources/ConsoleKit/Command/Command.swift
+++ b/Sources/ConsoleKitCommands/Base/Command.swift
@@ -1,3 +1,5 @@
+import ConsoleKitTerminal
+
/// A command that can be run through a `Console`.
///
/// Both `Command` and `CommandGroup` conform to `AnyCommand` which provides the basic requirements
@@ -87,22 +89,21 @@ extension Command {
public func run(using context: inout CommandContext) throws {
let signature = try Signature(from: &context.input)
guard context.input.arguments.isEmpty else {
- let input = context.input.arguments.joined(separator: " ")
- throw ConsoleError.init(identifier: "unknownInput", reason: "Input not recognized: \(input)")
+ throw CommandError.unknownInput(context.input.arguments.joined(separator: " "))
}
try self.run(using: context, signature: signature)
}
public func outputAutoComplete(using context: inout CommandContext) {
var autocomplete: [String] = []
- autocomplete += Signature.reference.arguments.map { $0.name }
- autocomplete += Signature.reference.options.map { "--" + $0.name }
+ autocomplete += Signature().arguments.map { $0.name }
+ autocomplete += Signature().options.map { "--" + $0.name }
context.console.output(autocomplete.joined(separator: " "), style: .plain)
}
public func outputHelp(using context: inout CommandContext) {
context.console.output("Usage: ".consoleText(.info) + context.input.executable.consoleText() + " ", newLine: false)
- Signature.reference.outputHelp(help: self.help, using: &context)
+ Signature().outputHelp(help: self.help, using: &context)
}
}
@@ -138,8 +139,8 @@ extension CommandSignature {
+ self.arguments.map { $0.name }
+ self.flags.map { $0.name }
- let padding = names.longestCount + 2
- if self.arguments.count > 0 {
+ let padding = (names.map(\.count).max() ?? 0) + 2
+ if !self.arguments.isEmpty {
context.console.print()
context.console.output("Arguments:".consoleText(.info))
for argument in self.arguments {
@@ -152,7 +153,7 @@ extension CommandSignature {
}
}
- if self.options.count > 0 {
+ if !self.options.isEmpty {
context.console.print()
context.console.output("Options:".consoleText(.info))
for option in self.options {
@@ -165,7 +166,7 @@ extension CommandSignature {
}
}
- if self.flags.count > 0 {
+ if !self.flags.isEmpty {
context.console.print()
context.console.output("Flags:".consoleText(.info))
for option in self.flags {
diff --git a/Sources/ConsoleKit/Command/CommandContext.swift b/Sources/ConsoleKitCommands/Base/CommandContext.swift
similarity index 92%
rename from Sources/ConsoleKit/Command/CommandContext.swift
rename to Sources/ConsoleKitCommands/Base/CommandContext.swift
index 4dd04dae..d12696b1 100644
--- a/Sources/ConsoleKit/Command/CommandContext.swift
+++ b/Sources/ConsoleKitCommands/Base/CommandContext.swift
@@ -1,3 +1,5 @@
+import protocol ConsoleKitTerminal.Console
+
/// A type-erased `CommandContext`
public struct CommandContext {
/// The `Console` this command was run on.
diff --git a/Sources/ConsoleKit/Command/CommandError.swift b/Sources/ConsoleKitCommands/Base/CommandError.swift
similarity index 62%
rename from Sources/ConsoleKit/Command/CommandError.swift
rename to Sources/ConsoleKitCommands/Base/CommandError.swift
index 3d7bf25e..0bffddef 100644
--- a/Sources/ConsoleKit/Command/CommandError.swift
+++ b/Sources/ConsoleKitCommands/Base/CommandError.swift
@@ -1,30 +1,33 @@
-/// Errors working with the `Command` module.
-public enum CommandError: Error, Equatable, CustomStringConvertible {
+/// Errors working with the ``ConsoleKitCommands`` module.
+public enum CommandError: Error, Equatable, CustomStringConvertible, CustomDebugStringConvertible {
case missingCommand
- case unknownCommand(_ command: String, available: [String])
- case missingRequiredArgument(_ argument: String)
- case invalidArgumentType(_ argument: String, type: Any.Type)
- case invalidOptionType(_ option: String, type: Any.Type)
+ case unknownCommand(String, available: [String])
+ case missingRequiredArgument(String)
+ case invalidArgumentType(String, type: any Any.Type)
+ case invalidOptionType(String, type: any Any.Type)
+ case unknownInput(String)
- /// See `Equatable`
+ // See `Equatable.==(_:_:)`.
public static func == (lhs: CommandError, rhs: CommandError) -> Bool {
switch (lhs, rhs) {
case (.missingCommand, .missingCommand):
return true
- case (let .unknownCommand(cmdL, available: availL), let .unknownCommand(cmdR, available: availR)):
- return cmdL == cmdR && availL.sorted() == availR.sorted()
- case (let .missingRequiredArgument(argL), let .missingRequiredArgument(argR)):
+ case let (.unknownCommand(cmdL, availL), .unknownCommand(cmdR, availR)):
+ return cmdL == cmdR && Set(availL) == Set(availR)
+ case let (.missingRequiredArgument(argL), .missingRequiredArgument(argR)):
return argL == argR
- case (let .invalidArgumentType(argL, type: tL), let .invalidArgumentType(argR, type: tR)):
+ case let (.invalidArgumentType(argL, tL), .invalidArgumentType(argR, tR)):
return argL == argR && tL == tR
- case (let .invalidOptionType(optL, type: tL), let .invalidOptionType(optR, type: tR)):
+ case let (.invalidOptionType(optL, tL), .invalidOptionType(optR, tR)):
return optL == optR && tL == tR
+ case let (.unknownInput(inputL), .unknownInput(inputR)):
+ return inputL == inputR
default:
return false
}
}
- /// See `CustomStringConvertible`.
+ // See `CustomStringConvertible.description`.
public var description: String {
switch self {
case .missingCommand:
@@ -36,8 +39,8 @@ public enum CommandError: Error, Equatable, CustomStringConvertible {
let suggestions: [(String, Int)] = available
.map { ($0, $0.levenshteinDistance(to: command)) }
- .sorted(by: smallerDistance)
- .filter(distanceLessThan(3))
+ .filter { $1 < 3 }
+ .sorted { $0.1 < $1.1 }
guard !suggestions.isEmpty else {
return "Unknown command `\(command)`"
@@ -56,19 +59,12 @@ public enum CommandError: Error, Equatable, CustomStringConvertible {
return "Could not convert argument for `\(argument)` to \(type)"
case let .invalidOptionType(option, type: type):
return "Could not convert option for `\(option)` to \(type)"
+ case let .unknownInput(input):
+ return "Input not recognized: \(input)"
}
}
-}
-
-private func smallerDistance(lhs: (String, Int), rhs: (String, Int)) -> Bool {
- return lhs.1 < rhs.1
-}
-private func distanceLessThan(_ threshold: Int) -> (String, Int) -> Bool {
- return { command, distance in distance < threshold }
-}
-
-extension CommandError: CustomDebugStringConvertible {
+ // See `CustomDebugStringConvertible.debugDescription`.
public var debugDescription: String {
switch self {
case .missingCommand:
@@ -81,6 +77,14 @@ extension CommandError: CustomDebugStringConvertible {
return #".invalidArgumentType("\#(argument)", type: \#(type))"#
case let .invalidOptionType(option, type: type):
return #".invalidOptionType("\#(option)", type: \#(type))"#
+ case let .unknownInput(input):
+ return #".unknownInput("\#(input)")"#
}
}
}
+
+@available(*, deprecated, message: "Subsumed by `CommandError`")
+public struct ConsoleError: Error {
+ public let identifier: String
+ public let reason: String
+}
diff --git a/Sources/ConsoleKit/Command/CommandGroup.swift b/Sources/ConsoleKitCommands/Base/CommandGroup.swift
similarity index 96%
rename from Sources/ConsoleKit/Command/CommandGroup.swift
rename to Sources/ConsoleKitCommands/Base/CommandGroup.swift
index bbebb62e..3be82c7d 100644
--- a/Sources/ConsoleKit/Command/CommandGroup.swift
+++ b/Sources/ConsoleKitCommands/Base/CommandGroup.swift
@@ -1,3 +1,5 @@
+import ConsoleKitTerminal
+
/// A group of named commands that can be run through a `Console`.
///
/// Usually you will use `Commands` to register commands and create a group.
@@ -20,7 +22,7 @@ public protocol CommandGroup: AnyCommand {
extension CommandGroup {
public var defaultCommand: (any AnyCommand)? {
- return nil
+ nil
}
}
@@ -60,8 +62,8 @@ extension CommandGroup {
context.console.print(self.help)
}
- let padding = self.commands.map { $0.key }.longestCount + 2
- if self.commands.count > 0 {
+ let padding = (self.commands.map(\.key.count).max() ?? 0) + 2
+ if !self.commands.isEmpty {
context.console.print()
context.console.output("Commands:".consoleText(.success))
for (key, command) in self.commands.sorted(by: { $0.key < $1.key }) {
diff --git a/Sources/ConsoleKit/Command/CommandInput.swift b/Sources/ConsoleKitCommands/Base/CommandInput.swift
similarity index 100%
rename from Sources/ConsoleKit/Command/CommandInput.swift
rename to Sources/ConsoleKitCommands/Base/CommandInput.swift
diff --git a/Sources/ConsoleKit/Command/Commands.swift b/Sources/ConsoleKitCommands/Base/Commands.swift
similarity index 100%
rename from Sources/ConsoleKit/Command/Commands.swift
rename to Sources/ConsoleKitCommands/Base/Commands.swift
diff --git a/Sources/ConsoleKit/Command/Console+Run.swift b/Sources/ConsoleKitCommands/Base/Console+Run.swift
similarity index 99%
rename from Sources/ConsoleKit/Command/Console+Run.swift
rename to Sources/ConsoleKitCommands/Base/Console+Run.swift
index d27c9200..09e5e4b4 100644
--- a/Sources/ConsoleKit/Command/Console+Run.swift
+++ b/Sources/ConsoleKitCommands/Base/Console+Run.swift
@@ -1,3 +1,5 @@
+import protocol ConsoleKitTerminal.Console
+
/// 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`.
diff --git a/Sources/ConsoleKitCommands/Base/ConsoleError.swift b/Sources/ConsoleKitCommands/Base/ConsoleError.swift
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/Sources/ConsoleKitCommands/Base/ConsoleError.swift
@@ -0,0 +1 @@
+
diff --git a/Sources/ConsoleKit/Command/Completion.swift b/Sources/ConsoleKitCommands/Completion/Completion.swift
similarity index 95%
rename from Sources/ConsoleKit/Command/Completion.swift
rename to Sources/ConsoleKitCommands/Completion/Completion.swift
index a4a270e1..e03b1d1c 100644
--- a/Sources/ConsoleKit/Command/Completion.swift
+++ b/Sources/ConsoleKitCommands/Completion/Completion.swift
@@ -46,9 +46,9 @@ extension Command {
public func renderCompletionFunctions(using context: CommandContext, shell: Shell) -> String {
switch shell {
case .bash:
- return self.renderBashCompletionFunction(using: context, signatureValues: Signature.reference.values)
+ return self.renderBashCompletionFunction(using: context, signatureValues: Signature().values)
case .zsh:
- return self.renderZshCompletionFunction(using: context, signatureValues: Signature.reference.values)
+ return self.renderZshCompletionFunction(using: context, signatureValues: Signature().values)
}
}
}
@@ -59,9 +59,9 @@ extension AsyncCommand {
public func renderCompletionFunctions(using context: CommandContext, shell: Shell) -> String {
switch shell {
case .bash:
- return self.renderBashCompletionFunction(using: context, signatureValues: Signature.reference.values)
+ return self.renderBashCompletionFunction(using: context, signatureValues: Signature().values)
case .zsh:
- return self.renderZshCompletionFunction(using: context, signatureValues: Signature.reference.values)
+ return self.renderZshCompletionFunction(using: context, signatureValues: Signature().values)
}
}
}
@@ -187,7 +187,7 @@ extension AnyCommand {
""" : ""
)\( !wordList.isEmpty ? """
- COMPREPLY=( $(compgen -W "\(wordList.joined(separator: " "))" -- $cur) )
+ COMPREPLY=( $(compgen -W "\(wordList.joined(separator: " "))" -- "$cur") )
""": ""
)\( arguments
.filter { $0.labels == nil }
@@ -364,7 +364,7 @@ extension AnyAsyncCommand {
""" : ""
)\( !wordList.isEmpty ? """
- COMPREPLY=( $(compgen -W "\(wordList.joined(separator: " "))" -- $cur) )
+ COMPREPLY=( $(compgen -W "\(wordList.joined(separator: " "))" -- "$cur") )
""": ""
)\( arguments
.filter { $0.labels == nil }
@@ -473,7 +473,7 @@ public struct CompletionAction: Sendable {
}
public subscript(shell: Shell) -> String? {
- return self.expressions[shell]
+ self.expressions[shell]
}
}
@@ -500,17 +500,15 @@ extension CompletionAction {
switch extensions.count {
case 0:
return [
- .bash: "_filedir",
+ .bash: #"if declare -F _filedir >/dev/null; then _filedir; else COMPREPLY+=( $(compgen -f -- "$cur") ); fi"#,
.zsh: "_files"
]
- case 1:
- return [
- .bash: "_filedir '@(\(extensions[0]))'",
- .zsh: "_files -g '*.\(extensions[0])'"
- ]
default:
return [
- .bash: "_filedir '@(\(extensions.joined(separator: "|")))'",
+ .bash: #"if declare -F _filedir >/dev/null; "# +
+ #"then _filedir '@(\#(extensions.joined(separator: "|")))'; "# +
+ #"else COMPREPLY+=( \#(extensions.map { #"$(compgen -f -X '!*.\#($0)' -- "$cur")"# }.joined(separator: "; ")) ); "# +
+ #"fi"#,
.zsh: "_files -g '*.(\(extensions.joined(separator: "|")))'"
]
}
@@ -518,8 +516,8 @@ extension CompletionAction {
/// Creates a `CompletionAction` that uses a built-in function to generate directory matches.
public static func directories() -> CompletionAction {
- return [
- .bash: "_filedir -d",
+ [
+ .bash: #"if declare -F _filedir >/dev/null; then _filedir -d; else COMPREPLY+=( compgen -d -- "$cur" ); fi"#,
.zsh: "_files -/"
]
}
@@ -527,7 +525,7 @@ extension CompletionAction {
/// Creates a `CompletionAction` that provides a predefined list of possible values.
public static func values(_ values: [String]) -> CompletionAction {
return [
- .bash: "COMPREPLY+=( $(compgen -W \"\(values.joined(separator: " "))\" -- $cur) )",
+ .bash: #"COMPREPLY+=( $(compgen -W "\#(values.joined(separator: " "))" -- "$cur") )"#,
.zsh: "{_values '' \(values.map { "'\($0)'" }.joined(separator: " "))}"
]
}
@@ -619,7 +617,7 @@ extension Argument {
// See `AnySignatureValue`.
var completionInfo: CompletionSignatureValueInfo {
- return .init(
+ .init(
name: self.name,
help: self.help,
action: self.completion
@@ -637,7 +635,7 @@ extension CommandInput {
/// `"program"`.
///
var executableName: String {
- return String(self.executablePath.first!.split(separator: "/").last!)
+ String(self.executablePath.first!.split(separator: "/").last!)
}
/// Returns the name to use for the completion function for the current `executablePath`.
@@ -667,7 +665,7 @@ extension StringProtocol {
/// Returns a copy of `self` with any characters that might cause trouble
/// in a completion script escaped.
fileprivate var completionEscaped: String {
- return self
+ self
.replacingOccurrences(of: "'", with: "\\'")
.replacingOccurrences(of: "\"", with: "\\\"")
.replacingOccurrences(of: "`", with: "\\`")
diff --git a/Sources/ConsoleKit/Utilities/GenerateAutocompleteCommand.swift b/Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift
similarity index 100%
rename from Sources/ConsoleKit/Utilities/GenerateAutocompleteCommand.swift
rename to Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift
diff --git a/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg
new file mode 100644
index 00000000..f3b1e796
--- /dev/null
+++ b/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg
@@ -0,0 +1,21 @@
+
diff --git a/Sources/ConsoleKitCommands/Docs.docc/index.md b/Sources/ConsoleKitCommands/Docs.docc/index.md
new file mode 100644
index 00000000..fed9d5df
--- /dev/null
+++ b/Sources/ConsoleKitCommands/Docs.docc/index.md
@@ -0,0 +1,9 @@
+# ``ConsoleKitCommands``
+
+@Metadata {
+ @TitleHeading(Package)
+}
+
+`ConsoleKitCommands` provides utilities for handing commandline arguments in a Swift application. It provides ``Command`` and ``AsyncCommand`` types, as well as other supporting types, for processing commands with arguments, options, and flags.
+
+> Note: At this time, the argument handling capabilities of `ConsoleKit` are considered obsolete; when possible, we strongly recommend using [ArgumentParser](https://github.com/apple/swift-argument-parser.git) instead.
diff --git a/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json b/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json
new file mode 100644
index 00000000..fdbbdb1e
--- /dev/null
+++ b/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json
@@ -0,0 +1,21 @@
+{
+ "theme": {
+ "aside": { "border-radius": "6px", "border-style": "double", "border-width": "3px" },
+ "border-radius": "0",
+ "button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+ "code": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+ "color": {
+ "consolekit": "#392048",
+ "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
+ "documentation-intro-accent": "var(--color-consolekit)",
+ "logo-base": { "dark": "#fff", "light": "#000" },
+ "logo-shape": { "dark": "#000", "light": "#fff" },
+ "fill": { "dark": "#000", "light": "#fff" }
+ },
+ "icons": { "technology": "/consolekit/images/vapor-consolekit-logo.svg" }
+ },
+ "features": {
+ "quickNavigation": { "enable": true },
+ "i18n": { "enable": true }
+ }
+}
diff --git a/Sources/ConsoleKit/Command/Argument.swift b/Sources/ConsoleKitCommands/Signatures/Argument.swift
similarity index 100%
rename from Sources/ConsoleKit/Command/Argument.swift
rename to Sources/ConsoleKitCommands/Signatures/Argument.swift
diff --git a/Sources/ConsoleKit/Command/CommandSignature.swift b/Sources/ConsoleKitCommands/Signatures/CommandSignature.swift
similarity index 91%
rename from Sources/ConsoleKit/Command/CommandSignature.swift
rename to Sources/ConsoleKitCommands/Signatures/CommandSignature.swift
index 853c5bb3..1854c51a 100644
--- a/Sources/ConsoleKit/Command/CommandSignature.swift
+++ b/Sources/ConsoleKitCommands/Signatures/CommandSignature.swift
@@ -10,11 +10,6 @@ public protocol CommandSignature: Sendable {
}
extension CommandSignature {
- static var reference: Self {
- let reference = Self()
- return reference
- }
-
var arguments: [any AnyArgument] {
return Mirror(reflecting: self).children
.compactMap { $0.value as? (any AnyArgument) }
@@ -58,7 +53,7 @@ internal protocol AnySignatureValue: AnyObject, Sendable {
var completionInfo: CompletionSignatureValueInfo { get }
}
-internal protocol AnyArgument: AnySignatureValue { }
+internal protocol AnyArgument: AnySignatureValue {}
internal protocol AnyOption: AnySignatureValue {
var short: Character? { get }
}
diff --git a/Sources/ConsoleKit/Command/Flag.swift b/Sources/ConsoleKitCommands/Signatures/Flag.swift
similarity index 100%
rename from Sources/ConsoleKit/Command/Flag.swift
rename to Sources/ConsoleKitCommands/Signatures/Flag.swift
diff --git a/Sources/ConsoleKit/Command/Option.swift b/Sources/ConsoleKitCommands/Signatures/Option.swift
similarity index 100%
rename from Sources/ConsoleKit/Command/Option.swift
rename to Sources/ConsoleKitCommands/Signatures/Option.swift
diff --git a/Sources/ConsoleKit/Utilities/String+LevenshteinDistance.swift b/Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift
similarity index 82%
rename from Sources/ConsoleKit/Utilities/String+LevenshteinDistance.swift
rename to Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift
index cc9e5d06..57e720ec 100644
--- a/Sources/ConsoleKit/Utilities/String+LevenshteinDistance.swift
+++ b/Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift
@@ -17,17 +17,14 @@ extension String {
}
// Create two work vectors of integer distances
- var v0: [Int] = Array(repeating: 0, count: target.count + 1)
- var v1: [Int] = Array(repeating: 0, count: target.count + 1)
-
// Initialize v0 (the previous row of distances)
// This row is A[0][i]: edit distance for an empty s
// The distance is just the number of characters to delete from t
- for i in 0.. Element? {
+ self.isEmpty ? nil : self.removeFirst()
+ }
+}
+
+extension Console {
+ func outputHelpListItem(name: String, help: String?, style: ConsoleStyle, padding: Int) {
+ self.output("\(" ".repeated(padding - name.count))\(name)".consoleText(style), newLine: false)
+ if let lines = help?.split(separator: "\n"), !lines.isEmpty {
+ self.print(" \(lines[0])")
+ lines.dropFirst().forEach { self.print("\(" ".repeated(padding)) \($0)") }
+ } else {
+ self.print(" n/a")
+ }
+ }
+}
+
+private extension String {
+ func repeated(_ count: Int) -> String { String(repeating: self, count: count) }
+}
diff --git a/Sources/ConsoleKitExample/DemoCommand.swift b/Sources/ConsoleKitExample/DemoCommand.swift
index 69001f61..f18cc92b 100644
--- a/Sources/ConsoleKitExample/DemoCommand.swift
+++ b/Sources/ConsoleKitExample/DemoCommand.swift
@@ -8,7 +8,7 @@ final class DemoCommand: Command {
@Option(name: "frames", help: "Custom frames for the loading bar\nUse a comma-separated list")
var frames: String?
- init() { }
+ init() {}
}
var help: String {
@@ -38,19 +38,17 @@ final class DemoCommand: Command {
} else {
context.console.print("Here's an example of loading")
}
-
- if let frames = signature.frames {
- let loadingBar = context.console.customActivity(frames: frames.split(separator: ",").map(String.init))
+
+ func run(loadingBar: ActivityIndicator) {
loadingBar.start()
-
context.console.wait(seconds: 2)
loadingBar.succeed()
- } else {
- let loadingBar = context.console.loadingBar(title: "Loading")
- loadingBar.start()
+ }
- context.console.wait(seconds: 2)
- loadingBar.succeed()
+ if let frames = signature.frames {
+ run(loadingBar: context.console.customActivity(frames: frames.split(separator: ",").map(String.init)))
+ } else {
+ run(loadingBar: context.console.loadingBar(title: "Loading"))
}
context.console.output("Now for secure input: ", newLine: false)
diff --git a/Sources/ConsoleKitExample/entrypoint.swift b/Sources/ConsoleKitExample/entrypoint.swift
new file mode 100644
index 00000000..12aa0af2
--- /dev/null
+++ b/Sources/ConsoleKitExample/entrypoint.swift
@@ -0,0 +1,21 @@
+import ConsoleKit
+import Foundation
+import Logging
+
+@main
+struct ConsoleKitExample {
+ static func main() {
+ let console = Terminal()
+ let input = CommandInput(arguments: ProcessInfo.processInfo.arguments)
+
+ var commands = Commands(enableAutocomplete: true)
+ commands.use(DemoCommand(), as: "demo", isDefault: false)
+
+ do {
+ let group = commands.group(help: "An example command-line application built with ConsoleKit")
+ try console.run(group, input: input)
+ } catch let error {
+ console.error("\(error)")
+ }
+ }
+}
diff --git a/Sources/ConsoleKitExample/main.swift b/Sources/ConsoleKitExample/main.swift
deleted file mode 100644
index 3e4df8e5..00000000
--- a/Sources/ConsoleKitExample/main.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-import ConsoleKit
-import Foundation
-import Logging
-
-let console: Console = Terminal()
-var input = CommandInput(arguments: ProcessInfo.processInfo.arguments)
-var context = CommandContext(console: console, input: input)
-
-var commands = Commands(enableAutocomplete: true)
-commands.use(DemoCommand(), as: "demo", isDefault: false)
-
-do {
- let group = commands
- .group(help: "An example command-line application built with ConsoleKit")
- try console.run(group, input: input)
-} catch let error {
- console.error("\(error)")
- exit(1)
-}
diff --git a/Sources/ConsoleKit/Activity/ActivityBar.swift b/Sources/ConsoleKitTerminal/Activity/ActivityBar.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/ActivityBar.swift
rename to Sources/ConsoleKitTerminal/Activity/ActivityBar.swift
diff --git a/Sources/ConsoleKit/Activity/ActivityIndicator.swift b/Sources/ConsoleKitTerminal/Activity/ActivityIndicator.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/ActivityIndicator.swift
rename to Sources/ConsoleKitTerminal/Activity/ActivityIndicator.swift
diff --git a/Sources/ConsoleKit/Activity/ActivityIndicatorRenderer.swift b/Sources/ConsoleKitTerminal/Activity/ActivityIndicatorRenderer.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/ActivityIndicatorRenderer.swift
rename to Sources/ConsoleKitTerminal/Activity/ActivityIndicatorRenderer.swift
diff --git a/Sources/ConsoleKit/Activity/ActivityIndicatorState.swift b/Sources/ConsoleKitTerminal/Activity/ActivityIndicatorState.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/ActivityIndicatorState.swift
rename to Sources/ConsoleKitTerminal/Activity/ActivityIndicatorState.swift
diff --git a/Sources/ConsoleKit/Activity/CustomActivity.swift b/Sources/ConsoleKitTerminal/Activity/CustomActivity.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/CustomActivity.swift
rename to Sources/ConsoleKitTerminal/Activity/CustomActivity.swift
diff --git a/Sources/ConsoleKit/Activity/LoadingBar.swift b/Sources/ConsoleKitTerminal/Activity/LoadingBar.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/LoadingBar.swift
rename to Sources/ConsoleKitTerminal/Activity/LoadingBar.swift
diff --git a/Sources/ConsoleKit/Activity/ProgressBar.swift b/Sources/ConsoleKitTerminal/Activity/ProgressBar.swift
similarity index 100%
rename from Sources/ConsoleKit/Activity/ProgressBar.swift
rename to Sources/ConsoleKitTerminal/Activity/ProgressBar.swift
diff --git a/Sources/ConsoleKit/Clear/Console+Clear.swift b/Sources/ConsoleKitTerminal/Clear/Console+Clear.swift
similarity index 100%
rename from Sources/ConsoleKit/Clear/Console+Clear.swift
rename to Sources/ConsoleKitTerminal/Clear/Console+Clear.swift
diff --git a/Sources/ConsoleKit/Clear/Console+Ephemeral.swift b/Sources/ConsoleKitTerminal/Clear/Console+Ephemeral.swift
similarity index 100%
rename from Sources/ConsoleKit/Clear/Console+Ephemeral.swift
rename to Sources/ConsoleKitTerminal/Clear/Console+Ephemeral.swift
diff --git a/Sources/ConsoleKit/Clear/ConsoleClear.swift b/Sources/ConsoleKitTerminal/Clear/ConsoleClear.swift
similarity index 100%
rename from Sources/ConsoleKit/Clear/ConsoleClear.swift
rename to Sources/ConsoleKitTerminal/Clear/ConsoleClear.swift
diff --git a/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg
new file mode 100644
index 00000000..f3b1e796
--- /dev/null
+++ b/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg
@@ -0,0 +1,21 @@
+
diff --git a/Sources/ConsoleKitTerminal/Docs.docc/index.md b/Sources/ConsoleKitTerminal/Docs.docc/index.md
new file mode 100644
index 00000000..b008b446
--- /dev/null
+++ b/Sources/ConsoleKitTerminal/Docs.docc/index.md
@@ -0,0 +1,11 @@
+# ``ConsoleKitTerminal``
+
+@Metadata {
+ @TitleHeading(Package)
+}
+
+`ConsoleKitTerminal` provides utilities for interacting with a console in a Swift application. It provides:
+
+* Utilities for sending text (including styles and colors, when supported) to a terminal.
+* Utilities for reading input from a terminal.
+* ``ConsoleLog`` and ``ConsoleFragmentLogger``, [SwiftLog](https://github.com/apple/swift-log) `LogHandler` implementations for customizable logging to a console.
diff --git a/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json b/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json
new file mode 100644
index 00000000..fdbbdb1e
--- /dev/null
+++ b/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json
@@ -0,0 +1,21 @@
+{
+ "theme": {
+ "aside": { "border-radius": "6px", "border-style": "double", "border-width": "3px" },
+ "border-radius": "0",
+ "button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+ "code": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
+ "color": {
+ "consolekit": "#392048",
+ "documentation-intro-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
+ "documentation-intro-accent": "var(--color-consolekit)",
+ "logo-base": { "dark": "#fff", "light": "#000" },
+ "logo-shape": { "dark": "#000", "light": "#fff" },
+ "fill": { "dark": "#000", "light": "#fff" }
+ },
+ "icons": { "technology": "/consolekit/images/vapor-consolekit-logo.svg" }
+ },
+ "features": {
+ "quickNavigation": { "enable": true },
+ "i18n": { "enable": true }
+ }
+}
diff --git a/Sources/ConsoleKit/Input/Console+Ask.swift b/Sources/ConsoleKitTerminal/Input/Console+Ask.swift
similarity index 100%
rename from Sources/ConsoleKit/Input/Console+Ask.swift
rename to Sources/ConsoleKitTerminal/Input/Console+Ask.swift
diff --git a/Sources/ConsoleKit/Input/Console+Choose.swift b/Sources/ConsoleKitTerminal/Input/Console+Choose.swift
similarity index 100%
rename from Sources/ConsoleKit/Input/Console+Choose.swift
rename to Sources/ConsoleKitTerminal/Input/Console+Choose.swift
diff --git a/Sources/ConsoleKit/Input/Console+Confirm.swift b/Sources/ConsoleKitTerminal/Input/Console+Confirm.swift
similarity index 100%
rename from Sources/ConsoleKit/Input/Console+Confirm.swift
rename to Sources/ConsoleKitTerminal/Input/Console+Confirm.swift
diff --git a/Sources/ConsoleKit/Input/Console+Input.swift b/Sources/ConsoleKitTerminal/Input/Console+Input.swift
similarity index 100%
rename from Sources/ConsoleKit/Input/Console+Input.swift
rename to Sources/ConsoleKitTerminal/Input/Console+Input.swift
diff --git a/Sources/ConsoleKit/Output/Console+Center.swift b/Sources/ConsoleKitTerminal/Output/Console+Center.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/Console+Center.swift
rename to Sources/ConsoleKitTerminal/Output/Console+Center.swift
diff --git a/Sources/ConsoleKit/Output/Console+Output.swift b/Sources/ConsoleKitTerminal/Output/Console+Output.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/Console+Output.swift
rename to Sources/ConsoleKitTerminal/Output/Console+Output.swift
diff --git a/Sources/ConsoleKit/Output/Console+Wait.swift b/Sources/ConsoleKitTerminal/Output/Console+Wait.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/Console+Wait.swift
rename to Sources/ConsoleKitTerminal/Output/Console+Wait.swift
diff --git a/Sources/ConsoleKit/Output/ConsoleColor.swift b/Sources/ConsoleKitTerminal/Output/ConsoleColor.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/ConsoleColor.swift
rename to Sources/ConsoleKitTerminal/Output/ConsoleColor.swift
diff --git a/Sources/ConsoleKit/Output/ConsoleStyle.swift b/Sources/ConsoleKitTerminal/Output/ConsoleStyle.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/ConsoleStyle.swift
rename to Sources/ConsoleKitTerminal/Output/ConsoleStyle.swift
diff --git a/Sources/ConsoleKit/Output/ConsoleText.swift b/Sources/ConsoleKitTerminal/Output/ConsoleText.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/ConsoleText.swift
rename to Sources/ConsoleKitTerminal/Output/ConsoleText.swift
diff --git a/Sources/ConsoleKit/Output/ConsoleTextFragment.swift b/Sources/ConsoleKitTerminal/Output/ConsoleTextFragment.swift
similarity index 100%
rename from Sources/ConsoleKit/Output/ConsoleTextFragment.swift
rename to Sources/ConsoleKitTerminal/Output/ConsoleTextFragment.swift
diff --git a/Sources/ConsoleKit/Terminal/ANSI.swift b/Sources/ConsoleKitTerminal/Terminal/ANSI.swift
similarity index 100%
rename from Sources/ConsoleKit/Terminal/ANSI.swift
rename to Sources/ConsoleKitTerminal/Terminal/ANSI.swift
diff --git a/Sources/ConsoleKit/Console.swift b/Sources/ConsoleKitTerminal/Terminal/Console.swift
similarity index 100%
rename from Sources/ConsoleKit/Console.swift
rename to Sources/ConsoleKitTerminal/Terminal/Console.swift
diff --git a/Sources/ConsoleKit/Terminal/Terminal.swift b/Sources/ConsoleKitTerminal/Terminal/Terminal.swift
similarity index 100%
rename from Sources/ConsoleKit/Terminal/Terminal.swift
rename to Sources/ConsoleKitTerminal/Terminal/Terminal.swift
diff --git a/Sources/ConsoleKit/Terminal/readpassphrase_linux.swift b/Sources/ConsoleKitTerminal/Terminal/readpassphrase_linux.swift
similarity index 100%
rename from Sources/ConsoleKit/Terminal/readpassphrase_linux.swift
rename to Sources/ConsoleKitTerminal/Terminal/readpassphrase_linux.swift
diff --git a/Sources/ConsoleKit/Utilities/AnySendableHashable.swift b/Sources/ConsoleKitTerminal/Utilities/AnySendableHashable.swift
similarity index 100%
rename from Sources/ConsoleKit/Utilities/AnySendableHashable.swift
rename to Sources/ConsoleKitTerminal/Utilities/AnySendableHashable.swift
diff --git a/Sources/ConsoleKit/Utilities/ConsoleLogger.swift b/Sources/ConsoleKitTerminal/Utilities/ConsoleLogger.swift
similarity index 100%
rename from Sources/ConsoleKit/Utilities/ConsoleLogger.swift
rename to Sources/ConsoleKitTerminal/Utilities/ConsoleLogger.swift
diff --git a/Sources/ConsoleKit/Utilities/LoggerFragment.swift b/Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift
similarity index 100%
rename from Sources/ConsoleKit/Utilities/LoggerFragment.swift
rename to Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift
diff --git a/Tests/AsyncConsoleKitTests/AsyncCommandErrorTests.swift b/Tests/AsyncConsoleKitTests/AsyncCommandErrorTests.swift
index 5b2b1a23..1a17c07a 100644
--- a/Tests/AsyncConsoleKitTests/AsyncCommandErrorTests.swift
+++ b/Tests/AsyncConsoleKitTests/AsyncCommandErrorTests.swift
@@ -1,4 +1,4 @@
-@testable import ConsoleKit
+@testable import ConsoleKitCommands
import XCTest
final class AsyncCommandErrorTests: XCTestCase {
diff --git a/Tests/AsyncConsoleKitTests/AsyncUtilities.swift b/Tests/AsyncConsoleKitTests/AsyncUtilities.swift
index 085d446d..44d6eaa0 100644
--- a/Tests/AsyncConsoleKitTests/AsyncUtilities.swift
+++ b/Tests/AsyncConsoleKitTests/AsyncUtilities.swift
@@ -8,14 +8,10 @@ final class TestGroup: AsyncCommandGroup {
struct Signature: CommandSignature {
@Flag(name: "version", help: "Prints the version")
var version: Bool
- init() { }
+ init() {}
}
- let commands: [String : AnyAsyncCommand] = [
- "test": TestCommand(),
- "sub": SubGroup()
- ]
-
+ let commands: [String : any AnyAsyncCommand] = ["test": TestCommand(), "sub": SubGroup()]
let help: String = "This is a test grouping!"
func run(using context: CommandContext, signature: Signature) async throws {
@@ -29,12 +25,10 @@ final class SubGroup: AsyncCommandGroup {
struct Signature: CommandSignature {
@Flag(name: "version", help: "Prints the version")
var version: Bool
- init() { }
+ init() {}
}
- let commands: [String : AnyAsyncCommand] = [
- "test": TestCommand()
- ]
+ let commands: [String: any AnyAsyncCommand] = ["test": TestCommand()]
let help: String = "This is a test sub grouping!"
@@ -65,7 +59,7 @@ final class TestCommand: AsyncCommand {
""")
var baz: Bool
- init() { }
+ init() {}
}
let help: String = "This is a test command"
@@ -86,7 +80,7 @@ final class StrictCommand: AsyncCommand {
@Argument(name: "bool")
var bool: Bool
- init() { }
+ init() {}
}
let help: String = "I error if you pass in bad values"
@@ -100,54 +94,33 @@ final class TestConsole: Console {
let _testInputQueue: NIOLockedValueBox<[String]> = NIOLockedValueBox([])
var testInputQueue: [String] {
- get {
- self._testInputQueue.withLockedValue { $0 }
- }
- set {
- self._testInputQueue.withLockedValue { $0 = newValue }
- }
+ get { self._testInputQueue.withLockedValue { $0 } }
+ set { self._testInputQueue.withLockedValue { $0 = newValue } }
}
let _testOutputQueue: NIOLockedValueBox<[String]> = NIOLockedValueBox([])
var testOutputQueue: [String] {
- get {
- self._testOutputQueue.withLockedValue { $0 }
- }
- set {
- self._testOutputQueue.withLockedValue { $0 = newValue }
- }
+ get { self._testOutputQueue.withLockedValue { $0 } }
+ set { self._testOutputQueue.withLockedValue { $0 = newValue } }
}
- let _userInfo: NIOLockedValueBox<[AnySendableHashable: Sendable]> = NIOLockedValueBox([:])
- var userInfo: [AnySendableHashable: Sendable] {
- get {
- self._userInfo.withLockedValue { $0 }
- }
- set {
- self._userInfo.withLockedValue { $0 = newValue }
- }
- }
-
- init() {
- self.testOutputQueue = []
- self.userInfo = [:]
+ let _userInfo: NIOLockedValueBox<[AnySendableHashable: any Sendable]> = NIOLockedValueBox([:])
+ var userInfo: [AnySendableHashable: any Sendable] {
+ get { self._userInfo.withLockedValue { $0 } }
+ set { self._userInfo.withLockedValue { $0 = newValue } }
}
func input(isSecure: Bool) -> String {
- return testInputQueue.popLast() ?? ""
+ self.testInputQueue.popLast() ?? ""
}
func output(_ text: ConsoleText, newLine: Bool) {
- testOutputQueue.insert(text.description + (newLine ? "\n" : ""), at: 0)
+ self.testOutputQueue.insert(text.description + (newLine ? "\n" : ""), at: 0)
}
- func report(error: String, newLine: Bool) {
- //
- }
+ func report(error: String, newLine: Bool) {}
- func clear(_ type: ConsoleClear) {
- //
- }
+ func clear(_ type: ConsoleClear) {}
- var size: (width: Int, height: Int) { return (0, 0) }
+ var size: (width: Int, height: Int) { (width: 0, height: 0) }
}
diff --git a/Tests/ConsoleKitPerformanceTests/ConsoleLoggerPerformanceTests.swift b/Tests/ConsoleKitPerformanceTests/ConsoleLoggerPerformanceTests.swift
index 646c5db4..0580f9c5 100644
--- a/Tests/ConsoleKitPerformanceTests/ConsoleLoggerPerformanceTests.swift
+++ b/Tests/ConsoleKitPerformanceTests/ConsoleLoggerPerformanceTests.swift
@@ -1,10 +1,3 @@
-//
-// ConsoleLoggerPerformanceTests.swift
-//
-//
-// Created by Cole Kurkowski on 8/19/23.
-//
-
import ConsoleKit
import Logging
import XCTest
@@ -14,32 +7,20 @@ final class TestConsole: Console {
let lastOutput: NIOLockedValueBox = .init(nil)
let _userInfo: NIOLockedValueBox<[AnySendableHashable: any Sendable]> = .init([:])
- var userInfo: [AnySendableHashable : Sendable] {
- get {
- _userInfo.withLockedValue { $0 }
- }
- set {
- _userInfo.withLockedValue { $0 = newValue }
- }
+ var userInfo: [AnySendableHashable : any Sendable] {
+ get { _userInfo.withLockedValue { $0 } }
+ set { _userInfo.withLockedValue { $0 = newValue } }
}
- func input(isSecure: Bool) -> String {
- ""
- }
+ func input(isSecure: Bool) -> String { "" }
- func output(_ text: ConsoleText, newLine: Bool) {
-
- }
+ func output(_ text: ConsoleText, newLine: Bool) {}
- func report(error: String, newLine: Bool) {
- //
- }
+ func report(error: String, newLine: Bool) {}
- func clear(_ type: ConsoleClear) {
- //
- }
+ func clear(_ type: ConsoleClear) {}
- var size: (width: Int, height: Int) { return (0, 0) }
+ var size: (width: Int, height: Int) { (width: 0, height: 0) }
}
class ConsoleLoggerPerformanceTests: XCTestCase {
diff --git a/Tests/ConsoleKitTests/ActivityTests.swift b/Tests/ConsoleKitTests/ActivityTests.swift
index 4fd77460..3fac8366 100644
--- a/Tests/ConsoleKitTests/ActivityTests.swift
+++ b/Tests/ConsoleKitTests/ActivityTests.swift
@@ -1,14 +1,14 @@
-@testable import ConsoleKit
+@testable import ConsoleKitTerminal
import XCTest
final class ActivityTests: XCTestCase {
func testActivityWidthKey() {
- var dict = [AnyHashable: String]()
+ var dict = [AnySendableHashable: String]()
- dict[AnyHashable(ActivityBarWidthKey())] = "width key"
- dict[AnyHashable("ConsoleKit.ActivityBarWidthKey")] = "string key"
+ dict[AnySendableHashable(ActivityBarWidthKey())] = "width key"
+ dict[AnySendableHashable("ConsoleKit.ActivityBarWidthKey")] = "string key"
- XCTAssertEqual(dict[AnyHashable(ActivityBarWidthKey())], "width key")
- XCTAssertEqual(dict[AnyHashable("ConsoleKit.ActivityBarWidthKey")], "string key")
+ XCTAssertEqual(dict[AnySendableHashable(ActivityBarWidthKey())], "width key")
+ XCTAssertEqual(dict[AnySendableHashable("ConsoleKit.ActivityBarWidthKey")], "string key")
}
}
diff --git a/Tests/ConsoleKitTests/CommandErrorTests.swift b/Tests/ConsoleKitTests/CommandErrorTests.swift
index 373e86b5..c98c2c72 100644
--- a/Tests/ConsoleKitTests/CommandErrorTests.swift
+++ b/Tests/ConsoleKitTests/CommandErrorTests.swift
@@ -1,4 +1,4 @@
-@testable import ConsoleKit
+@testable import ConsoleKitCommands
import XCTest
class CommandErrorTests: XCTestCase {
diff --git a/Tests/ConsoleKitTests/TerminalTests.swift b/Tests/ConsoleKitTests/TerminalTests.swift
index 0a938ce5..73223259 100644
--- a/Tests/ConsoleKitTests/TerminalTests.swift
+++ b/Tests/ConsoleKitTests/TerminalTests.swift
@@ -1,5 +1,5 @@
import XCTest
-@testable import ConsoleKit
+@testable import ConsoleKitTerminal
class TerminalTests: XCTestCase {
func testStylizeForeground() throws {
diff --git a/Tests/ConsoleKitTests/Utilities.swift b/Tests/ConsoleKitTests/Utilities.swift
index 9baaf0e8..df5b86ea 100644
--- a/Tests/ConsoleKitTests/Utilities.swift
+++ b/Tests/ConsoleKitTests/Utilities.swift
@@ -8,10 +8,10 @@ final class TestGroup: CommandGroup {
struct Signature: CommandSignature {
@Flag(name: "version", help: "Prints the version")
var version: Bool
- init() { }
+ init() {}
}
- let commands: [String : AnyCommand] = [
+ let commands: [String: any AnyCommand] = [
"test": TestCommand(),
"sub": SubGroup()
]
@@ -29,10 +29,10 @@ final class SubGroup: CommandGroup {
struct Signature: CommandSignature {
@Flag(name: "version", help: "Prints the version")
var version: Bool
- init() { }
+ init() {}
}
- let commands: [String : AnyCommand] = [
+ let commands: [String: any AnyCommand] = [
"test": TestCommand()
]
@@ -65,7 +65,7 @@ final class TestCommand: Command {
""")
var baz: Bool
- init() { }
+ init() {}
}
let help: String = "This is a test command"
@@ -86,7 +86,7 @@ final class StrictCommand: Command {
@Argument(name: "bool")
var bool: Bool
- init() { }
+ init() {}
}
var help: String {
"I error if you pass in bad values"
@@ -101,32 +101,20 @@ final class TestConsole: Console {
let _testInputQueue: NIOLockedValueBox<[String]> = NIOLockedValueBox([])
var testInputQueue: [String] {
- get {
- self._testInputQueue.withLockedValue { $0 }
- }
- set {
- self._testInputQueue.withLockedValue { $0 = newValue }
- }
+ get { self._testInputQueue.withLockedValue { $0 } }
+ set { self._testInputQueue.withLockedValue { $0 = newValue } }
}
let _testOutputQueue: NIOLockedValueBox<[String]> = NIOLockedValueBox([])
var testOutputQueue: [String] {
- get {
- self._testOutputQueue.withLockedValue { $0 }
- }
- set {
- self._testOutputQueue.withLockedValue { $0 = newValue }
- }
+ get { self._testOutputQueue.withLockedValue { $0 } }
+ set { self._testOutputQueue.withLockedValue { $0 = newValue } }
}
- let _userInfo: NIOLockedValueBox<[AnySendableHashable: Sendable]> = NIOLockedValueBox([:])
- var userInfo: [AnySendableHashable: Sendable] {
- get {
- self._userInfo.withLockedValue { $0 }
- }
- set {
- self._userInfo.withLockedValue { $0 = newValue }
- }
+ let _userInfo: NIOLockedValueBox<[AnySendableHashable: any Sendable]> = NIOLockedValueBox([:])
+ var userInfo: [AnySendableHashable: any Sendable] {
+ get { self._userInfo.withLockedValue { $0 } }
+ set { self._userInfo.withLockedValue { $0 = newValue } }
}
init() {
@@ -143,13 +131,9 @@ final class TestConsole: Console {
testOutputQueue.insert(text.description + (newLine ? "\n" : ""), at: 0)
}
- func report(error: String, newLine: Bool) {
- //
- }
+ func report(error: String, newLine: Bool) {}
- func clear(_ type: ConsoleClear) {
- //
- }
+ func clear(_ type: ConsoleClear) {}
- var size: (width: Int, height: Int) { return (0, 0) }
+ var size: (width: Int, height: Int) { (width: 0, height: 0) }
}