diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 998a0ebe..9f8d71ff 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,3 +8,11 @@ updates:
dependencies:
patterns:
- "*"
+ - package-ecosystem: "swift"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ groups:
+ dependencies:
+ patterns:
+ - "*"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index d7412c17..6e6a91c3 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -10,13 +10,24 @@ permissions:
jobs:
unit-tests:
- uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
- with:
- with_windows: true
- with_musl: true
- secrets: inherit
+ permissions:
+ contents: read
+ uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
+ with:
+ with_windows: true
+ with_musl: true
+ secrets: inherit
+
+ submit-dependencies:
+ permissions:
+ contents: write
+ if: ${{ github.event_name == 'push' }}
+ uses: vapor/ci/.github/workflows/submit-deps.yml@main
+ secrets: inherit
integration-check:
+ permissions:
+ contents: read
runs-on: ubuntu-latest
container: swift:noble
steps:
diff --git a/Package.swift b/Package.swift
index 1eceb51c..052f5a3f 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.8
+// swift-tools-version:6.1
import PackageDescription
let package = Package(
@@ -15,8 +15,8 @@ let package = Package(
.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.62.0"),
+ .package(url: "https://github.com/apple/swift-log.git", from: "1.11.0"),
+ .package(url: "https://github.com/apple/swift-nio.git", from: "2.97.0"),
],
targets: [
.target(
@@ -81,6 +81,10 @@ let package = Package(
)
var swiftSettings: [SwiftSetting] { [
- .enableUpcomingFeature("ForwardTrailingClosures"),
- .enableUpcomingFeature("ConciseMagicFile"),
+ .enableUpcomingFeature("ExistentialAny"),
+ //.enableUpcomingFeature("InternalImportsByDefault"),
+ .enableUpcomingFeature("MemberImportVisibility"),
+ .enableUpcomingFeature("InferIsolatedConformances"),
+ //.enableUpcomingFeature("NonisolatedNonsendingByDefault"),
+ .enableUpcomingFeature("ImmutableWeakCaptures"),
] }
diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift
deleted file mode 100644
index 752091e8..00000000
--- a/Package@swift-5.9.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-// swift-tools-version:5.9
-import PackageDescription
-
-let package = Package(
- name: "console-kit",
- platforms: [
- .macOS(.v10_15),
- .iOS(.v13),
- .watchOS(.v6),
- .tvOS(.v13),
- ],
- 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.62.0"),
- ],
- targets: [
- .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
- ),
- ]
-)
-
-var swiftSettings: [SwiftSetting] { [
- .enableUpcomingFeature("ExistentialAny"),
- .enableUpcomingFeature("ForwardTrailingClosures"),
- .enableUpcomingFeature("ConciseMagicFile"),
- .enableUpcomingFeature("DisableOutwardActorInference"),
- .enableExperimentalFeature("StrictConcurrency=complete"),
-] }
diff --git a/README.md b/README.md
index 8d05807f..d4e3c19f 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,13 @@
-
-
-
-
-
+
-
-
-
+
+
+
+Utilities for interacting with a terminal and the commandline in a Swift application.
diff --git a/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
index f3b1e796..0135210e 100644
--- a/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
+++ b/Sources/ConsoleKit/Docs.docc/images/vapor-consolekit-logo.svg
@@ -1,21 +1,25 @@
diff --git a/Sources/ConsoleKit/Docs.docc/theme-settings.json b/Sources/ConsoleKit/Docs.docc/theme-settings.json
index 9d414567..d7b909a4 100644
--- a/Sources/ConsoleKit/Docs.docc/theme-settings.json
+++ b/Sources/ConsoleKit/Docs.docc/theme-settings.json
@@ -1,18 +1,21 @@
{
"theme": {
- "aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
+ "aside": { "border-radius": "16px", "border-width": "3px", "border-style": "double" },
"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-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-consolekit)",
+ "hero-eyebrow": "white",
+ "documentation-intro-figure": "white",
+ "hero-title": "white",
"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" }
+ "icons": { "technology": "/consolekit/images/ConsoleKit/vapor-consolekit-logo.svg" }
},
"features": {
"quickNavigation": { "enable": true },
diff --git a/Sources/ConsoleKitCommands/Async/GenerateAsyncAutocompleteCommand.swift b/Sources/ConsoleKitCommands/Async/GenerateAsyncAutocompleteCommand.swift
index cd57e935..cfec9b37 100644
--- a/Sources/ConsoleKitCommands/Async/GenerateAsyncAutocompleteCommand.swift
+++ b/Sources/ConsoleKitCommands/Async/GenerateAsyncAutocompleteCommand.swift
@@ -1,3 +1,4 @@
+import ConsoleKitTerminal
import Foundation
struct GenerateAsyncAutocompleteCommand: AsyncCommand {
diff --git a/Sources/ConsoleKitCommands/Completion/Completion.swift b/Sources/ConsoleKitCommands/Completion/Completion.swift
index e03b1d1c..b2e30524 100644
--- a/Sources/ConsoleKitCommands/Completion/Completion.swift
+++ b/Sources/ConsoleKitCommands/Completion/Completion.swift
@@ -1,3 +1,5 @@
+import Foundation
+
/// Shell completion implementations.
public enum Shell: String, LosslessStringConvertible, CaseIterable, Sendable {
case bash
diff --git a/Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift b/Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift
index d837a807..f5ccbb2c 100644
--- a/Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift
+++ b/Sources/ConsoleKitCommands/Completion/GenerateAutocompleteCommand.swift
@@ -1,3 +1,4 @@
+import ConsoleKitTerminal
import Foundation
struct GenerateAutocompleteCommand: Command {
diff --git a/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg
index f3b1e796..0135210e 100644
--- a/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg
+++ b/Sources/ConsoleKitCommands/Docs.docc/images/vapor-consolekit-logo.svg
@@ -1,21 +1,25 @@
diff --git a/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json b/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json
index 9d414567..7e6dcffa 100644
--- a/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json
+++ b/Sources/ConsoleKitCommands/Docs.docc/theme-settings.json
@@ -1,18 +1,21 @@
{
"theme": {
- "aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
+ "aside": { "border-radius": "16px", "border-width": "3px", "border-style": "double" },
"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-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-consolekit)",
+ "hero-eyebrow": "white",
+ "documentation-intro-figure": "white",
+ "hero-title": "white",
"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" }
+ "icons": { "technology": "/consolekit/images/ConsoleKitCommands/vapor-consolekit-logo.svg" }
},
"features": {
"quickNavigation": { "enable": true },
diff --git a/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg b/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg
index f3b1e796..0135210e 100644
--- a/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg
+++ b/Sources/ConsoleKitTerminal/Docs.docc/images/vapor-consolekit-logo.svg
@@ -1,21 +1,25 @@
diff --git a/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json b/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json
index 9d414567..8e716bd3 100644
--- a/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json
+++ b/Sources/ConsoleKitTerminal/Docs.docc/theme-settings.json
@@ -1,18 +1,21 @@
{
"theme": {
- "aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
+ "aside": { "border-radius": "16px", "border-width": "3px", "border-style": "double" },
"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-fill": "radial-gradient(circle at top, var(--color-consolekit) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-consolekit)",
+ "hero-eyebrow": "white",
+ "documentation-intro-figure": "white",
+ "hero-title": "white",
"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" }
+ "icons": { "technology": "/consolekit/images/ConsoleKitTerminal/vapor-consolekit-logo.svg" }
},
"features": {
"quickNavigation": { "enable": true },
diff --git a/Sources/ConsoleKitTerminal/Terminal/ANSI.swift b/Sources/ConsoleKitTerminal/Terminal/ANSI.swift
index 532fe966..35b6ef77 100644
--- a/Sources/ConsoleKitTerminal/Terminal/ANSI.swift
+++ b/Sources/ConsoleKitTerminal/Terminal/ANSI.swift
@@ -1,6 +1,15 @@
-import Foundation
-#if canImport(Android)
-import Android
+#if canImport(Darwin)
+import Darwin.C
+#elseif canImport(Glibc)
+@preconcurrency import Glibc
+#elseif canImport(Musl)
+@preconcurrency import Musl
+#elseif canImport(Android)
+@preconcurrency import Android
+#elseif os(WASI)
+import WASILibc
+#elseif os(Windows)
+import CRT
#endif
/// Terminal ANSI commands
@@ -51,8 +60,12 @@ extension Terminal {
// fdopen() on stdout is fast; also the returned file MUST NOT be fclose()d
// This avoids concurrency complaints due to accessing global `stdout`.
+ #if os(Windows)
+ fflush(_fdopen(_fileno(stdout), "w+"))
+ #else
fflush(fdopen(STDOUT_FILENO, "w+"))
-
+ #endif
+
}
}
diff --git a/Sources/ConsoleKitTerminal/Terminal/Console.swift b/Sources/ConsoleKitTerminal/Terminal/Console.swift
index 89e5e182..f9612448 100644
--- a/Sources/ConsoleKitTerminal/Terminal/Console.swift
+++ b/Sources/ConsoleKitTerminal/Terminal/Console.swift
@@ -1,6 +1,15 @@
-import Foundation
-#if canImport(Android)
-import Android
+#if canImport(Darwin)
+import Darwin.C
+#elseif canImport(Glibc)
+@preconcurrency import Glibc
+#elseif canImport(Musl)
+@preconcurrency import Musl
+#elseif canImport(Android)
+@preconcurrency import Android
+#elseif os(WASI)
+import WASILibc
+#elseif os(Windows)
+import CRT
#endif
/// Protocol for powering styled Console I/O.
@@ -91,6 +100,8 @@ extension Console {
#if Xcode
// Xcode output does not support ANSI commands
return false
+ #elseif os(Windows)
+ return _isatty(_fileno(stdout)) > 0
#else
// If STDOUT is not an interactive terminal then omit ANSI commands
return isatty(STDOUT_FILENO) > 0
diff --git a/Sources/ConsoleKitTerminal/Terminal/Terminal.swift b/Sources/ConsoleKitTerminal/Terminal/Terminal.swift
index ba05514e..3ca15cb7 100644
--- a/Sources/ConsoleKitTerminal/Terminal/Terminal.swift
+++ b/Sources/ConsoleKitTerminal/Terminal/Terminal.swift
@@ -1,11 +1,18 @@
-import Foundation
-import NIOConcurrencyHelpers
-#if canImport(Android)
-import Android
-#endif
-#if os(Windows)
+#if canImport(Darwin)
+import Darwin.C
+#elseif canImport(Glibc)
+@preconcurrency import Glibc
+#elseif canImport(Musl)
+@preconcurrency import Musl
+#elseif canImport(Android)
+@preconcurrency import Android
+#elseif os(WASI)
+import WASILibc
+#elseif os(Windows)
+import CRT
import WinSDK
#endif
+import NIOConcurrencyHelpers
/// Generic console that uses a mixture of Swift standard
/// library and Foundation code to fulfill protocol requirements.
diff --git a/Sources/ConsoleKitTerminal/Utilities/ConsoleLogger.swift b/Sources/ConsoleKitTerminal/Utilities/ConsoleLogger.swift
index c2f6db19..e0e0a027 100644
--- a/Sources/ConsoleKitTerminal/Utilities/ConsoleLogger.swift
+++ b/Sources/ConsoleKitTerminal/Utilities/ConsoleLogger.swift
@@ -1,136 +1,78 @@
import Logging
-/// A `LoggerFragment` which implements the default logger message format.
-public func defaultLoggerFragment() -> some LoggerFragment {
+/// The complete explicit type of the ``defaultLoggerFragment()``. Unfortunately, we have to
+/// spell it out instead of just letting it be `some LoggerFragment` in order to define the
+/// ``ConsoleLogger`` alias properly.
+public typealias DefaultLoggerFragmentType = AndFragment, AndFragment, SeparatorFragment>>, SeparatorFragment>, IfMaxLevelFragment>>
+
+/// A ``LoggerFragment`` which implements the default logger message format.
+public func defaultLoggerFragment() -> DefaultLoggerFragmentType {
LabelFragment().maxLevel(.trace)
.and(LevelFragment().separated(" ").and(MessageFragment().separated(" ")))
.and(MetadataFragment().separated(" "))
.and(SourceLocationFragment().separated(" ").maxLevel(.debug))
}
-/// A `LoggerFragment` which implements the default logger message format with a timestamp at the front.
+/// A ``LoggerFragment`` which implements the default logger message format with a timestamp at the front.
public func timestampDefaultLoggerFragment(
timestampSource: some TimestampSource = SystemTimestampSource()
) -> some LoggerFragment {
TimestampFragment(timestampSource).and(defaultLoggerFragment().separated(" "))
}
-/// Outputs logs to a `Console` via a `LoggerFragment` pipeline.
+/// Outputs logs to a ``Console`` via a ``LoggerFragment`` pipeline.
public struct ConsoleFragmentLogger: LogHandler, Sendable {
+ /// The log handler's label.
public let label: String
-
- /// See `LogHandler.metadata`.
+
+ // See `LogHandler.metadata`.
public var metadata: Logger.Metadata
- /// See `LogHandler.metadataProvider`.
+ // See `LogHandler.metadataProvider`.
public var metadataProvider: Logger.MetadataProvider?
- /// See `LogHandler.logLevel`.
+ // See `LogHandler.logLevel`.
public var logLevel: Logger.Level
- /// The conosle that the messages will get logged to.
+ /// The console to which messages will be logged.
public let console: any Console
- /// The `LoggerFragment` this logger outputs through.
- public var fragment: T
-
- /// Creates a new `ConsoleLogger` instance.
+ private var _fragment: T
+
+ /// The ``LoggerFragment`` this logger outputs through.
+ public var fragment: T {
+ get { self._fragment }
+ @available(*, deprecated, message: "Setting ConsoleFragmentLogger's fragment after creation is deprecated.")
+ set { self._fragment = newValue }
+ }
+
+ /// Creates a new ``ConsoleFragmentLogger`` instance.
///
/// - Parameters:
- /// - fragment: The `LoggerFragment` this logger outputs through.
- /// - label: Unique identifier for this logger.
+ /// - fragment: The ``LoggerFragment`` this handler outputs through.
+ /// - label: Unique identifier for this handler.
/// - console: The console to log the messages to.
- /// - level: The minimum level of message that the logger will output. This defaults to `.debug`, the lowest level.
- /// - metadata: Extra metadata to log with the message. This defaults to an empty dictionary.
- public init(fragment: T, label: String, console: any Console, level: Logger.Level = .debug, metadata: Logger.Metadata = [:]) {
- self.fragment = fragment
+ /// - level: The minimum level of message that the handler will output. Defaults to `.debug`.
+ /// - metadata: Extra metadata to log with the message. Defaults to an empty dictionary.
+ public init(fragment: T = defaultLoggerFragment(), label: String, console: any Console, level: Logger.Level = .debug, metadata: Logger.Metadata = [:]) {
+ self._fragment = fragment
self.label = label
self.metadata = metadata
self.logLevel = level
self.console = console
}
- public init(fragment: T, label: String, console: any Console, level: Logger.Level = .debug, metadata: Logger.Metadata = [:], metadataProvider: Logger.MetadataProvider?) {
- self.fragment = fragment
- self.label = label
- self.metadata = metadata
- self.logLevel = level
- self.console = console
- self.metadataProvider = metadataProvider
- }
-
- /// See `LogHandler[metadataKey:]`.
- ///
- /// This just acts as a getter/setter for the `.metadata` property.
- public subscript(metadataKey key: String) -> Logger.Metadata.Value? {
- get { return self.metadata[key] }
- set { self.metadata[key] = newValue }
- }
-
- /// See `LogHandler.log(level:message:metadata:source:file:function:line:)`.
- public func log(
- level: Logger.Level,
- message: Logger.Message,
- metadata: Logger.Metadata?,
- source: String,
- file: String,
- function: String,
- line: UInt
- ) {
- var output = FragmentOutput()
- var record = LogRecord(
- level: level,
- message: message,
- metadata: metadata,
- source: source,
- file: file,
- function: function,
- line: line,
- label: self.label,
- loggerLevel: self.logLevel,
- loggerMetadata: self.metadata,
- metadataProvider: self.metadataProvider
- )
-
- self.fragment.write(&record, to: &output)
-
- self.console.output(output.text)
- }
-}
-
-/// Outputs logs to a `Console`.
-public struct ConsoleLogger: LogHandler, Sendable {
- public let label: String
-
- /// See `LogHandler.metadata`.
- public var metadata: Logger.Metadata
-
- /// See `LogHandler.metadataProvider`.
- public var metadataProvider: Logger.MetadataProvider?
-
- /// See `LogHandler.logLevel`.
- public var logLevel: Logger.Level
-
- /// The conosle that the messages will get logged to.
- public let console: any Console
-
- public var fragment: some LoggerFragment = defaultLoggerFragment()
-
- /// Creates a new `ConsoleLogger` instance.
+ /// Creates a new ``ConsoleFragmentLogger`` instance.
///
/// - Parameters:
- /// - label: Unique identifier for this logger.
+ /// - fragment: The ``LoggerFragment`` this handler outputs through.
+ /// - label: Unique identifier for this handler.
/// - console: The console to log the messages to.
- /// - level: The minimum level of message that the logger will output. This defaults to `.debug`, the lowest level.
- /// - metadata: Extra metadata to log with the message. This defaults to an empty dictionary.
- public init(label: String, console: any Console, level: Logger.Level = .debug, metadata: Logger.Metadata = [:]) {
- self.label = label
- self.metadata = metadata
- self.logLevel = level
- self.console = console
- }
-
- public init(label: String, console: any Console, level: Logger.Level = .debug, metadata: Logger.Metadata = [:], metadataProvider: Logger.MetadataProvider?) {
+ /// - level: The minimum level of message that the handler will output. Defaults to `.debug`.
+ /// - metadata: Extra metadata to log with the message. Defaults to an empty dictionary.
+ /// - metadataProvider: A metadata provider to associate with this handler.
+ public init(fragment: T = defaultLoggerFragment(), label: String, console: any Console, level: Logger.Level = .debug, metadata: Logger.Metadata = [:], metadataProvider: Logger.MetadataProvider?) {
+ self._fragment = fragment
self.label = label
self.metadata = metadata
self.logLevel = level
@@ -138,50 +80,43 @@ public struct ConsoleLogger: LogHandler, Sendable {
self.metadataProvider = metadataProvider
}
- /// See `LogHandler[metadataKey:]`.
- ///
- /// This just acts as a getter/setter for the `.metadata` property.
+ // See `LogHandler.subscript(metadataKey:)`.
public subscript(metadataKey key: String) -> Logger.Metadata.Value? {
get { return self.metadata[key] }
set { self.metadata[key] = newValue }
}
-
- /// See `LogHandler.log(level:message:metadata:source:file:function:line:)`.
- public func log(
- level: Logger.Level,
- message: Logger.Message,
- metadata: Logger.Metadata?,
- source: String,
- file: String,
- function: String,
- line: UInt
- ) {
+
+ // See `LogHandler.log(event:)`.
+ public func log(event: LogEvent) {
var output = FragmentOutput()
-
var record = LogRecord(
- level: level,
- message: message,
- metadata: metadata,
- source: source,
- file: file,
- function: function,
- line: line,
+ level: event.level,
+ message: event.message,
+ metadata: event.metadata,
+ source: event.source,
+ file: event.file,
+ function: event.function,
+ line: event.line,
label: self.label,
loggerLevel: self.logLevel,
loggerMetadata: self.metadata,
metadataProvider: self.metadataProvider
)
-
+
self.fragment.write(&record, to: &output)
-
self.console.output(output.text)
}
}
+/// Outputs logs to a ``Console`` using the ``defaultLoggerFragment()``.
+public typealias ConsoleLogger = ConsoleFragmentLogger
+
extension LoggingSystem {
- /// Bootstraps a `ConsoleLogger` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem` as the default log handler.
///
- /// LoggingSystem.boostrap(console: console)
+ /// ```swift
+ /// LoggingSystem.boostrap(console: console)
+ /// ```
///
/// - Parameters:
/// - console: The console the logger will log the messages to.
@@ -195,9 +130,11 @@ extension LoggingSystem {
self.bootstrap(console: console, level: level, metadata: metadata, metadataProvider: nil)
}
- /// Bootstraps a `ConsoleLogger` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleLogger`` to the `LoggingSystem` as the default log handler.
///
- /// LoggingSystem.boostrap(console: console)
+ /// ```swift
+ /// LoggingSystem.boostrap(console: console)
+ /// ```
///
/// - Parameters:
/// - console: The console the logger will log the messages to.
@@ -210,14 +147,16 @@ extension LoggingSystem {
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil
) {
- self.bootstrap({ (label, metadataProvider) in
+ self.bootstrap({ label, metadataProvider in
return ConsoleLogger(label: label, console: console, level: level, metadata: metadata, metadataProvider: metadataProvider)
}, metadataProvider: metadataProvider)
}
- /// Bootstraps a `ConsoleFragmentLogger` to the `LoggingSystem`, so that logger will be used in `Logger.init(label:)`.
+ /// Bootstraps a ``ConsoleFragmentLogger`` to the `LoggingSystem` as the default log handler.
///
- /// LoggingSystem.boostrap(console: console)
+ /// ```swift
+ /// LoggingSystem.boostrap(fragment: timestampDefaultLoggerFragment())
+ /// ```
///
/// - Parameters:
/// - fragment: The logger fragment which will be used to build the logged messages.
@@ -232,8 +171,8 @@ extension LoggingSystem {
metadata: Logger.Metadata = [:],
metadataProvider: Logger.MetadataProvider? = nil
) {
- self.bootstrap({ (label, metadataProvider) in
- return ConsoleFragmentLogger(fragment: fragment, label: label, console: console, level: level, metadata: metadata, metadataProvider: metadataProvider)
+ self.bootstrap({ label, metadataProvider in
+ ConsoleFragmentLogger(fragment: fragment, label: label, console: console, level: level, metadata: metadata, metadataProvider: metadataProvider)
}, metadataProvider: metadataProvider)
}
}
@@ -249,16 +188,9 @@ extension Logger.Level {
case .critical: return ConsoleStyle(color: .brightRed)
}
}
-
+
+ @available(*, deprecated, renamed: "rawValue", message: "Use `Logger.Level.rawValue` instead")
public var name: String {
- switch self {
- case .trace: return "TRACE"
- case .debug: return "DEBUG"
- case .info: return "INFO"
- case .notice: return "NOTICE"
- case .warning: return "WARNING"
- case .error: return "ERROR"
- case .critical: return "CRITICAL"
- }
+ self.rawValue.uppercased()
}
}
diff --git a/Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift b/Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift
index 4b6ce9ab..3daa729b 100644
--- a/Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift
+++ b/Sources/ConsoleKitTerminal/Utilities/LoggerFragment.swift
@@ -2,6 +2,8 @@ import Logging
import Foundation
/// Information about a specific log message, including information from the logger the message was logged to.
+///
+/// > Note: This type is obsoleted by the new `LogEvent` type in `swift-log`.
public struct LogRecord {
public init(level: Logger.Level, message: Logger.Message, metadata: Logger.Metadata? = nil, source: String, file: String, function: String, line: UInt, label: String, loggerLevel: Logger.Level, loggerMetadata: Logger.Metadata, metadataProvider: Logger.MetadataProvider? = nil) {
self.level = level
@@ -188,7 +190,7 @@ public struct LevelFragment: LoggerFragment {
public init() { }
public func write(_ record: inout LogRecord, to output: inout FragmentOutput) {
- output += "[ \(record.level.name) ]".consoleText(record.level.style)
+ output += "[ \(record.level.rawValue.uppercased()) ]".consoleText(record.level.style)
output.needsSeparator = true
}
}
diff --git a/Tests/AsyncConsoleKitTests/AsyncUtilities.swift b/Tests/AsyncConsoleKitTests/AsyncUtilities.swift
index 44d6eaa0..3770c57b 100644
--- a/Tests/AsyncConsoleKitTests/AsyncUtilities.swift
+++ b/Tests/AsyncConsoleKitTests/AsyncUtilities.swift
@@ -2,8 +2,6 @@ import ConsoleKit
import XCTest
import NIOConcurrencyHelpers
-extension String: Error {}
-
final class TestGroup: AsyncCommandGroup {
struct Signature: CommandSignature {
@Flag(name: "version", help: "Prints the version")
diff --git a/Tests/ConsoleKitTests/LoggingTests.swift b/Tests/ConsoleKitTests/LoggingTests.swift
index 420de1f4..c38e45f6 100644
--- a/Tests/ConsoleKitTests/LoggingTests.swift
+++ b/Tests/ConsoleKitTests/LoggingTests.swift
@@ -134,7 +134,7 @@ final class ConsoleLoggerTests: XCTestCase {
// Remove the timezone, since there doesn't appear to be a good way to mock it with strftime.
while logged.removeFirst() != " " { }
- XCTAssertEqual(logged, "[ \(Logger.Level.info.name) ] logged (ConsoleKitTests/LoggingTests.swift:1)\n")
+ XCTAssertEqual(logged, "[ \(Logger.Level.info.rawValue.uppercased()) ] logged (ConsoleKitTests/LoggingTests.swift:1)\n")
}
func testSourceFragment() {
@@ -150,12 +150,12 @@ final class ConsoleLoggerTests: XCTestCase {
logger.info("logged", line: 1)
- XCTAssertEqual(console.testOutputQueue.first, "ConsoleKitTests [ \(Logger.Level.info.name) ] logged (ConsoleKitTests/LoggingTests.swift:1)\n")
+ XCTAssertEqual(console.testOutputQueue.first, "ConsoleKitTests [ \(Logger.Level.info.rawValue.uppercased()) ] logged (ConsoleKitTests/LoggingTests.swift:1)\n")
}
}
private func XCTAssertLog(_ console: TestConsole, _ level: Logger.Level, _ message: String, file: StaticString = #filePath, line: UInt = #line) {
- XCTAssertEqual(console.testOutputQueue.first ?? "", "[ \(level.name) ] \(message)\n", file: file, line: line)
+ XCTAssertEqual(console.testOutputQueue.first ?? "", "[ \(level.rawValue.uppercased()) ] \(message)\n", file: file, line: line)
}
enum TraceNamespace {
diff --git a/Tests/ConsoleKitTests/Utilities.swift b/Tests/ConsoleKitTests/Utilities.swift
index df5b86ea..65aeb8ad 100644
--- a/Tests/ConsoleKitTests/Utilities.swift
+++ b/Tests/ConsoleKitTests/Utilities.swift
@@ -2,8 +2,6 @@ import ConsoleKit
import XCTest
import NIOConcurrencyHelpers
-extension String: Error {}
-
final class TestGroup: CommandGroup {
struct Signature: CommandSignature {
@Flag(name: "version", help: "Prints the version")