From 7454699306651494cb6916aaecf34f2631214d59 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Mon, 13 Nov 2023 11:23:31 -0600 Subject: [PATCH 1/6] Split ConsoleKit into two functional targets - one for terminal interaction, one for command handling, plus an umbrella for compatibility. Also update README, and docs images. Clean up several bits of code. --- .github/CONTRIBUTING.md | 5 - .github/workflows/api-docs.yml | 4 +- Package.swift | 74 +++++++++----- Package@swift-5.9.swift | 96 +++++++++++++------ README.md | 17 ++-- Sources/ConsoleKit/Command/Utilities.swift | 47 --------- .../ConsoleKit/Docs.docc/images/article.svg | 1 - .../images/vapor-consolekit-logo.svg | 53 ++++------ .../ConsoleKit/Docs.docc/theme-settings.json | 61 ++++-------- Sources/ConsoleKit/Exports.swift | 2 + .../ConsoleKitAsyncExample/DemoCommand.swift | 16 ++-- .../{entry.swift => entrypoint.swift} | 3 +- .../AnyCommand.swift | 0 .../Argument.swift | 0 .../Async/AnyAsyncCommand.swift | 0 .../Async/AsyncCommand.swift | 2 + .../Async/AsyncCommandGroup.swift | 6 +- .../Async/AsyncCommands.swift | 0 .../GenerateAsyncAutocompleteCommand.swift | 0 .../Command.swift | 10 +- .../CommandContext.swift | 2 + .../CommandError.swift | 0 .../CommandGroup.swift | 6 +- .../CommandInput.swift | 0 .../CommandSignature.swift | 0 .../Commands.swift | 0 .../Completion.swift | 0 .../Console+Run.swift | 2 + .../ConsoleError.swift | 0 .../images/vapor-consolekit-logo.svg | 21 ++++ Sources/ConsoleKitCommands/Docs.docc/index.md | 13 +++ .../Docs.docc/theme-settings.json | 21 ++++ .../Command => ConsoleKitCommands}/Flag.swift | 0 .../GenerateAutocompleteCommand.swift | 0 .../Option.swift | 0 .../String+LevenshteinDistance.swift | 0 Sources/ConsoleKitCommands/Utilities.swift | 29 ++++++ Sources/ConsoleKitExample/DemoCommand.swift | 18 ++-- Sources/ConsoleKitExample/entrypoint.swift | 22 +++++ Sources/ConsoleKitExample/main.swift | 19 ---- .../Activity/ActivityBar.swift | 0 .../Activity/ActivityIndicator.swift | 0 .../Activity/ActivityIndicatorRenderer.swift | 0 .../Activity/ActivityIndicatorState.swift | 0 .../Activity/CustomActivity.swift | 0 .../Activity/LoadingBar.swift | 0 .../Activity/ProgressBar.swift | 0 .../Clear/Console+Clear.swift | 0 .../Clear/Console+Ephemeral.swift | 0 .../Clear/ConsoleClear.swift | 0 .../images/vapor-consolekit-logo.svg | 21 ++++ Sources/ConsoleKitTerminal/Docs.docc/index.md | 13 +++ .../Docs.docc/theme-settings.json | 21 ++++ .../Input/Console+Ask.swift | 0 .../Input/Console+Choose.swift | 0 .../Input/Console+Confirm.swift | 0 .../Input/Console+Input.swift | 0 .../Output/Console+Center.swift | 0 .../Output/Console+Output.swift | 0 .../Output/Console+Wait.swift | 0 .../Output/ConsoleColor.swift | 0 .../Output/ConsoleStyle.swift | 0 .../Output/ConsoleText.swift | 0 .../Output/ConsoleTextFragment.swift | 0 .../Terminal/ANSI.swift | 0 .../Terminal}/Console.swift | 0 .../Terminal/Terminal.swift | 0 .../Terminal/readpassphrase_linux.swift | 0 .../Utilities/AnySendableHashable.swift | 0 .../Utilities/ConsoleLogger.swift | 0 .../Utilities/LoggerFragment.swift | 0 .../AsyncConsoleKitTests/AsyncUtilities.swift | 65 ++++--------- .../ConsoleLoggerPerformanceTests.swift | 35 ++----- Tests/ConsoleKitTests/ActivityTests.swift | 12 +-- Tests/ConsoleKitTests/TerminalTests.swift | 2 +- Tests/ConsoleKitTests/Utilities.swift | 50 ++++------ 76 files changed, 415 insertions(+), 354 deletions(-) delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 Sources/ConsoleKit/Command/Utilities.swift delete mode 100644 Sources/ConsoleKit/Docs.docc/images/article.svg create mode 100644 Sources/ConsoleKit/Exports.swift rename Sources/ConsoleKitAsyncExample/{entry.swift => entrypoint.swift} (90%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/AnyCommand.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Argument.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Async/AnyAsyncCommand.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Async/AsyncCommand.swift (99%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Async/AsyncCommandGroup.swift (95%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Async/AsyncCommands.swift (100%) rename Sources/{ConsoleKit/Utilities => ConsoleKitCommands/Async}/GenerateAsyncAutocompleteCommand.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Command.swift (96%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/CommandContext.swift (92%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/CommandError.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/CommandGroup.swift (95%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/CommandInput.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/CommandSignature.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Commands.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Completion.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Console+Run.swift (99%) rename Sources/{ConsoleKit/Utilities => ConsoleKitCommands}/ConsoleError.swift (100%) create mode 100644 Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg create mode 100644 Sources/ConsoleKitCommands/Docs.docc/index.md create mode 100644 Sources/ConsoleKitCommands/Docs.docc/theme-settings.json rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Flag.swift (100%) rename Sources/{ConsoleKit/Utilities => ConsoleKitCommands}/GenerateAutocompleteCommand.swift (100%) rename Sources/{ConsoleKit/Command => ConsoleKitCommands}/Option.swift (100%) rename Sources/{ConsoleKit/Utilities => ConsoleKitCommands}/String+LevenshteinDistance.swift (100%) create mode 100644 Sources/ConsoleKitCommands/Utilities.swift create mode 100644 Sources/ConsoleKitExample/entrypoint.swift delete mode 100644 Sources/ConsoleKitExample/main.swift rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/ActivityBar.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/ActivityIndicator.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/ActivityIndicatorRenderer.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/ActivityIndicatorState.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/CustomActivity.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/LoadingBar.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Activity/ProgressBar.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Clear/Console+Clear.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Clear/Console+Ephemeral.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Clear/ConsoleClear.swift (100%) create mode 100644 Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg create mode 100644 Sources/ConsoleKitTerminal/Docs.docc/index.md create mode 100644 Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json rename Sources/{ConsoleKit => ConsoleKitTerminal}/Input/Console+Ask.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Input/Console+Choose.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Input/Console+Confirm.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Input/Console+Input.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/Console+Center.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/Console+Output.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/Console+Wait.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/ConsoleColor.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/ConsoleStyle.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/ConsoleText.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Output/ConsoleTextFragment.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Terminal/ANSI.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal/Terminal}/Console.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Terminal/Terminal.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Terminal/readpassphrase_linux.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Utilities/AnySendableHashable.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Utilities/ConsoleLogger.swift (100%) rename Sources/{ConsoleKit => ConsoleKitTerminal}/Utilities/LoggerFragment.swift (100%) 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..d1cc93ac 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@

- - - ConsoleKit + + + ConsoleKit

-Documentation -Team Chat -MIT License -Continuous Integration -Swift 5.6 +Documentation +Team Chat +MIT License +Continuous Integration + +Swift 5.7+


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/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/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/AnyCommand.swift b/Sources/ConsoleKitCommands/AnyCommand.swift similarity index 100% rename from Sources/ConsoleKit/Command/AnyCommand.swift rename to Sources/ConsoleKitCommands/AnyCommand.swift diff --git a/Sources/ConsoleKit/Command/Argument.swift b/Sources/ConsoleKitCommands/Argument.swift similarity index 100% rename from Sources/ConsoleKit/Command/Argument.swift rename to Sources/ConsoleKitCommands/Argument.swift diff --git a/Sources/ConsoleKit/Command/Async/AnyAsyncCommand.swift b/Sources/ConsoleKitCommands/Async/AnyAsyncCommand.swift similarity index 100% rename from Sources/ConsoleKit/Command/Async/AnyAsyncCommand.swift rename to Sources/ConsoleKitCommands/Async/AnyAsyncCommand.swift diff --git a/Sources/ConsoleKit/Command/Async/AsyncCommand.swift b/Sources/ConsoleKitCommands/Async/AsyncCommand.swift similarity index 99% rename from Sources/ConsoleKit/Command/Async/AsyncCommand.swift rename to Sources/ConsoleKitCommands/Async/AsyncCommand.swift index 166edbc0..9fdeb846 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 diff --git a/Sources/ConsoleKit/Command/Async/AsyncCommandGroup.swift b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift similarity index 95% rename from Sources/ConsoleKit/Command/Async/AsyncCommandGroup.swift rename to Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift index 759e9ba7..7b6099db 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. @@ -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.max(by: { $0.key.count < $1.key.count })?.key.count ?? 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/Command.swift b/Sources/ConsoleKitCommands/Command.swift similarity index 96% rename from Sources/ConsoleKit/Command/Command.swift rename to Sources/ConsoleKitCommands/Command.swift index b141954e..b54483ba 100644 --- a/Sources/ConsoleKit/Command/Command.swift +++ b/Sources/ConsoleKitCommands/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 @@ -138,8 +140,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.max(by: { $0.count < $1.count })?.count ?? 0) + 2 + if !self.arguments.isEmpty { context.console.print() context.console.output("Arguments:".consoleText(.info)) for argument in self.arguments { @@ -152,7 +154,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 +167,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/CommandContext.swift similarity index 92% rename from Sources/ConsoleKit/Command/CommandContext.swift rename to Sources/ConsoleKitCommands/CommandContext.swift index 4dd04dae..d12696b1 100644 --- a/Sources/ConsoleKit/Command/CommandContext.swift +++ b/Sources/ConsoleKitCommands/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/CommandError.swift similarity index 100% rename from Sources/ConsoleKit/Command/CommandError.swift rename to Sources/ConsoleKitCommands/CommandError.swift diff --git a/Sources/ConsoleKit/Command/CommandGroup.swift b/Sources/ConsoleKitCommands/CommandGroup.swift similarity index 95% rename from Sources/ConsoleKit/Command/CommandGroup.swift rename to Sources/ConsoleKitCommands/CommandGroup.swift index bbebb62e..56eb2e71 100644 --- a/Sources/ConsoleKit/Command/CommandGroup.swift +++ b/Sources/ConsoleKitCommands/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. @@ -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.max(by: { $0.key.count < $1.key.count })?.key.count ?? 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/CommandInput.swift similarity index 100% rename from Sources/ConsoleKit/Command/CommandInput.swift rename to Sources/ConsoleKitCommands/CommandInput.swift diff --git a/Sources/ConsoleKit/Command/CommandSignature.swift b/Sources/ConsoleKitCommands/CommandSignature.swift similarity index 100% rename from Sources/ConsoleKit/Command/CommandSignature.swift rename to Sources/ConsoleKitCommands/CommandSignature.swift diff --git a/Sources/ConsoleKit/Command/Commands.swift b/Sources/ConsoleKitCommands/Commands.swift similarity index 100% rename from Sources/ConsoleKit/Command/Commands.swift rename to Sources/ConsoleKitCommands/Commands.swift diff --git a/Sources/ConsoleKit/Command/Completion.swift b/Sources/ConsoleKitCommands/Completion.swift similarity index 100% rename from Sources/ConsoleKit/Command/Completion.swift rename to Sources/ConsoleKitCommands/Completion.swift diff --git a/Sources/ConsoleKit/Command/Console+Run.swift b/Sources/ConsoleKitCommands/Console+Run.swift similarity index 99% rename from Sources/ConsoleKit/Command/Console+Run.swift rename to Sources/ConsoleKitCommands/Console+Run.swift index d27c9200..09e5e4b4 100644 --- a/Sources/ConsoleKit/Command/Console+Run.swift +++ b/Sources/ConsoleKitCommands/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/ConsoleKit/Utilities/ConsoleError.swift b/Sources/ConsoleKitCommands/ConsoleError.swift similarity index 100% rename from Sources/ConsoleKit/Utilities/ConsoleError.swift rename to Sources/ConsoleKitCommands/ConsoleError.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..77c4a8a6 --- /dev/null +++ b/Sources/ConsoleKitCommands/Docs.docc/index.md @@ -0,0 +1,13 @@ +# ``ConsoleKit`` + +@Metadata { + @TitleHeading(Package) +} + +ConsoleKit provides utilities for interacting with a console via a Swift application. It provides: + +* 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. 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/Flag.swift b/Sources/ConsoleKitCommands/Flag.swift similarity index 100% rename from Sources/ConsoleKit/Command/Flag.swift rename to Sources/ConsoleKitCommands/Flag.swift diff --git a/Sources/ConsoleKit/Utilities/GenerateAutocompleteCommand.swift b/Sources/ConsoleKitCommands/GenerateAutocompleteCommand.swift similarity index 100% rename from Sources/ConsoleKit/Utilities/GenerateAutocompleteCommand.swift rename to Sources/ConsoleKitCommands/GenerateAutocompleteCommand.swift diff --git a/Sources/ConsoleKit/Command/Option.swift b/Sources/ConsoleKitCommands/Option.swift similarity index 100% rename from Sources/ConsoleKit/Command/Option.swift rename to Sources/ConsoleKitCommands/Option.swift diff --git a/Sources/ConsoleKit/Utilities/String+LevenshteinDistance.swift b/Sources/ConsoleKitCommands/String+LevenshteinDistance.swift similarity index 100% rename from Sources/ConsoleKit/Utilities/String+LevenshteinDistance.swift rename to Sources/ConsoleKitCommands/String+LevenshteinDistance.swift diff --git a/Sources/ConsoleKitCommands/Utilities.swift b/Sources/ConsoleKitCommands/Utilities.swift new file mode 100644 index 00000000..569e9c8b --- /dev/null +++ b/Sources/ConsoleKitCommands/Utilities.swift @@ -0,0 +1,29 @@ +import protocol ConsoleKitTerminal.Console +import struct ConsoleKitTerminal.ConsoleStyle + +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 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..d624913c --- /dev/null +++ b/Sources/ConsoleKitExample/entrypoint.swift @@ -0,0 +1,22 @@ +import ConsoleKit +import Foundation +import Logging + +@main +struct ConsoleKitExample { + static func main() { + let 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)") + } + } +} 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..77c4a8a6 --- /dev/null +++ b/Sources/ConsoleKitTerminal/Docs.docc/index.md @@ -0,0 +1,13 @@ +# ``ConsoleKit`` + +@Metadata { + @TitleHeading(Package) +} + +ConsoleKit provides utilities for interacting with a console via a Swift application. It provides: + +* 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. 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/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/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) } } From 18a1686ed93f3956063fed6559795e9f5c8d41f9 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Mon, 13 Nov 2023 11:35:19 -0600 Subject: [PATCH 2/6] Fixup tests --- Sources/ConsoleKitExample/entrypoint.swift | 3 +-- Tests/AsyncConsoleKitTests/AsyncCommandErrorTests.swift | 2 +- Tests/ConsoleKitTests/CommandErrorTests.swift | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/ConsoleKitExample/entrypoint.swift b/Sources/ConsoleKitExample/entrypoint.swift index d624913c..12aa0af2 100644 --- a/Sources/ConsoleKitExample/entrypoint.swift +++ b/Sources/ConsoleKitExample/entrypoint.swift @@ -6,8 +6,7 @@ import Logging struct ConsoleKitExample { static func main() { let console = Terminal() - var input = CommandInput(arguments: ProcessInfo.processInfo.arguments) - var context = CommandContext(console: console, input: input) + let input = CommandInput(arguments: ProcessInfo.processInfo.arguments) var commands = Commands(enableAutocomplete: true) commands.use(DemoCommand(), as: "demo", isDefault: false) 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/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 { From aa96b6fe2eb406ed23aec796e77053a70ce9bf52 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Tue, 14 Nov 2023 09:45:40 -0600 Subject: [PATCH 3/6] Apply suggestions from code review Co-authored-by: Mahdi Bahrami Co-authored-by: Tim Condon <0xTim@users.noreply.github.com> --- Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift | 2 +- Sources/ConsoleKitCommands/Command.swift | 2 +- Sources/ConsoleKitCommands/CommandGroup.swift | 2 +- Sources/ConsoleKitCommands/Docs.docc/index.md | 2 +- Sources/ConsoleKitCommands/Utilities.swift | 4 ++-- Sources/ConsoleKitTerminal/Docs.docc/index.md | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift index 7b6099db..5bdcd382 100644 --- a/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift +++ b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift @@ -62,7 +62,7 @@ extension AsyncCommandGroup { context.console.print(self.help) } - let padding = (self.commands.max(by: { $0.key.count < $1.key.count })?.key.count ?? 0) + 2 + let padding = (self.commands.map(\.key.count).max() ?? 0) + 2 if !self.commands.isEmpty { context.console.print() context.console.output("Commands:".consoleText(.success)) diff --git a/Sources/ConsoleKitCommands/Command.swift b/Sources/ConsoleKitCommands/Command.swift index b54483ba..3ceb5c70 100644 --- a/Sources/ConsoleKitCommands/Command.swift +++ b/Sources/ConsoleKitCommands/Command.swift @@ -140,7 +140,7 @@ extension CommandSignature { + self.arguments.map { $0.name } + self.flags.map { $0.name } - let padding = (names.max(by: { $0.count < $1.count })?.count ?? 0) + 2 + let padding = (names.map(\.count).max() ?? 0) + 2 if !self.arguments.isEmpty { context.console.print() context.console.output("Arguments:".consoleText(.info)) diff --git a/Sources/ConsoleKitCommands/CommandGroup.swift b/Sources/ConsoleKitCommands/CommandGroup.swift index 56eb2e71..fd1f317c 100644 --- a/Sources/ConsoleKitCommands/CommandGroup.swift +++ b/Sources/ConsoleKitCommands/CommandGroup.swift @@ -62,7 +62,7 @@ extension CommandGroup { context.console.print(self.help) } - let padding = (self.commands.max(by: { $0.key.count < $1.key.count })?.key.count ?? 0) + 2 + let padding = (self.commands.map(\.key.count).max() ?? 0) + 2 if !self.commands.isEmpty { context.console.print() context.console.output("Commands:".consoleText(.success)) diff --git a/Sources/ConsoleKitCommands/Docs.docc/index.md b/Sources/ConsoleKitCommands/Docs.docc/index.md index 77c4a8a6..06fd7190 100644 --- a/Sources/ConsoleKitCommands/Docs.docc/index.md +++ b/Sources/ConsoleKitCommands/Docs.docc/index.md @@ -1,4 +1,4 @@ -# ``ConsoleKit`` +# ``ConsoleKitCommands`` @Metadata { @TitleHeading(Package) diff --git a/Sources/ConsoleKitCommands/Utilities.swift b/Sources/ConsoleKitCommands/Utilities.swift index 569e9c8b..216810a6 100644 --- a/Sources/ConsoleKitCommands/Utilities.swift +++ b/Sources/ConsoleKitCommands/Utilities.swift @@ -4,10 +4,10 @@ import struct ConsoleKitTerminal.ConsoleStyle extension Array { /// Pops the first element from the array. mutating func popFirst() -> Element? { - guard let pop = first else { + guard let pop = self.first else { return nil } - self = Array(dropFirst()) + self = Array(self.dropFirst()) return pop } } diff --git a/Sources/ConsoleKitTerminal/Docs.docc/index.md b/Sources/ConsoleKitTerminal/Docs.docc/index.md index 77c4a8a6..77930fe8 100644 --- a/Sources/ConsoleKitTerminal/Docs.docc/index.md +++ b/Sources/ConsoleKitTerminal/Docs.docc/index.md @@ -1,4 +1,4 @@ -# ``ConsoleKit`` +# ``ConsoleKitTerminal`` @Metadata { @TitleHeading(Package) From 08a3c6b193fa72bc0e8b45c6eacbc481af9617f4 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Tue, 14 Nov 2023 10:55:40 -0600 Subject: [PATCH 4/6] Fix up docs per PR feedback. More code cleanup. Apply some of the lessons learned from https://github.com/apple/swift-argument-parser/pull/590, pretty much just for the hell of it. Deprecate `ConsoleErrror`. --- Sources/ConsoleKit/Docs.docc/index.md | 8 +-- .../Async/AnyAsyncCommand.swift | 2 +- .../Async/AsyncCommand.swift | 9 ++-- .../Async/AsyncCommandGroup.swift | 2 +- .../{ => Base}/AnyCommand.swift | 2 +- .../{ => Base}/Command.swift | 9 ++-- .../{ => Base}/CommandContext.swift | 0 .../{ => Base}/CommandError.swift | 54 ++++++++++--------- .../{ => Base}/CommandGroup.swift | 2 +- .../{ => Base}/CommandInput.swift | 0 .../{ => Base}/Commands.swift | 0 .../{ => Base}/Console+Run.swift | 0 .../Base/ConsoleError.swift | 1 + .../{ => Completion}/Completion.swift | 38 +++++++------ .../GenerateAutocompleteCommand.swift | 0 Sources/ConsoleKitCommands/ConsoleError.swift | 14 ----- Sources/ConsoleKitCommands/Docs.docc/index.md | 8 +-- .../{ => Signatures}/Argument.swift | 0 .../{ => Signatures}/CommandSignature.swift | 7 +-- .../{ => Signatures}/Flag.swift | 0 .../{ => Signatures}/Option.swift | 0 .../String+LevenshteinDistance.swift | 0 .../{ => Utilities}/Utilities.swift | 6 +-- Sources/ConsoleKitTerminal/Docs.docc/index.md | 10 ++-- 24 files changed, 70 insertions(+), 102 deletions(-) rename Sources/ConsoleKitCommands/{ => Base}/AnyCommand.swift (98%) rename Sources/ConsoleKitCommands/{ => Base}/Command.swift (94%) rename Sources/ConsoleKitCommands/{ => Base}/CommandContext.swift (100%) rename Sources/ConsoleKitCommands/{ => Base}/CommandError.swift (62%) rename Sources/ConsoleKitCommands/{ => Base}/CommandGroup.swift (99%) rename Sources/ConsoleKitCommands/{ => Base}/CommandInput.swift (100%) rename Sources/ConsoleKitCommands/{ => Base}/Commands.swift (100%) rename Sources/ConsoleKitCommands/{ => Base}/Console+Run.swift (100%) create mode 100644 Sources/ConsoleKitCommands/Base/ConsoleError.swift rename Sources/ConsoleKitCommands/{ => Completion}/Completion.swift (95%) rename Sources/ConsoleKitCommands/{ => Completion}/GenerateAutocompleteCommand.swift (100%) delete mode 100644 Sources/ConsoleKitCommands/ConsoleError.swift rename Sources/ConsoleKitCommands/{ => Signatures}/Argument.swift (100%) rename Sources/ConsoleKitCommands/{ => Signatures}/CommandSignature.swift (91%) rename Sources/ConsoleKitCommands/{ => Signatures}/Flag.swift (100%) rename Sources/ConsoleKitCommands/{ => Signatures}/Option.swift (100%) rename Sources/ConsoleKitCommands/{ => Utilities}/String+LevenshteinDistance.swift (100%) rename Sources/ConsoleKitCommands/{ => Utilities}/Utilities.swift (85%) 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/ConsoleKitCommands/Async/AnyAsyncCommand.swift b/Sources/ConsoleKitCommands/Async/AnyAsyncCommand.swift index 5df3f6c0..884fddcc 100644 --- a/Sources/ConsoleKitCommands/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/ConsoleKitCommands/Async/AsyncCommand.swift b/Sources/ConsoleKitCommands/Async/AsyncCommand.swift index 9fdeb846..eabce96c 100644 --- a/Sources/ConsoleKitCommands/Async/AsyncCommand.swift +++ b/Sources/ConsoleKitCommands/Async/AsyncCommand.swift @@ -89,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/ConsoleKitCommands/Async/AsyncCommandGroup.swift b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift index 5bdcd382..e43254db 100644 --- a/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift +++ b/Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift @@ -22,7 +22,7 @@ public protocol AsyncCommandGroup: AnyAsyncCommand { extension AsyncCommandGroup { public var defaultCommand: (any AnyAsyncCommand)? { - return nil + nil } } diff --git a/Sources/ConsoleKitCommands/AnyCommand.swift b/Sources/ConsoleKitCommands/Base/AnyCommand.swift similarity index 98% rename from Sources/ConsoleKitCommands/AnyCommand.swift rename to Sources/ConsoleKitCommands/Base/AnyCommand.swift index 57f64eb6..28fbe8f1 100644 --- a/Sources/ConsoleKitCommands/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/ConsoleKitCommands/Command.swift b/Sources/ConsoleKitCommands/Base/Command.swift similarity index 94% rename from Sources/ConsoleKitCommands/Command.swift rename to Sources/ConsoleKitCommands/Base/Command.swift index 3ceb5c70..f293331b 100644 --- a/Sources/ConsoleKitCommands/Command.swift +++ b/Sources/ConsoleKitCommands/Base/Command.swift @@ -89,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) } } diff --git a/Sources/ConsoleKitCommands/CommandContext.swift b/Sources/ConsoleKitCommands/Base/CommandContext.swift similarity index 100% rename from Sources/ConsoleKitCommands/CommandContext.swift rename to Sources/ConsoleKitCommands/Base/CommandContext.swift diff --git a/Sources/ConsoleKitCommands/CommandError.swift b/Sources/ConsoleKitCommands/Base/CommandError.swift similarity index 62% rename from Sources/ConsoleKitCommands/CommandError.swift rename to Sources/ConsoleKitCommands/Base/CommandError.swift index 3d7bf25e..0bffddef 100644 --- a/Sources/ConsoleKitCommands/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/ConsoleKitCommands/CommandGroup.swift b/Sources/ConsoleKitCommands/Base/CommandGroup.swift similarity index 99% rename from Sources/ConsoleKitCommands/CommandGroup.swift rename to Sources/ConsoleKitCommands/Base/CommandGroup.swift index fd1f317c..3be82c7d 100644 --- a/Sources/ConsoleKitCommands/CommandGroup.swift +++ b/Sources/ConsoleKitCommands/Base/CommandGroup.swift @@ -22,7 +22,7 @@ public protocol CommandGroup: AnyCommand { extension CommandGroup { public var defaultCommand: (any AnyCommand)? { - return nil + nil } } diff --git a/Sources/ConsoleKitCommands/CommandInput.swift b/Sources/ConsoleKitCommands/Base/CommandInput.swift similarity index 100% rename from Sources/ConsoleKitCommands/CommandInput.swift rename to Sources/ConsoleKitCommands/Base/CommandInput.swift diff --git a/Sources/ConsoleKitCommands/Commands.swift b/Sources/ConsoleKitCommands/Base/Commands.swift similarity index 100% rename from Sources/ConsoleKitCommands/Commands.swift rename to Sources/ConsoleKitCommands/Base/Commands.swift diff --git a/Sources/ConsoleKitCommands/Console+Run.swift b/Sources/ConsoleKitCommands/Base/Console+Run.swift similarity index 100% rename from Sources/ConsoleKitCommands/Console+Run.swift rename to Sources/ConsoleKitCommands/Base/Console+Run.swift 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/ConsoleKitCommands/Completion.swift b/Sources/ConsoleKitCommands/Completion/Completion.swift similarity index 95% rename from Sources/ConsoleKitCommands/Completion.swift rename to Sources/ConsoleKitCommands/Completion/Completion.swift index a4a270e1..e03b1d1c 100644 --- a/Sources/ConsoleKitCommands/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/ConsoleKitCommands/GenerateAutocompleteCommand.swift b/Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift similarity index 100% rename from Sources/ConsoleKitCommands/GenerateAutocompleteCommand.swift rename to Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift diff --git a/Sources/ConsoleKitCommands/ConsoleError.swift b/Sources/ConsoleKitCommands/ConsoleError.swift deleted file mode 100644 index 5586d9fc..00000000 --- a/Sources/ConsoleKitCommands/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/ConsoleKitCommands/Docs.docc/index.md b/Sources/ConsoleKitCommands/Docs.docc/index.md index 06fd7190..fed9d5df 100644 --- a/Sources/ConsoleKitCommands/Docs.docc/index.md +++ b/Sources/ConsoleKitCommands/Docs.docc/index.md @@ -4,10 +4,6 @@ @TitleHeading(Package) } -ConsoleKit provides utilities for interacting with a console via a Swift application. It provides: +`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. -* 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. +> 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/Argument.swift b/Sources/ConsoleKitCommands/Signatures/Argument.swift similarity index 100% rename from Sources/ConsoleKitCommands/Argument.swift rename to Sources/ConsoleKitCommands/Signatures/Argument.swift diff --git a/Sources/ConsoleKitCommands/CommandSignature.swift b/Sources/ConsoleKitCommands/Signatures/CommandSignature.swift similarity index 91% rename from Sources/ConsoleKitCommands/CommandSignature.swift rename to Sources/ConsoleKitCommands/Signatures/CommandSignature.swift index 853c5bb3..1854c51a 100644 --- a/Sources/ConsoleKitCommands/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/ConsoleKitCommands/Flag.swift b/Sources/ConsoleKitCommands/Signatures/Flag.swift similarity index 100% rename from Sources/ConsoleKitCommands/Flag.swift rename to Sources/ConsoleKitCommands/Signatures/Flag.swift diff --git a/Sources/ConsoleKitCommands/Option.swift b/Sources/ConsoleKitCommands/Signatures/Option.swift similarity index 100% rename from Sources/ConsoleKitCommands/Option.swift rename to Sources/ConsoleKitCommands/Signatures/Option.swift diff --git a/Sources/ConsoleKitCommands/String+LevenshteinDistance.swift b/Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift similarity index 100% rename from Sources/ConsoleKitCommands/String+LevenshteinDistance.swift rename to Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift diff --git a/Sources/ConsoleKitCommands/Utilities.swift b/Sources/ConsoleKitCommands/Utilities/Utilities.swift similarity index 85% rename from Sources/ConsoleKitCommands/Utilities.swift rename to Sources/ConsoleKitCommands/Utilities/Utilities.swift index 216810a6..fc29f9c0 100644 --- a/Sources/ConsoleKitCommands/Utilities.swift +++ b/Sources/ConsoleKitCommands/Utilities/Utilities.swift @@ -4,11 +4,7 @@ import struct ConsoleKitTerminal.ConsoleStyle extension Array { /// Pops the first element from the array. mutating func popFirst() -> Element? { - guard let pop = self.first else { - return nil - } - self = Array(self.dropFirst()) - return pop + self.isEmpty ? nil : self.removeFirst() } } diff --git a/Sources/ConsoleKitTerminal/Docs.docc/index.md b/Sources/ConsoleKitTerminal/Docs.docc/index.md index 77930fe8..b008b446 100644 --- a/Sources/ConsoleKitTerminal/Docs.docc/index.md +++ b/Sources/ConsoleKitTerminal/Docs.docc/index.md @@ -4,10 +4,8 @@ @TitleHeading(Package) } -ConsoleKit provides utilities for interacting with a console via a Swift application. It provides: +`ConsoleKitTerminal` provides utilities for interacting with a console in a Swift application. It provides: -* 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. +* 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. From 5d4b1b41f27fd64a24068b8183e6ec4250b38c55 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Fri, 1 Dec 2023 10:59:38 -0600 Subject: [PATCH 5/6] Readme cleanup --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d1cc93ac..c608c6e6 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@

-Documentation +Documentation Team Chat -MIT License +MIT License Continuous Integration - -Swift 5.7+ + +Swift 5.7+


From b1301dda60457fe703c7bf9cadb06f6868b04815 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Fri, 1 Dec 2023 11:00:01 -0600 Subject: [PATCH 6/6] Make the levenshteinDistance method noticeably more efficient. --- .../Utilities/String+LevenshteinDistance.swift | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift b/Sources/ConsoleKitCommands/Utilities/String+LevenshteinDistance.swift index cc9e5d06..57e720ec 100644 --- a/Sources/ConsoleKitCommands/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..