aboutsummaryrefslogtreecommitdiff
path: root/Sources
diff options
context:
space:
mode:
authorTommaso Negri <me@tommasongr.com>2026-10-14 22:30:19 +0200
committerTommaso Negri <me@tommasongr.com>2026-10-14 22:30:19 +0200
commit498ac51307412adc29d6d4a6240ae7b98d55621e (patch)
tree084d983c850673b60b0bfae48d0a4852737f06af /Sources
parent4942df3a59c0dd7c95b82727f8b03ddf80657973 (diff)
downloadbar-498ac51307412adc29d6d4a6240ae7b98d55621e.tar.gz
bar-498ac51307412adc29d6d4a6240ae7b98d55621e.zip
improve performances
Diffstat (limited to 'Sources')
-rw-r--r--Sources/bar/Models/Block.swift7
-rw-r--r--Sources/bar/Models/Cell.swift20
-rw-r--r--Sources/bar/Models/Runner.swift6
3 files changed, 23 insertions, 10 deletions
diff --git a/Sources/bar/Models/Block.swift b/Sources/bar/Models/Block.swift
index a9881f7..6f2b30d 100644
--- a/Sources/bar/Models/Block.swift
+++ b/Sources/bar/Models/Block.swift
@@ -44,6 +44,7 @@ final class Block: ObservableObject, Identifiable {
@Published var cells: [Cell] = []
private var tick: Task<Void, Never>?
+ private var lastLines: [String]?
init(name: String, placement: Config.Block.Placement, command: String, interval: Double? = nil) {
self.name = name
@@ -81,7 +82,11 @@ final class Block: ObservableObject, Identifiable {
/// Each line becomes a ``Cell``. This is always called
/// on the main actor so SwiftUI sees the update immediately.
@MainActor
- private func apply(_ lines: [String]) {
+ func apply(_ lines: [String]) {
+ // A refresh often returns the same text. Avoid parsing and invalidating
+ // every hosting view when nothing changed (including highlight prefixes).
+ guard lines != lastLines else { return }
+ lastLines = lines
self.cells = lines.map { Cell(rawValue: $0) }
}
diff --git a/Sources/bar/Models/Cell.swift b/Sources/bar/Models/Cell.swift
index d715fc2..b7911b5 100644
--- a/Sources/bar/Models/Cell.swift
+++ b/Sources/bar/Models/Cell.swift
@@ -1,5 +1,6 @@
import RegexBuilder
import SwiftUI
+import Synchronization
/// A thin wrapper around a single text line captured
/// by a block.
@@ -27,6 +28,15 @@ import SwiftUI
/// within a group. For example when you want to show
/// window manager workspaces and which one is active.
struct Cell: RawRepresentable, Identifiable {
+ /// Build the parser once rather than on every refresh of every cell.
+ private static let pattern = Mutex(Regex {
+ Optionally {
+ "&!"
+ Capture { OneOrMore(.digit) }
+ }
+ Capture { OneOrMore(.any) }
+ })
+
/// A content-derived identifier combining text and highlight.
///
/// Identical cells share this value and content changes change it.
@@ -41,15 +51,7 @@ struct Cell: RawRepresentable, Identifiable {
var background: Color
init(rawValue: String) {
- let pattern = Regex {
- Optionally {
- "&!"
- Capture { OneOrMore(.digit) }
- }
- Capture { OneOrMore(.any) }
- }
-
- guard let match = rawValue.firstMatch(of: pattern) else {
+ guard let match = Self.pattern.withLock({ rawValue.firstMatch(of: $0) }) else {
self.rawValue = rawValue
self.background = .clear
self.id = "\(rawValue):0"
diff --git a/Sources/bar/Models/Runner.swift b/Sources/bar/Models/Runner.swift
index 1fb88ad..6c90d54 100644
--- a/Sources/bar/Models/Runner.swift
+++ b/Sources/bar/Models/Runner.swift
@@ -21,6 +21,12 @@ enum Runner {
/// 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] {
+ // Detached tasks do not run inside AppKit's main event-loop pool.
+ // Drain temporary Foundation objects at the end of each command.
+ autoreleasepool { execute(command, env: env) }
+ }
+
+ private static func execute(_ command: String, env: [String: String]) -> [String] {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/sh")
process.arguments = ["-c", command]