summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--Sources/bar/Config.swift6
-rw-r--r--Sources/bar/Models/Block.swift5
-rw-r--r--Sources/bar/Models/Cell.swift13
-rw-r--r--Sources/bar/Models/HEX.swift11
-rw-r--r--Sources/bar/Models/Runner.swift18
-rw-r--r--Sources/bar/bar.docc/command.md11
-rw-r--r--Sources/bar/bar.docc/customisation.md2
-rw-r--r--Sources/bar/bar.docc/highlighting.md5
-rw-r--r--Sources/bar/bar.docc/how-it-works.md3
-rw-r--r--tasks/20261014-192338/TASK.md21
11 files changed, 68 insertions, 29 deletions
diff --git a/README.md b/README.md
index a06f361..3c8e99e 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ static let blocks: [Block] = [
### Intuitive shell scripting
-Populate the block by writing to `stdout`, hide it by exiting with `0`:
+Populate the block by writing to `stdout`. To hide it, exit with `0` without printing anything to `stdout`:
```shell
if [[ -n $session ]]; then
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
diff --git a/tasks/20261014-192338/TASK.md b/tasks/20261014-192338/TASK.md
index b649850..ac79e76 100644
--- a/tasks/20261014-192338/TASK.md
+++ b/tasks/20261014-192338/TASK.md
@@ -1,6 +1,6 @@
# Align comments and documentation with actual guarantees
-- STATUS: OPEN
+- STATUS: CLOSED
- PRIORITY: 180
- TAGS: review,docs
@@ -13,3 +13,22 @@ Approach: Explain concrete contracts simply: source configuration catches Swift
Completion checks: Cross-check each claim against code and tests, build DocC with the project's documented workflow, and correct stale symbol links. This task can be revisited after related fixes; do not pre-document functionality that has not landed.
Design constraint: Follow README.md: keep source-based configuration, no dependencies or plugin framework, and use the smallest readable change that makes the existing behavior reliable. This is a suggestion for individual review, not a deadline. Findings were recorded on 2026-10-14; re-check the current code before implementing.
+
+## Completion
+
+Updated README and DocC to distinguish compile-time Swift checks from runtime
+shell and color behavior, require successful empty stdout for hiding, describe
+line parsing and actual stderr/error handling, and explain the limits of the
+30-second termination request. Cell and Block comments distinguish identity from
+content updates; Cell documents its content-derived ID and BlockView's current
+positional rendering. Config and HEX comments describe runtime color parsing,
+unsupported-length fallback, partial scanning, and disabled repeating intervals.
+Highlighting documentation qualifies prefix stripping and invalid levels against
+the current parser. HEX remains implemented and its symbol links remain valid;
+Color.hex(_:) is formatted as code because DocC does not emit a linkable page for
+that extension member in this catalog.
+
+Validation: reviewed claims against the current implementations and existing
+hover/lifetime tests; `make -C Sources/bar/bar.docc build` completed without
+warnings or unresolved symbol links; `swift test` passed all four existing tests;
+`git diff --check` passed. Runtime behavior is unchanged.