diff options
| author | Tommaso Negri <me@tommasongr.com> | 2026-10-14 22:13:55 +0200 |
|---|---|---|
| committer | Tommaso Negri <me@tommasongr.com> | 2026-10-14 22:13:55 +0200 |
| commit | ed506be5076c500f19e8a39e89867ee54007577e (patch) | |
| tree | 1e9f8471ef5186f57e1a41080a7d66dd47aec4be /Sources | |
| parent | 8aacd1f753c7ef21a7e1173cc08c5b0a85a94c6b (diff) | |
| download | bar-ed506be5076c500f19e8a39e89867ee54007577e.tar.gz bar-ed506be5076c500f19e8a39e89867ee54007577e.zip | |
improve and clarify documentation
Diffstat (limited to 'Sources')
| -rw-r--r-- | Sources/bar/Config.swift | 6 | ||||
| -rw-r--r-- | Sources/bar/Models/Block.swift | 5 | ||||
| -rw-r--r-- | Sources/bar/Models/Cell.swift | 13 | ||||
| -rw-r--r-- | Sources/bar/Models/HEX.swift | 11 | ||||
| -rw-r--r-- | Sources/bar/Models/Runner.swift | 18 | ||||
| -rw-r--r-- | Sources/bar/bar.docc/command.md | 11 | ||||
| -rw-r--r-- | Sources/bar/bar.docc/customisation.md | 2 | ||||
| -rw-r--r-- | Sources/bar/bar.docc/highlighting.md | 5 | ||||
| -rw-r--r-- | Sources/bar/bar.docc/how-it-works.md | 3 |
9 files changed, 47 insertions, 27 deletions
diff --git a/Sources/bar/Config.swift b/Sources/bar/Config.swift index f1edf01..565459b 100644 --- a/Sources/bar/Config.swift +++ b/Sources/bar/Config.swift @@ -30,7 +30,8 @@ enum Config { // // You can use system default colors and the standard SwiftUI // methods to define them. However, for convenience we added - // support for hex colors too (see ``HEX``). + // support for hex colors too (see ``HEX``). These strings are parsed + // at runtime, so the compiler does not check their format. // // E.g: `.hex("#000000")` @@ -110,7 +111,8 @@ extension Config { /// The interval, in seconds, at which the command is executed. /// /// If set to `nil`, the block will be evaluated just once - /// at launch. You can of course trigger a manual update via + /// at launch. Zero and negative intervals also disable repeating updates. + /// You can of course trigger a manual update via /// a notification later on. let interval: Double? diff --git a/Sources/bar/Models/Block.swift b/Sources/bar/Models/Block.swift index cb09a4b..a9881f7 100644 --- a/Sources/bar/Models/Block.swift +++ b/Sources/bar/Models/Block.swift @@ -9,7 +9,8 @@ import Foundation /// notifications (see ``Notifier``). @MainActor final class Block: ObservableObject, Identifiable { - /// Stable identity for SwiftUI diffing. + /// Distinguishes this block instance in SwiftUI, even when names match. + /// Content updates are published separately through ``cells``. let id = UUID() /// Identifier used for manual updates via Darwin @@ -70,7 +71,7 @@ final class Block: ObservableObject, Identifiable { } } - /// Stop the interval timer. + /// Cancel future interval refreshes. Already-running commands continue. func stop() { tick?.cancel() } diff --git a/Sources/bar/Models/Cell.swift b/Sources/bar/Models/Cell.swift index a09d1f9..d715fc2 100644 --- a/Sources/bar/Models/Cell.swift +++ b/Sources/bar/Models/Cell.swift @@ -9,9 +9,8 @@ import SwiftUI /// is then laid out horizontally respecting the order. /// /// ### Highlight -/// Besides the underlying text value, a cell holds an -/// highlight level (as Int) that, if true, applies the -/// special background color defined in ``Config``. +/// Besides the underlying text value, a cell holds a background +/// color selected by a highlight level from ``Config``. /// You can set the highlight at runtime by prefixing the /// text line with the special notation `&!<level>`, where /// `<level>` is a positive integer that can be used as an @@ -28,11 +27,11 @@ import SwiftUI /// within a group. For example when you want to show /// window manager workspaces and which one is active. struct Cell: RawRepresentable, Identifiable { - /// Stable identity for SwiftUI diffing. + /// A content-derived identifier combining text and highlight. /// - /// The id is constructed by the rawValue + highlight - /// so that SwiftUI redraws the cell only on content - /// change and not every time the cell is computed. + /// Identical cells share this value and content changes change it. + /// ``BlockView`` uses line positions to distinguish rendered cells; + /// view identity does not prevent updates to their displayed content. let id: String /// The represented text content. diff --git a/Sources/bar/Models/HEX.swift b/Sources/bar/Models/HEX.swift index a262630..5ceb393 100644 --- a/Sources/bar/Models/HEX.swift +++ b/Sources/bar/Models/HEX.swift @@ -14,7 +14,9 @@ import SwiftUI /// /// Single-digit components are expanded by repeating the digit; for example, /// `#3aF` is read as `#33AAFF`. When present, the trailing digits encode alpha -/// (opacity); otherwise opacity defaults to `1`. +/// (opacity); otherwise opacity defaults to `1`. Surrounding whitespace is +/// trimmed during conversion. Unsupported lengths resolve to opaque black; +/// characters are not fully validated, so use one of the formats above. struct HEX { /// The raw hex code, exactly as supplied. It is not validated or normalized; /// parsing is performed lazily by `Color.hex(_:)`. @@ -40,8 +42,11 @@ extension SwiftUI.Color { /// Supported formats (the leading `#` is optional): `#RGB`, `#RGBA`, /// `#RRGGBB`, and `#RRGGBBAA`. Single-digit components are expanded by /// repeating the digit. When present, the trailing digits encode alpha - /// (opacity); otherwise opacity defaults to `1`. Malformed input resolves - /// to opaque black. + /// (opacity); otherwise opacity defaults to `1`. Surrounding whitespace is + /// trimmed. Unsupported lengths resolve to opaque black. At supported + /// lengths, Scanner may parse only a leading hexadecimal portion; its + /// success result is not checked. Invalid characters therefore do not + /// reliably produce opaque black (alpha formats can be transparent). /// /// - Parameter code: A hex color code. static func hex(_ code: String) -> SwiftUI.Color { diff --git a/Sources/bar/Models/Runner.swift b/Sources/bar/Models/Runner.swift index dc88049..1fb88ad 100644 --- a/Sources/bar/Models/Runner.swift +++ b/Sources/bar/Models/Runner.swift @@ -3,12 +3,12 @@ import Foundation /// Runs a shell command and returns its stdout as separate lines. /// /// Blocking — always call from a background context (e.g. `Task.detached`). -/// A 30-second timeout prevents hanging processes from consuming -/// cooperative pool threads indefinitely. +/// After 30 seconds, requests termination of the shell process. This is +/// not a hard execution limit: the shell can ignore termination, and child +/// processes can keep output pipes open. Pipe reads and waiting can still block. enum Runner { - /// The maximum time (in seconds) a command is allowed to run before - /// being killed. This prevents a single hung process from consuming - /// a cooperative thread indefinitely. + /// Delay in seconds before requesting shell termination with SIGTERM. + /// Does not forcibly kill the shell or terminate its descendants. private static let timeout: Double = 30 /// Run a command and returns stdout as an array of separated lines. @@ -17,7 +17,9 @@ enum Runner { /// - env: An optional dictionary of strings to merge into /// the process environment. /// - /// - Returns: An array of the text lines printed to stdout. + /// - Returns: Parsed stdout on success; ["ERROR"] on launch failure or + /// nonzero exit, or [""] if successful output cannot be decoded as UTF-8. + /// Captured stderr is forwarded only after a nonzero exit. static func run(_ command: String, env: [String: String] = [:]) -> [String] { let process = Process() process.executableURL = URL(fileURLWithPath: "/bin/sh") @@ -36,8 +38,8 @@ enum Runner { return ["ERROR"] } - // Schedule a kill after the timeout expires. - // If the process finishes before that, the timer is cancelled. + // Request shell termination after the timeout expires. + // Cancel the timer after pipe reads and process waiting finish. let timer = DispatchSource.makeTimerSource() timer.schedule(deadline: .now() + timeout) timer.setEventHandler { [weak process] in diff --git a/Sources/bar/bar.docc/command.md b/Sources/bar/bar.docc/command.md index da1a71f..3196011 100644 --- a/Sources/bar/bar.docc/command.md +++ b/Sources/bar/bar.docc/command.md @@ -5,6 +5,9 @@ How the block's command is executed. Each block runs its ``Config-swift.enum/Block/command`` as a shell script via `/bin/sh -c`. The standard output is captured and **each line becomes one ``Cell``** in the bar. Cells are laid out horizontally in the order they appear. +One final newline is removed; other blank lines and spaces are preserved. +A successful command with empty stdout produces no cells, hiding the block. +Printing a newline produces a blank cell rather than hiding it. ```shell # A single-line command produces one cell @@ -26,7 +29,13 @@ On the contrary, if you run `bar` from a launch agent, you'll probably not have ## Error handling If the command exits with a non-zero status or cannot be launched, the block displays a single cell containing the text `ERROR`. -The command's stderr is forwarded to the `bar` process stderr, which you can inspect for the actual failure. +After a non-zero exit, captured stderr is forwarded to the `bar` process stderr. +Stderr from a successful command is discarded, and launch failures do not forward a diagnostic. +Successful stdout that cannot be decoded as UTF-8 produces a blank cell. + +After 30 seconds, *bar* requests termination of the shell with SIGTERM. +This is not a hard deadline: a shell can ignore the signal, and child processes can keep the output pipes open. +The current runner reads stdout and then stderr before waiting for exit, so commands with enough stderr output can also block while stdout is being read. ```shell # Example: simulate a command failure diff --git a/Sources/bar/bar.docc/customisation.md b/Sources/bar/bar.docc/customisation.md index 602f29a..e006fa3 100644 --- a/Sources/bar/bar.docc/customisation.md +++ b/Sources/bar/bar.docc/customisation.md @@ -29,7 +29,7 @@ enum Config { ## HEX Colors -You can use any standard SwiftUI color. For convenience, we also provide the ``HEX`` type for defining colors by hex code directly in source: +You can use any standard SwiftUI color. For convenience, `Color.hex(_:)` parses hex strings directly in source, and ``HEX`` wraps a stored hex code: ```swift static let foreground: Color = .hex("#CDD6F4") diff --git a/Sources/bar/bar.docc/highlighting.md b/Sources/bar/bar.docc/highlighting.md index aa2ad0d..8075031 100644 --- a/Sources/bar/bar.docc/highlighting.md +++ b/Sources/bar/bar.docc/highlighting.md @@ -34,8 +34,9 @@ echo "&!2 workspace 2" # highlighted with Config.highlights[1] echo "workspace 3" # no highlight ``` -> Important: The `&!<level>` notation is stripped before rendering, so only the text after it is displayed. +> Important: A parsed `&!<level>` prefix followed by text is stripped before rendering, so only the text after it is displayed. > For example, `&!1 workspace 1` renders as `workspace 1` on a highlighted background. > Important: The highlight level is a positive integer that indexes into ``Config-swift.enum/highlights`` (1-based). -> If the level exceeds the number of defined highlights, the cell is treated as unhighlighted. +> For a parsed prefix followed by text, zero, an out-of-range level, or a number too large to represent as an Int leaves the cell unhighlighted and removes the prefix. +> Use a level followed by text as shown above: malformed or textless prefixes are not guaranteed to be stripped by the current parser. diff --git a/Sources/bar/bar.docc/how-it-works.md b/Sources/bar/bar.docc/how-it-works.md index ab8216a..d9c4bd4 100644 --- a/Sources/bar/bar.docc/how-it-works.md +++ b/Sources/bar/bar.docc/how-it-works.md @@ -15,7 +15,8 @@ You're supposed to fully understand how it works, make it yours, and ultimately *bar* does not read a configuration file somewhere on your system. Instead, configuration happens directly in the source code by editing ``Config`` and rebuilding the software. -This approach allows us to keep the software extremely minimal and reliable, since all the possible errors are caught at build time. +This keeps configuration simple and lets the Swift compiler catch syntax and type errors when you build. +Shell commands and string values, such as hex color codes, are interpreted at runtime, so you still need to check their output and behavior. ## No pre-built binaries |
