From f385c03435241165a52cc7c4574c6d61a11c8d0a Mon Sep 17 00:00:00 2001 From: Philip Niedertscheider Date: Thu, 1 Oct 2026 21:01:39 +0200 Subject: [PATCH] ref(cli): Extract terminal signal setup Move SIGPIPE configuration into a dedicated terminal setup service while preserving its ordering after telemetry startup. --- Sources/CLI/main/AppleDocs.swift | 20 ++++++-------------- Sources/CLI/main/Dependencies.swift | 1 + Sources/CLI/main/TerminalSetup.swift | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 Sources/CLI/main/TerminalSetup.swift diff --git a/Sources/CLI/main/AppleDocs.swift b/Sources/CLI/main/AppleDocs.swift index bde1d3b..103c342 100644 --- a/Sources/CLI/main/AppleDocs.swift +++ b/Sources/CLI/main/AppleDocs.swift @@ -1,14 +1,6 @@ import ArgumentParser import Logging -#if canImport(Darwin) - import Darwin -#elseif canImport(Glibc) - import Glibc -#elseif canImport(Musl) - import Musl -#endif - @main enum AppleDocs { private static let logger = Logger(label: "com.techprimate.apple-docs") @@ -17,11 +9,8 @@ enum AppleDocs { static func main() async { let telemetry = Dependencies.shared.telemetry telemetry.start() - // Ignore SIGPIPE so writing to a closed pipe (e.g. `apple-docs ... | head`) - // fails with EPIPE instead of terminating the process. - // Must stay after `telemetry.start()`: the crash handler installs its own - // SIGPIPE handler during start, which would otherwise replace SIG_IGN. - signal(SIGPIPE, SIG_IGN) + // Telemetry installs a SIGPIPE handler during start, so configure the terminal afterward. + Dependencies.shared.terminalSetup.configure() var loggingConfigured = false do { @@ -49,6 +38,9 @@ enum AppleDocs { } private static func verboseLoggingEnabled(for command: any ParsableCommand) -> Bool { - (command as? any GlobalOptionsProviding)?.global.verbose ?? false + guard let optionsProvider = command as? any GlobalOptionsProviding else { + return false + } + return optionsProvider.global.verbose } } diff --git a/Sources/CLI/main/Dependencies.swift b/Sources/CLI/main/Dependencies.swift index 9f4f1b3..9f95c59 100644 --- a/Sources/CLI/main/Dependencies.swift +++ b/Sources/CLI/main/Dependencies.swift @@ -9,6 +9,7 @@ struct Dependencies: Sendable { static let shared = Dependencies() let terminalCapabilities = DefaultTerminalCapabilities() + let terminalSetup = TerminalSetup() let telemetry = DefaultTelemetry( // Telemetry starts before SwiftLog is bootstrapped. Resolve its logger only when logging an event. logger: { Logger(label: "com.techprimate.apple-docs.telemetry") }, diff --git a/Sources/CLI/main/TerminalSetup.swift b/Sources/CLI/main/TerminalSetup.swift new file mode 100644 index 0000000..98dd81b --- /dev/null +++ b/Sources/CLI/main/TerminalSetup.swift @@ -0,0 +1,14 @@ +#if canImport(Darwin) + import Darwin +#elseif canImport(Glibc) + import Glibc +#elseif canImport(Musl) + import Musl +#endif + +struct TerminalSetup { + func configure() { + // Ignore SIGPIPE so writing to a closed pipe fails with EPIPE instead of terminating. + signal(SIGPIPE, SIG_IGN) + } +}