diff options
| author | Igor Soarez <igor@soarez.org> | 2026-10-27 15:27:14 +0200 |
|---|---|---|
| committer | Igor Soarez <igor@soarez.org> | 2026-10-27 15:27:14 +0200 |
| commit | 9eddef09c769b315f4eabef6eaf4bb58e70d0966 (patch) | |
| tree | c550811ebde6c1b4e2ea7c561a587a15f570fa6a | |
| parent | a7e065cd4f39abda178af58127ead1ab502e0f3b (diff) | |
menu, panel, search: a peach ! in a column of its own; low dimmed more
the ! was the color of the name, read as part of it, and pushed high
names two characters out of line. it is now peach (herdr's palette, no
status uses it) in a fixed-width column every row has, so names line up.
a low agent's name is dimmed to 0.5 (0.7 was hard to see).
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | menubar/main.swift | 12 | ||||
| -rw-r--r-- | menubar/model.swift | 33 |
3 files changed, 37 insertions, 13 deletions
@@ -99,8 +99,9 @@ than a poll is still a completion. - **Importance**: mark an agent high, normal (the default), or low. Within a status, more important agents are listed first, so a jump goes to them first; status still comes first (a blocked low agent before a done high - one). A high agent shows a bold `!` before its name; a low agent's name is - lightly dimmed, its second line says "low", and it makes no sound (it + one). A high agent shows a peach `!` before its name (in a column of its + own, so names line up); a low agent's name is dimmed, its second line + says "low", and it makes no sound (it still notifies, and waits in line like any other). In pi, type `/importance high|normal|low` (no argument: the current level); pi saves it with the session, so it comes back after `/reload`, a restart, or a diff --git a/menubar/main.swift b/menubar/main.swift index 135c099..2230817 100644 --- a/menubar/main.swift +++ b/menubar/main.swift @@ -424,6 +424,18 @@ if arguments.contains("--selftest") { if rowTitle(high).string != "✓ ! Fix it" || rowTitlePrefix(high) != "✓ ! " { failures.append("title: a high agent is marked: \(rowTitle(high).string)") } + let markColor = rowTitle(high).attribute(.foregroundColor, at: rowTitlePrefix(high).utf16.count - 2, + effectiveRange: nil) as? NSColor + if markColor != herdrPeach { failures.append("title: the ! is peach") } + let normal = Row(paneId: "%2", agent: "pi", name: "Fix it", status: .done, session: "s", window: "w", since: 1) + if rowTitle(normal).string != "✓ Fix it" || rowTitlePrefix(normal).count != rowTitlePrefix(high).count { + failures.append("title: names line up with or without the mark: '\(rowTitle(normal).string)'") + } + let low = Row(paneId: "%3", agent: "pi", name: "Fix it", status: .done, session: "s", window: "w", since: 1, + importance: .low) + let lowColor = rowTitle(low).attribute(.foregroundColor, at: rowTitlePrefix(low).utf16.count, + effectiveRange: nil) as? NSColor + if lowColor?.alphaComponent != lowImportanceAlpha { failures.append("title: a low agent's name is dimmed") } failures.forEach { print("FAIL \($0)") } print(failures.isEmpty ? "selftest ok" : "selftest: \(failures.count) failed") exit(failures.isEmpty ? 0 : 1) diff --git a/menubar/model.swift b/menubar/model.swift index 513f9fb..f0f977e 100644 --- a/menubar/model.swift +++ b/menubar/model.swift @@ -18,6 +18,8 @@ let herdrTeal = herdrColor(dark: (148, 226, 213), light: (23, 146, 153)) let herdrYellow = herdrColor(dark: (249, 226, 175), light: (223, 142, 29)) let herdrGreen = herdrColor(dark: (166, 227, 161), light: (64, 160, 43)) let herdrGray = herdrColor(dark: (108, 112, 134), light: (156, 160, 176)) +/// Not a status color: marks a high-importance agent. +let herdrPeach = herdrColor(dark: (250, 179, 135), light: (254, 100, 11)) /// herdr's mocha text colors, fixed (not appearance-dependent) for the /// always-dark floating panel. @@ -324,15 +326,23 @@ func plainTitle(for rows: [Row]) -> String { title(for: rows).string } -/// The title's characters before the name: the status symbol, and `!` for a -/// high agent. +/// The title's characters before the name: the status symbol and the +/// importance column. func rowTitlePrefix(_ row: Row) -> String { - "\(row.status.symbol) " + (row.importance == .high ? "! " : "") + "\(row.status.symbol) " + importanceMark(row) + " " } -/// Row title: the colored status symbol, a bold `!` for a high agent, then -/// the agent's name. Unnamed agents show their harness, dimmed, so it never -/// competes with real names; a low agent's name is lightly dimmed. +/// The importance column: `!` for a high agent, a blank otherwise, so every +/// name starts in the same place. +private func importanceMark(_ row: Row) -> String { row.importance == .high ? "!" : " " } + +/// How much a low agent's name is dimmed: enough to recede, still legible. +let lowImportanceAlpha: CGFloat = 0.5 + +/// Row title: the colored status symbol, the importance column (a peach `!` +/// for a high agent), then the agent's name. Unnamed agents show their +/// harness, dimmed, so it never competes with real names; a low agent's name +/// is dimmed. func rowTitle(_ row: Row, primary: NSColor = .labelColor, secondary: NSColor = .secondaryLabelColor) -> NSAttributedString { let font = NSFont.menuFont(ofSize: 0) @@ -340,11 +350,12 @@ func rowTitle(_ row: Row, primary: NSColor = .labelColor, let text = NSMutableAttributedString() text.append(NSAttributedString( string: "\(row.status.symbol) ", attributes: [.font: mono, .foregroundColor: row.status.color])) - if row.importance == .high { - text.append(NSAttributedString( - string: "! ", attributes: [.font: NSFont.boldSystemFont(ofSize: font.pointSize), .foregroundColor: primary])) - } - let labelColor = row.name.isEmpty ? secondary : row.importance == .low ? primary.withAlphaComponent(0.7) : primary + text.append(NSAttributedString( + string: importanceMark(row) + " ", + attributes: [.font: NSFont.monospacedSystemFont(ofSize: font.pointSize, weight: .heavy), + .foregroundColor: herdrPeach])) + let labelColor = row.name.isEmpty ? secondary + : row.importance == .low ? primary.withAlphaComponent(lowImportanceAlpha) : primary text.append(NSAttributedString( string: row.label, attributes: [.font: font, .foregroundColor: labelColor])) return text |
