From ec076ee6e315e6059545d0364a329cdb4b80b306 Mon Sep 17 00:00:00 2001 From: Tommaso Negri Date: Wed, 14 Oct 2026 22:18:15 +0200 Subject: remove leftover code in HEX --- Sources/bar/Config.swift | 2 +- Sources/bar/Models/Color+Hex.swift | 60 +++++++++++++++++ Sources/bar/Models/HEX.swift | 119 ---------------------------------- Sources/bar/bar.docc/bar.md | 1 - Sources/bar/bar.docc/customisation.md | 4 +- tasks/20261014-192305/TASK.md | 22 ++++++- 6 files changed, 84 insertions(+), 124 deletions(-) create mode 100644 Sources/bar/Models/Color+Hex.swift delete mode 100644 Sources/bar/Models/HEX.swift diff --git a/Sources/bar/Config.swift b/Sources/bar/Config.swift index 565459b..d8c1350 100644 --- a/Sources/bar/Config.swift +++ b/Sources/bar/Config.swift @@ -30,7 +30,7 @@ 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``). These strings are parsed + // support for hex colors too with `Color.hex(_:)`. These strings are parsed // at runtime, so the compiler does not check their format. // // E.g: `.hex("#000000")` diff --git a/Sources/bar/Models/Color+Hex.swift b/Sources/bar/Models/Color+Hex.swift new file mode 100644 index 0000000..4f82e78 --- /dev/null +++ b/Sources/bar/Models/Color+Hex.swift @@ -0,0 +1,60 @@ +import SwiftUI + +extension SwiftUI.Color { + /// Creates a color from a hex code, resolving it in the sRGB color space. + /// + /// 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`. 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 { + var sanitized = code.trimmingCharacters(in: .whitespacesAndNewlines) + if sanitized.hasPrefix("#") { + sanitized.removeFirst() + } + + var rgba: UInt64 = 0 + Scanner(string: sanitized).scanHexInt64(&rgba) + + let red: Double + let green: Double + let blue: Double + let opacity: Double + + switch sanitized.count { + case 8: // RRGGBBAA + red = Double((rgba >> 24) & 0xFF) / 255.0 + green = Double((rgba >> 16) & 0xFF) / 255.0 + blue = Double((rgba >> 8) & 0xFF) / 255.0 + opacity = Double(rgba & 0xFF) / 255.0 + case 6: // RRGGBB + red = Double((rgba >> 16) & 0xFF) / 255.0 + green = Double((rgba >> 8) & 0xFF) / 255.0 + blue = Double(rgba & 0xFF) / 255.0 + opacity = 1.0 + case 4: // RGBA + red = Double(((rgba >> 12) & 0xF) * 0x11) / 255.0 + green = Double(((rgba >> 8) & 0xF) * 0x11) / 255.0 + blue = Double(((rgba >> 4) & 0xF) * 0x11) / 255.0 + opacity = Double((rgba & 0xF) * 0x11) / 255.0 + case 3: // RGB + red = Double(((rgba >> 8) & 0xF) * 0x11) / 255.0 + green = Double(((rgba >> 4) & 0xF) * 0x11) / 255.0 + blue = Double((rgba & 0xF) * 0x11) / 255.0 + opacity = 1.0 + default: + red = 0.0 + green = 0.0 + blue = 0.0 + opacity = 1.0 + } + + return Color(.sRGB, red: red, green: green, blue: blue, opacity: opacity) + } +} diff --git a/Sources/bar/Models/HEX.swift b/Sources/bar/Models/HEX.swift deleted file mode 100644 index 5ceb393..0000000 --- a/Sources/bar/Models/HEX.swift +++ /dev/null @@ -1,119 +0,0 @@ -import SwiftUI - -/// A color described by a hexadecimal color code. -/// -/// `HEX` is a lightweight, string-backed representation: the code is stored -/// verbatim and parsed only when converted to a SwiftUI color via `Color(hex:)` -/// or `Color.hex(_:)`, which resolve it in the sRGB color space. -/// -/// Supported formats (the leading `#` is optional): -/// - `#RGB` -/// - `#RGBA` -/// - `#RRGGBB` -/// - `#RRGGBBAA` -/// -/// 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`. 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(_:)`. - var code: String - - /// Creates a hex color from the given code. - /// - /// - Parameter code: A hex color code. Stored verbatim; see ``HEX`` for the - /// accepted formats. - init(code: String) { - self.code = code - } -} - -extension SwiftUI.Color { - /// Creates a color from a ``HEX`` value. - init(hex: HEX) { - self = .hex(hex.code) - } - - /// Creates a color from a hex code, resolving it in the sRGB color space. - /// - /// 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`. 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 { - var sanitized = code.trimmingCharacters(in: .whitespacesAndNewlines) - if sanitized.hasPrefix("#") { - sanitized.removeFirst() - } - - var rgba: UInt64 = 0 - Scanner(string: sanitized).scanHexInt64(&rgba) - - let red: Double - let green: Double - let blue: Double - let opacity: Double - - switch sanitized.count { - case 8: // RRGGBBAA - red = Double((rgba >> 24) & 0xFF) / 255.0 - green = Double((rgba >> 16) & 0xFF) / 255.0 - blue = Double((rgba >> 8) & 0xFF) / 255.0 - opacity = Double(rgba & 0xFF) / 255.0 - case 6: // RRGGBB - red = Double((rgba >> 16) & 0xFF) / 255.0 - green = Double((rgba >> 8) & 0xFF) / 255.0 - blue = Double(rgba & 0xFF) / 255.0 - opacity = 1.0 - case 4: // RGBA - red = Double(((rgba >> 12) & 0xF) * 0x11) / 255.0 - green = Double(((rgba >> 8) & 0xF) * 0x11) / 255.0 - blue = Double(((rgba >> 4) & 0xF) * 0x11) / 255.0 - opacity = Double((rgba & 0xF) * 0x11) / 255.0 - case 3: // RGB - red = Double(((rgba >> 8) & 0xF) * 0x11) / 255.0 - green = Double(((rgba >> 4) & 0xF) * 0x11) / 255.0 - blue = Double((rgba & 0xF) * 0x11) / 255.0 - opacity = 1.0 - default: - red = 0.0 - green = 0.0 - blue = 0.0 - opacity = 1.0 - } - - return Color(.sRGB, red: red, green: green, blue: blue, opacity: opacity) - } -} - -extension SwiftUI.Color.Resolved { - /// The hex code for this resolved color. - /// - /// Components are clamped to `0...1` and quantized to 8 bits. - /// The result is a 6-digit `#RRGGBB` code, or an 8-digit `#RRGGBBAA` code - /// when the color is not fully opaque. - var hex: HEX { - let r = Int((min(max(Double(red), 0), 1) * 255).rounded()) - let g = Int((min(max(Double(green), 0), 1) * 255).rounded()) - let b = Int((min(max(Double(blue), 0), 1) * 255).rounded()) - - let code: String - if opacity < 1 { - let a = Int((min(max(Double(opacity), 0), 1) * 255).rounded()) - code = String(format: "#%02X%02X%02X%02X", r, g, b, a) - } else { - code = String(format: "#%02X%02X%02X", r, g, b) - } - - return HEX(code: code) - } -} diff --git a/Sources/bar/bar.docc/bar.md b/Sources/bar/bar.docc/bar.md index 61fee5b..bb17e56 100644 --- a/Sources/bar/bar.docc/bar.md +++ b/Sources/bar/bar.docc/bar.md @@ -31,7 +31,6 @@ If you specify the interval, the block will re-run the command with such frequen - - - ``Config`` -- ``HEX`` ### Bar diff --git a/Sources/bar/bar.docc/customisation.md b/Sources/bar/bar.docc/customisation.md index e006fa3..f5d5195 100644 --- a/Sources/bar/bar.docc/customisation.md +++ b/Sources/bar/bar.docc/customisation.md @@ -27,9 +27,9 @@ enum Config { > Tip: While testing the configuration you might want to use the `make run` target. > It will build and execute the program right away, without copying the binaries. -## HEX Colors +## Hex colors -You can use any standard SwiftUI color. For convenience, `Color.hex(_:)` parses hex strings directly in source, and ``HEX`` wraps a stored hex code: +You can use any standard SwiftUI color. For convenience, `Color.hex(_:)` parses hex strings directly in source: ```swift static let foreground: Color = .hex("#CDD6F4") diff --git a/tasks/20261014-192305/TASK.md b/tasks/20261014-192305/TASK.md index 6442a5a..828e130 100644 --- a/tasks/20261014-192305/TASK.md +++ b/tasks/20261014-192305/TASK.md @@ -1,6 +1,6 @@ # Review and remove unused HEX conversion surface -- STATUS: OPEN +- STATUS: CLOSED - PRIORITY: 170 - TAGS: review,cleanup,core @@ -13,3 +13,23 @@ Approach: Search all references first, including documentation and published pat Completion checks: swift build and swift test pass; no dangling HEX symbol links or references remain. Supported hex syntax and Config appearance are unchanged. Explain the kept/removed API choice in the change description so it can be reviewed separately from strict input validation. 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 + +Reference review found no callers of the HEX wrapper, Color.init(hex:), or +Color.Resolved.hex in Sources, Tests, examples, or published patches. Removed +these unused conversions to keep source customization focused on the existing +Color.hex(String) helper. Moved that helper to Models/Color+Hex.swift and updated +Config and DocC references. The published background-blur patch uses only the +retained .hex(String) helper and needs no change. + +This is API simplification, separate from strict input validation: the parser +body is byte-for-byte unchanged, as are configured foreground, background, and +highlight values. Supported syntax and existing malformed-input behavior remain +unchanged. Users with private customizations that call the removed helpers can +use Color.hex(code) for forward conversion or keep their own conversion helpers. + +Validation: swift build succeeded; swift test passed all four existing tests; +make -C Sources/bar/bar.docc build completed without warnings or unresolved +links; reference search found no remaining removed-API references in Sources, +Tests, patches, or README; git diff --check passed. -- cgit v1.2.3