Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a7dd700

Browse files
authoredDec 6, 2023
Revise async commands support (#196)
* Bump NIO version requirement * Deprecate unneeded and functionally incorrect APIs * Simplify and correct sync command adapters. * Remove excess imports, avoid concurrency warnings about fflush(), and a bit of code style
1 parent 18262d2 commit a7dd700

File tree

10 files changed

+38
-85
lines changed

10 files changed

+38
-85
lines changed
 

‎Package@swift-5.9.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ let package = Package(
2424
],
2525
dependencies: [
2626
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.3"),
27-
.package(url: "https://github.com/apple/swift-nio.git", from: "2.56.0"),
27+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.62.0"),
2828
],
2929
targets: [
3030
.target(

‎Sources/ConsoleKitCommands/Async/AsyncCommandGroup.swift

-32
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,10 @@ import ConsoleKitTerminal
1818
public protocol AsyncCommandGroup: AnyAsyncCommand {
1919
var commands: [String: any AnyAsyncCommand] { get }
2020
var defaultCommand: (any AnyAsyncCommand)? { get }
21-
22-
/// Merges this group with another group.
23-
/// - Parameters:
24-
/// - group: The group to merge with.
25-
/// - defaultCommand: The new default command to use.
26-
/// - help: The help message to use for the merged group.
27-
/// - Returns: A new `AsyncCommandGroup` with the merged commands.
28-
func merge(
29-
with group: any AsyncCommandGroup,
30-
defaultCommand: (any AnyAsyncCommand)?,
31-
help: String
32-
) -> any AsyncCommandGroup
33-
}
34-
35-
public struct MergedAsyncCommandGroup: AsyncCommandGroup {
36-
public let commands: [String: any AnyAsyncCommand]
37-
public let defaultCommand: (any AnyAsyncCommand)?
38-
public var help: String
3921
}
4022

4123
extension AsyncCommandGroup {
4224
public var defaultCommand: (any AnyAsyncCommand)? { nil }
43-
44-
public func merge(
45-
with group: any AsyncCommandGroup,
46-
defaultCommand: (any AnyAsyncCommand)?,
47-
help: String
48-
) -> any AsyncCommandGroup {
49-
var mergedCommands = self.commands
50-
mergedCommands.merge(group.commands, uniquingKeysWith: { (_, new) in new })
51-
return MergedAsyncCommandGroup(
52-
commands: mergedCommands,
53-
defaultCommand: defaultCommand,
54-
help: help
55-
)
56-
}
5725
}
5826

5927
extension AsyncCommandGroup {

‎Sources/ConsoleKitCommands/Base/AnyCommand.swift

+3-6
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,9 @@ extension AnyCommand {
2525
""
2626
}
2727

28-
// we need to have a sync environment so the compiler uses the sync run method over the async version
29-
private func syncRun(using context: inout CommandContext) throws {
30-
try self.run(using: &context)
31-
}
32-
3328
public func run(using context: inout CommandContext) async throws {
34-
try self.syncRun(using: &context)
29+
try await withCheckedThrowingContinuation { continuation in
30+
continuation.resume(with: .init { try self.run(using: &context) })
31+
}
3532
}
3633
}

‎Sources/ConsoleKitCommands/Base/CommandGroup.swift

+2-6
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,10 @@ public protocol CommandGroup: AnyCommand, AsyncCommandGroup {
2121
}
2222

2323
extension CommandGroup {
24-
public var defaultCommand: (any AnyCommand)? {
25-
nil
26-
}
24+
public var defaultCommand: (any AnyCommand)? { nil }
2725

2826
public var commands: [String: any AnyAsyncCommand] {
29-
// make the compiler happy
30-
let castedCommands: [String: any AnyCommand] = commands
31-
return castedCommands
27+
self.commands as [String: any AnyCommand]
3228
}
3329
}
3430

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@available(*, deprecated, message: "This API should not have been made public and is obsolete; do not use it.")
2+
public struct MergedAsyncCommandGroup: AsyncCommandGroup {
3+
public let commands: [String: any AnyAsyncCommand]
4+
public let defaultCommand: (any AnyAsyncCommand)?
5+
public var help: String
6+
}
7+
8+
extension AsyncCommandGroup {
9+
@available(*, deprecated, message: "This API should not have been made public and is obsolete; do not use it.")
10+
public func merge(
11+
with group: any AsyncCommandGroup,
12+
defaultCommand: (any AnyAsyncCommand)?,
13+
help: String
14+
) -> any AsyncCommandGroup {
15+
MergedAsyncCommandGroup(commands: self.commands.merging(group.commands, uniquingKeysWith: { $1 }), defaultCommand: defaultCommand, help: help)
16+
}
17+
}

‎Sources/ConsoleKitTerminal/Activity/ActivityIndicator.swift

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
#if os(Linux)
1+
#if !canImport(Darwin)
22
// Needed because DispatchQueue isn't Sendable on Linux
33
@preconcurrency import Foundation
44
#else
55
import Foundation
66
#endif
7-
#if canImport(Darwin)
8-
import Darwin
9-
#else
10-
import Glibc
11-
#endif
127
import NIOConcurrencyHelpers
138

149
extension ActivityIndicatorType {
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
#if canImport(Darwin)
2-
import Darwin
3-
#else
4-
import Glibc
5-
#endif
1+
import Foundation
62

73
extension Console {
84
/// Blocks the current thread for the specified number of seconds.
@@ -14,8 +10,6 @@ extension Console {
1410
/// - parameters:
1511
/// - seconds: The number of seconds to wait for.
1612
public func wait(seconds: Double) {
17-
let factor = 1000 * 1000
18-
let microseconds = seconds * Double(factor)
19-
usleep(useconds_t(microseconds))
13+
Thread.sleep(forTimeInterval: seconds)
2014
}
2115
}

‎Sources/ConsoleKitTerminal/Terminal/ANSI.swift

+11-7
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,21 @@ enum ANSISGRCommand {
4343
extension Terminal {
4444
/// Performs an `ANSICommand`.
4545
func command(_ command: ANSICommand) {
46-
guard enableCommands else { return }
46+
guard self.enableCommands else { return }
4747
Swift.print(command.ansi, terminator: "")
48-
fflush(stdout)
48+
49+
// fdopen() on stdout is fast; also the returned file MUST NOT be fclose()d
50+
// This avoids concurrency complaints due to accessing global `stdout`.
51+
fflush(fdopen(STDOUT_FILENO, "w+"))
52+
4953
}
5054
}
5155

5256
extension ConsoleText {
5357
/// Wraps a string in the ANSI codes indicated
5458
/// by the style specification
5559
func terminalStylize() -> String {
56-
return fragments
60+
self.fragments
5761
.map { $0.string.terminalStylize($0.style) }
5862
.joined()
5963
}
@@ -180,13 +184,13 @@ extension ConsoleStyle {
180184
var ansiCommand: ANSICommand {
181185
var commands: [ANSISGRCommand] = [.reset]
182186

183-
if isBold {
187+
if self.isBold {
184188
commands.append(.bold)
185189
}
186-
if let color = color {
190+
if let color = self.color {
187191
commands.append(color.ansiSpec.foregroundAnsiCommand)
188192
}
189-
if let background = background {
193+
if let background = self.background {
190194
commands.append(background.ansiSpec.backgroundAnsiCommand)
191195
}
192196
return .sgr(commands)
@@ -196,6 +200,6 @@ extension ConsoleStyle {
196200
extension String {
197201
/// Converts a String to a full ANSI command.
198202
fileprivate var ansi: String {
199-
return "\u{001B}[" + self
203+
"\u{001B}[\(self)"
200204
}
201205
}

‎Sources/ConsoleKitTerminal/Terminal/Terminal.swift

-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
#if canImport(Darwin)
2-
import Darwin
3-
#elseif canImport(Glibc)
4-
import Glibc
5-
#elseif os(Windows)
6-
import CRT
7-
#endif
81
import Foundation
92
import NIOConcurrencyHelpers
103

‎Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
import Logging
2-
3-
#if canImport(Darwin)
4-
import Darwin
5-
#elseif os(Windows)
6-
import CRT
7-
#elseif canImport(Glibc)
8-
import Glibc
9-
#elseif canImport(WASILibc)
10-
import WASILibc
11-
#else
12-
#error("Unsupported runtime")
13-
#endif
2+
import Foundation
143

154
/// Information about a specific log message, including information from the logger the message was logged to.
165
public struct LogRecord {

0 commit comments

Comments
 (0)
Please sign in to comment.