From 627d4c16dc0684c302be8d8555013bff76fe4502 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 11:01:50 +0000 Subject: [PATCH 01/21] feat(cli): add TerminalUI target and framed windows for interactive screens --- cli/Package.swift | 12 +- cli/Sources/TerminalUI/Buffer.swift | 129 +++++ cli/Sources/TerminalUI/Gauge.swift | 15 + cli/Sources/TerminalUI/KeyHints.swift | 47 ++ cli/Sources/TerminalUI/Scrollbar.swift | 29 ++ cli/Sources/TerminalUI/Style.swift | 47 ++ .../{puremac/Core => TerminalUI}/Term.swift | 45 +- .../Core => TerminalUI}/TerminalSession.swift | 30 +- cli/Sources/TerminalUI/Window.swift | 75 +++ cli/Sources/puremac/Commands/Analyze.swift | 215 +++++--- cli/Sources/puremac/Commands/Clean.swift | 1 + cli/Sources/puremac/Commands/Config.swift | 1 + cli/Sources/puremac/Commands/Ignore.swift | 1 + cli/Sources/puremac/Commands/Optimize.swift | 1 + cli/Sources/puremac/Commands/Purge.swift | 1 + cli/Sources/puremac/Core/FocusPointer.swift | 7 + .../puremac/Core/InteractiveReview.swift | 217 ++++---- cli/Sources/puremac/Core/Render.swift | 4 +- cli/Sources/puremac/Core/TerminalMenu.swift | 98 ++-- cli/Sources/puremac/Core/TooSmallScreen.swift | 25 + cli/Sources/puremac/PureMac.swift | 1 + cli/Tests/TerminalUITests/BufferTests.swift | 165 +++++++ cli/Tests/TerminalUITests/GaugeTests.swift | 35 ++ cli/Tests/TerminalUITests/KeyHintsTests.swift | 74 +++ .../TerminalUITests/ScrollbarTests.swift | 47 ++ cli/Tests/TerminalUITests/StyleTests.swift | 28 ++ cli/Tests/TerminalUITests/TermTests.swift | 30 ++ .../TerminalSessionTests.swift | 13 + cli/Tests/TerminalUITests/WindowTests.swift | 131 +++++ cli/Tests/puremacTests/AnalyzeTests.swift | 283 +++++++++-- .../InteractiveScreensTests.swift | 463 ++++++++++++++++++ cli/Tests/puremacTests/TerminalUITests.swift | 201 -------- 32 files changed, 1990 insertions(+), 481 deletions(-) create mode 100644 cli/Sources/TerminalUI/Buffer.swift create mode 100644 cli/Sources/TerminalUI/Gauge.swift create mode 100644 cli/Sources/TerminalUI/KeyHints.swift create mode 100644 cli/Sources/TerminalUI/Scrollbar.swift create mode 100644 cli/Sources/TerminalUI/Style.swift rename cli/Sources/{puremac/Core => TerminalUI}/Term.swift (72%) rename cli/Sources/{puremac/Core => TerminalUI}/TerminalSession.swift (92%) create mode 100644 cli/Sources/TerminalUI/Window.swift create mode 100644 cli/Sources/puremac/Core/FocusPointer.swift create mode 100644 cli/Sources/puremac/Core/TooSmallScreen.swift create mode 100644 cli/Tests/TerminalUITests/BufferTests.swift create mode 100644 cli/Tests/TerminalUITests/GaugeTests.swift create mode 100644 cli/Tests/TerminalUITests/KeyHintsTests.swift create mode 100644 cli/Tests/TerminalUITests/ScrollbarTests.swift create mode 100644 cli/Tests/TerminalUITests/StyleTests.swift create mode 100644 cli/Tests/TerminalUITests/TermTests.swift create mode 100644 cli/Tests/TerminalUITests/TerminalSessionTests.swift create mode 100644 cli/Tests/TerminalUITests/WindowTests.swift create mode 100644 cli/Tests/puremacTests/InteractiveScreensTests.swift delete mode 100644 cli/Tests/puremacTests/TerminalUITests.swift diff --git a/cli/Package.swift b/cli/Package.swift index 3f1743c..e1dbe17 100644 --- a/cli/Package.swift +++ b/cli/Package.swift @@ -11,16 +11,26 @@ let package = Package( .package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0"), ], targets: [ + .target( + name: "TerminalUI", + path: "Sources/TerminalUI" + ), .executableTarget( name: "puremac", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), + "TerminalUI", ], path: "Sources/puremac" ), + .testTarget( + name: "TerminalUITests", + dependencies: ["TerminalUI"], + path: "Tests/TerminalUITests" + ), .testTarget( name: "puremacTests", - dependencies: ["puremac"], + dependencies: ["puremac", "TerminalUI"], path: "Tests/puremacTests" ), ] diff --git a/cli/Sources/TerminalUI/Buffer.swift b/cli/Sources/TerminalUI/Buffer.swift new file mode 100644 index 0000000..92cad97 --- /dev/null +++ b/cli/Sources/TerminalUI/Buffer.swift @@ -0,0 +1,129 @@ +public enum RowConstraint: Equatable { + case length(Int) + case fill +} + +public struct Rect: Equatable { + public var x, y, width, height: Int + + public init(x: Int, y: Int, width: Int, height: Int) { + self.x = x + self.y = y + self.width = width + self.height = height + } + + public func splitRows(_ constraints: [RowConstraint]) -> [Rect] { + var remaining = max(0, height) + let fixed: [Int?] = constraints.map { constraint in + guard case .length(let length) = constraint else { return nil } + let taken = min(max(0, length), remaining) + remaining -= taken + return taken + } + let fills = fixed.filter { $0 == nil }.count + var fillIndex = 0 + let heights: [Int] = fixed.map { height in + if let height { return height } + defer { fillIndex += 1 } + return remaining / fills + (fillIndex < remaining % fills ? 1 : 0) + } + + var top = y + return heights.map { rowHeight in + let row = Rect(x: x, y: top, width: width, height: rowHeight) + top += row.height + return row + } + } +} + +public struct Cell: Equatable { + public var symbol: String + public var style: TextStyle + + static let blank = Cell(symbol: " ", style: .plain) +} + +public struct Buffer: Equatable { + public let width: Int + public let height: Int + private var cells: [Cell] + + public var area: Rect { Rect(x: 0, y: 0, width: width, height: height) } + + public init(width: Int, height: Int) { + self.width = max(0, width) + self.height = max(0, height) + cells = Array(repeating: .blank, count: self.width * self.height) + } + + public subscript(x: Int, y: Int) -> Cell { + cells[index(x: x, y: y)] + } + + @discardableResult + public mutating func write(_ text: String, x: Int, y: Int, style: TextStyle = .plain, maxWidth: Int = .max) -> Int { + write([Span(text, style)], x: x, y: y, maxWidth: maxWidth) + } + + @discardableResult + public mutating func write(_ spans: [Span], x: Int, y: Int, maxWidth: Int = .max) -> Int { + guard (0.. 0 else { return 0 } + let limit = x + min(maxWidth, width - x) + var column = x + for span in spans { + for character in Term.sanitize(span.text) { + let characterWidth = Term.displayWidth(String(character)) + guard column + characterWidth <= limit else { return column - x } + for offset in 0.. [String] { + (0.. [String] { + lines(colors: false) + } + + private func index(x: Int, y: Int) -> Int { + precondition((0.. 0 { + cells[index - 1] = .blank + } + if column + 1 < width, cells[index + 1].symbol == "" { + cells[index + 1] = .blank + } + } +} diff --git a/cli/Sources/TerminalUI/Gauge.swift b/cli/Sources/TerminalUI/Gauge.swift new file mode 100644 index 0000000..9cd9097 --- /dev/null +++ b/cli/Sources/TerminalUI/Gauge.swift @@ -0,0 +1,15 @@ +public struct Gauge { + public var fraction: Double + + public init(fraction: Double) { + self.fraction = fraction + } + + public func spans(width: Int) -> [Span] { + let filled = Term.filledCount(fraction: fraction, width: width) + return [ + Span(String(repeating: "█", count: filled)), + Span(String(repeating: "░", count: max(0, width) - filled), TextStyle(dim: true)) + ].filter { !$0.text.isEmpty } + } +} diff --git a/cli/Sources/TerminalUI/KeyHints.swift b/cli/Sources/TerminalUI/KeyHints.swift new file mode 100644 index 0000000..7512bbc --- /dev/null +++ b/cli/Sources/TerminalUI/KeyHints.swift @@ -0,0 +1,47 @@ +public struct KeyHint: Equatable { + public var key: String, action: String + + public init(_ key: String, _ action: String) { + self.key = key + self.action = action + } +} + +public struct KeyHints { + public var hints: [KeyHint] + + public init(_ hints: [KeyHint]) { + self.hints = hints + } + + public func rows(width: Int) -> [[Span]] { + let separator = " " + var rows: [[Span]] = [] + var current: [Span] = [] + var used = 0 + for hint in hints { + let spans = [Span(hint.key), Span(" " + hint.action, TextStyle(dim: true))] + let hintWidth = spans.reduce(0) { $0 + Term.displayWidth($1.text) } + let needed = current.isEmpty ? hintWidth : used + separator.count + hintWidth + if !current.isEmpty, needed > width { + rows.append(current) + current = [] + } + if current.isEmpty { + used = hintWidth + } else { + current.append(Span(separator)) + used = needed + } + current += spans + } + if !current.isEmpty { rows.append(current) } + return rows + } + + public func render(in rect: Rect, buffer: inout Buffer) { + for (row, spans) in rows(width: rect.width).prefix(rect.height).enumerated() { + buffer.write(spans, x: rect.x, y: rect.y + row, maxWidth: rect.width) + } + } +} diff --git a/cli/Sources/TerminalUI/Scrollbar.swift b/cli/Sources/TerminalUI/Scrollbar.swift new file mode 100644 index 0000000..538ba62 --- /dev/null +++ b/cli/Sources/TerminalUI/Scrollbar.swift @@ -0,0 +1,29 @@ +public struct Scrollbar { + public var total: Int, visible: Int, offset: Int + + public init(total: Int, visible: Int, offset: Int) { + self.total = total + self.visible = visible + self.offset = offset + } + + public static func centeredOffset(total: Int, visible: Int, focus: Int) -> Int { + max(0, min(max(0, total - visible), focus - visible / 2)) + } + + public func thumb(trackHeight: Int) -> Range? { + guard total > visible, trackHeight > 0 else { return nil } + let length = max(1, Int((Double(trackHeight * visible) / Double(total)).rounded())) + let travel = total - visible + let clamped = max(0, min(travel, offset)) + let start = Int((Double((trackHeight - length) * clamped) / Double(travel)).rounded()) + return start..<(start + length) + } + + public func render(column x: Int, rows: Range, buffer: inout Buffer, style: TextStyle = .plain) { + guard let thumb = thumb(trackHeight: rows.count) else { return } + for row in thumb { + buffer.write("┃", x: x, y: rows.lowerBound + row, style: style) + } + } +} diff --git a/cli/Sources/TerminalUI/Style.swift b/cli/Sources/TerminalUI/Style.swift new file mode 100644 index 0000000..cef1029 --- /dev/null +++ b/cli/Sources/TerminalUI/Style.swift @@ -0,0 +1,47 @@ +public enum TerminalColor: Equatable { + case red, green, yellow, cyan + + var sgrCode: Int { + switch self { + case .red: return 31 + case .green: return 32 + case .yellow: return 33 + case .cyan: return 36 + } + } +} + +public struct TextStyle: Equatable { + public var color: TerminalColor? + public var bold: Bool + public var dim: Bool + public var inverse: Bool + + public init(color: TerminalColor? = nil, bold: Bool = false, dim: Bool = false, inverse: Bool = false) { + self.color = color + self.bold = bold + self.dim = dim + self.inverse = inverse + } + + public static let plain = TextStyle() + + var sgrParameters: String { + var codes: [Int] = [] + if bold { codes.append(1) } + if dim { codes.append(2) } + if inverse { codes.append(7) } + if let color { codes.append(color.sgrCode) } + return codes.map(String.init).joined(separator: ";") + } +} + +public struct Span: Equatable { + public var text: String + public var style: TextStyle + + public init(_ text: String, _ style: TextStyle = .plain) { + self.text = text + self.style = style + } +} diff --git a/cli/Sources/puremac/Core/Term.swift b/cli/Sources/TerminalUI/Term.swift similarity index 72% rename from cli/Sources/puremac/Core/Term.swift rename to cli/Sources/TerminalUI/Term.swift index ad5ba82..69d358c 100644 --- a/cli/Sources/puremac/Core/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -1,35 +1,33 @@ import Darwin import Foundation -enum Term { +public enum Term { private static let localeConfigured: Void = { setlocale(LC_CTYPE, "") }() - static var colorEnabled: Bool { + public static var colorEnabled: Bool { ProcessInfo.processInfo.environment["NO_COLOR"] == nil && ProcessInfo.processInfo.environment["TERM"] != "dumb" && isatty(fileno(stdout)) == 1 } - static func style(_ string: String, _ codes: String) -> String { + private static func style(_ string: String, _ codes: String) -> String { colorEnabled ? "\u{1B}[\(codes)m\(string)\u{1B}[0m" : string } - static func bold(_ string: String) -> String { style(string, "1") } - static func dim(_ string: String) -> String { style(string, "2") } - static func red(_ string: String) -> String { style(string, "31") } - static func green(_ string: String) -> String { style(string, "32") } - static func yellow(_ string: String) -> String { style(string, "33") } - static func blue(_ string: String) -> String { style(string, "34") } - static func cyan(_ string: String) -> String { style(string, "36") } - static func inverse(_ string: String) -> String { style(string, "7") } + public static func bold(_ string: String) -> String { style(string, "1") } + public static func dim(_ string: String) -> String { style(string, "2") } + public static func red(_ string: String) -> String { style(string, "31") } + public static func green(_ string: String) -> String { style(string, "32") } + public static func yellow(_ string: String) -> String { style(string, "33") } + public static func cyan(_ string: String) -> String { style(string, "36") } - static func err(_ string: String) { + public static func err(_ string: String) { FileHandle.standardError.write(Data((string + "\n").utf8)) } - static func confirm(_ prompt: String, default defaultValue: Bool = false) -> Bool { + public static func confirm(_ prompt: String, default defaultValue: Bool = false) -> Bool { guard isatty(fileno(stdin)) == 1 else { return defaultValue } let hint = defaultValue ? "[Y/n]" : "[y/N]" print("\(sanitize(prompt)) \(hint) ", terminator: "") @@ -39,15 +37,18 @@ enum Term { return answer == "y" || answer == "yes" } - static func bar(fraction: Double, width: Int = 24) -> String { - let safeWidth = max(0, width) - let clamped = max(0, min(1, fraction)) - let filled = Int((Double(safeWidth) * clamped).rounded()) + public static func bar(fraction: Double, width: Int = 24) -> String { + let filled = filledCount(fraction: fraction, width: width) return String(repeating: "█", count: filled) - + String(repeating: "░", count: safeWidth - filled) + + String(repeating: "░", count: max(0, width) - filled) + } + + static func filledCount(fraction: Double, width: Int) -> Int { + let clamped = max(0, min(1, fraction)) + return Int((Double(max(0, width)) * clamped).rounded()) } - static func sanitize(_ string: String) -> String { + public static func sanitize(_ string: String) -> String { var output = "" output.reserveCapacity(string.count) for scalar in string.unicodeScalars { @@ -67,7 +68,7 @@ enum Term { return output } - static func displayWidth(_ string: String) -> Int { + public static func displayWidth(_ string: String) -> Int { _ = localeConfigured var width = 0 var escapeState = 0 @@ -92,12 +93,12 @@ enum Term { return width } - static func pad(_ string: String, to width: Int) -> String { + public static func pad(_ string: String, to width: Int) -> String { let missing = max(0, width - displayWidth(string)) return string + String(repeating: " ", count: missing) } - static func truncate(_ string: String, to width: Int, middle: Bool = false) -> String { + public static func truncate(_ string: String, to width: Int, middle: Bool = false) -> String { let safe = sanitize(string) guard width > 0 else { return "" } guard displayWidth(safe) > width else { return safe } diff --git a/cli/Sources/puremac/Core/TerminalSession.swift b/cli/Sources/TerminalUI/TerminalSession.swift similarity index 92% rename from cli/Sources/puremac/Core/TerminalSession.swift rename to cli/Sources/TerminalUI/TerminalSession.swift index 97faf4b..ee79841 100644 --- a/cli/Sources/puremac/Core/TerminalSession.swift +++ b/cli/Sources/TerminalUI/TerminalSession.swift @@ -1,7 +1,7 @@ import Darwin import Foundation -enum TerminalKey: Equatable { +public enum TerminalKey: Equatable { case up case down case left @@ -19,7 +19,7 @@ enum TerminalKey: Equatable { case unknown } -enum TerminalSessionError: Error { +public enum TerminalSessionError: Error { case unsupported case setupFailed } @@ -75,8 +75,8 @@ private func terminalExitHandler() { terminalRestore() } -final class TerminalSession { - static var isSupported: Bool { +public final class TerminalSession { + public static var isSupported: Bool { isatty(STDIN_FILENO) == 1 && isatty(STDOUT_FILENO) == 1 && ProcessInfo.processInfo.environment["TERM"] != "dumb" @@ -84,15 +84,15 @@ final class TerminalSession { private var isClosed = false - var width: Int { + public var width: Int { terminalDimensions().width } - var height: Int { + public var height: Int { terminalDimensions().height } - init() throws { + public init() throws { guard Self.isSupported else { throw TerminalSessionError.unsupported } @@ -138,14 +138,18 @@ final class TerminalSession { close() } - func draw(lines: [String]) { - guard !isClosed else { return } + static func frame(lines: [String], height: Int) -> String { let visibleLines = Array(lines.prefix(max(1, height))) - let frame = visibleLines.map { "\u{1B}[2K" + $0 }.joined(separator: "\r\n") - terminalWrite("\u{1B}[H" + frame + "\u{1B}[J") + let body = visibleLines.map { "\u{1B}[2K" + $0 }.joined(separator: "\r\n") + return "\u{1B}[H" + body + (visibleLines.count < height ? "\u{1B}[J" : "") + } + + public func draw(_ buffer: Buffer) { + guard !isClosed else { return } + terminalWrite(Self.frame(lines: buffer.lines(), height: height)) } - func readKey() -> TerminalKey { + public func readKey() -> TerminalKey { guard !isClosed, let first = readByte() else { return .escape } switch first { @@ -164,7 +168,7 @@ final class TerminalSession { } } - func close() { + public func close() { guard !isClosed else { return } isClosed = true terminalRestore() diff --git a/cli/Sources/TerminalUI/Window.swift b/cli/Sources/TerminalUI/Window.swift new file mode 100644 index 0000000..394a16c --- /dev/null +++ b/cli/Sources/TerminalUI/Window.swift @@ -0,0 +1,75 @@ +public struct Window { + public var title: String + public var info: String? + public var borderStyle: TextStyle + public var titleStyle: TextStyle + public var infoStyle: TextStyle + + public init( + title: String, + info: String? = nil, + borderStyle: TextStyle = TextStyle(dim: true), + titleStyle: TextStyle = TextStyle(color: .cyan, bold: true), + infoStyle: TextStyle = TextStyle(bold: true) + ) { + self.title = title + self.info = info + self.borderStyle = borderStyle + self.titleStyle = titleStyle + self.infoStyle = infoStyle + } + + @discardableResult + public func render(in rect: Rect, buffer: inout Buffer) -> Rect { + guard rect.width >= 2, rect.height >= 2 else { return contentRect(in: rect) } + let right = rect.x + rect.width - 1 + let bottom = rect.y + rect.height - 1 + buffer.write(horizontalBorder("╭", "╮", width: rect.width), x: rect.x, y: rect.y, style: borderStyle) + buffer.write(horizontalBorder("╰", "╯", width: rect.width), x: rect.x, y: bottom, style: borderStyle) + for row in (rect.y + 1).. Rect { + guard rect.width >= 2, rect.height >= 2 else { + return Rect(x: rect.x, y: rect.y, width: 0, height: 0) + } + return Rect( + x: rect.x + 2, + y: rect.y + 1, + width: max(0, rect.width - 4), + height: max(0, rect.height - 2) + ) + } + + public func renderDivider(atRow y: Int, in rect: Rect, buffer: inout Buffer) { + guard rect.width >= 2 else { return } + buffer.write(horizontalBorder("├", "┤", width: rect.width), x: rect.x, y: y, style: borderStyle) + } + + private func horizontalBorder(_ left: String, _ right: String, width: Int) -> String { + left + String(repeating: "─", count: width - 2) + right + } + + private func renderTitle(in rect: Rect, buffer: inout Buffer) { + let infoText = info.map(Term.sanitize) + var titleSpace = rect.width - 6 + if let infoText { + let infoWidth = Term.displayWidth(infoText) + let withInfo = rect.width - 9 - infoWidth + if withInfo >= 4 { + titleSpace = withInfo + let infoColumn = rect.x + rect.width - 4 - infoWidth + buffer.write([Span(" "), Span(infoText, infoStyle), Span(" ")], x: infoColumn, y: rect.y) + } + } + let text = Term.truncate(title, to: titleSpace) + if !text.isEmpty { + buffer.write([Span(" "), Span(text, titleStyle), Span(" ")], x: rect.x + 2, y: rect.y) + } + } +} diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index a07e2b9..2980b42 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI struct Analyze: ParsableCommand { static let configuration = CommandConfiguration( @@ -241,7 +242,7 @@ struct Analyze: ParsableCommand { private func browse(_ target: String, ignore: IgnoreStore) throws { let session = try TerminalSession() defer { session.close() } - session.draw(lines: measuringLines(target, width: session.width)) + session.draw(Self.renderMeasuring(target, width: session.width, height: session.height)) var levels = [BrowserLevel(snapshot: scanFolder(target, ignore: ignore))] var running = true @@ -254,7 +255,7 @@ struct Analyze: ParsableCommand { count: levels[index].snapshot.children.count, visibleRows: visibleRows ) - session.draw(lines: Self.browserLines(level: levels[index], width: session.width, height: session.height)) + session.draw(Self.renderBrowser(level: levels[index], width: session.width, height: session.height)) switch session.readKey() { case .up: @@ -271,7 +272,7 @@ struct Analyze: ParsableCommand { levels[index].selected = max(0, levels[index].snapshot.children.count - 1) case .enter, .right: guard let child = Self.focusedChild(levels[index]), child.isDir, !child.isPackage else { continue } - session.draw(lines: measuringLines(child.path, width: session.width)) + session.draw(Self.renderMeasuring(child.path, width: session.width, height: session.height)) levels.append(BrowserLevel(snapshot: scanFolder(child.path, ignore: ignore))) case .left, .backspace: if levels.count > 1 { levels.removeLast() } @@ -290,66 +291,151 @@ struct Analyze: ParsableCommand { } } - private func measuringLines(_ path: String, width: Int) -> [String] { - let safeWidth = max(1, width) - return [ - Term.bold(Term.cyan(Term.truncate("PureMac Space Explorer", to: safeWidth))), - "", - Term.dim(Term.truncate("Measuring allocated space...", to: safeWidth)), - Term.truncate(path, to: safeWidth, middle: true), - "", - Term.dim(Term.truncate("Ctrl+C cancel", to: safeWidth)) - ] + static func renderMeasuring(_ path: String, width: Int, height: Int) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: windowTitle, exitHint: "Ctrl+C cancel", width: width, height: height) + } + var buffer = Buffer(width: width, height: height) + let content = window.render(in: buffer.area, buffer: &buffer) + let cancelHint = KeyHints([KeyHint("Ctrl+C", "cancel")]) + let areas = content.splitRows([.length(2), .fill, .length(1), .length(cancelHint.rows(width: content.width).count)]) + let (header, divider, footer) = (areas[0], areas[2], areas[3]) + + buffer.write("Measuring allocated space...", x: header.x, y: header.y, style: TextStyle(dim: true), maxWidth: header.width) + buffer.write(Term.truncate(path, to: header.width, middle: true), x: header.x, y: header.y + 1) + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + cancelHint.render(in: footer, buffer: &buffer) + return buffer + } + + private static let windowTitle = "PureMac Space Explorer" + private static let focusedLabel = "Focused: " + private static let window = Window(title: windowTitle) + private static let rowPrefixWidth = 4 + Render.sizeColumnWidth + private static let minimumGaugeWidth = 6 + private static let maximumGaugeWidth = 20 + private static let gaugeReservedWidth = 32 + private static let headerRows = 2 + private static let dividerRows = 1 + private static let minimumListRows = 3 + private static let browserHints = KeyHints([ + KeyHint("↑↓", "move"), + KeyHint("Enter/→", "open"), + KeyHint("O", "reveal"), + KeyHint("←/⌫", "back"), + KeyHint("q/Esc", "exit") + ]) + + private struct BrowserLayout { + let header: Rect + let list: Rect + let divider: Rect + let path: Rect + let error: Rect + let footer: Rect + let pathLines: [String] + + var visibleRows: Int { max(1, list.height) } + } + + private static func layout(snapshot: FolderSnapshot, selected: Int, width: Int, height: Int) -> BrowserLayout { + let content = window.contentRect(in: Rect(x: 0, y: 0, width: width, height: height)) + let focusedPath = snapshot.children.indices.contains(selected) ? snapshot.children[selected].path : snapshot.path + let pathWidth = max(1, content.width - focusedLabel.count) + let hintRows = browserHints.rows(width: content.width).count + let errorRows = snapshot.errors.isEmpty ? 0 : 1 + let spareRows = content.height - headerRows - dividerRows - errorRows - hintRows - minimumListRows + var pathLines = wrap(focusedPath, width: pathWidth) + let pathRows = min(pathLines.count, max(1, spareRows)) + var budget = pathRows * pathWidth + while pathLines.count > pathRows && budget > 1 { + pathLines = wrap(Term.truncate(focusedPath, to: budget, middle: true), width: pathWidth) + budget -= 1 + } + let areas = content.splitRows( + [.length(headerRows), .fill, .length(dividerRows), .length(pathRows), .length(errorRows), .length(hintRows)] + ) + return BrowserLayout( + header: areas[0], + list: areas[1], + divider: areas[2], + path: areas[3], + error: areas[4], + footer: areas[5], + pathLines: pathLines + ) } - static func browserLines(level: BrowserLevel, width: Int, height: Int) -> [String] { - let safeWidth = max(1, width) - let safeHeight = max(1, height) - if safeWidth < 40 || safeHeight < 12 { - let compact = [ - Term.bold(Term.cyan(Term.truncate("PureMac Space Explorer", to: safeWidth))), - Term.truncate("Terminal too small", to: safeWidth), - Term.dim(Term.truncate("Resize to at least 40 x 12", to: safeWidth)), - "", - Term.dim(Term.truncate("Esc/q exit", to: safeWidth)) - ] - return Array(compact.prefix(safeHeight)) + static func renderBrowser(level: BrowserLevel, width: Int, height: Int) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: windowTitle, exitHint: "Esc/q exit", width: width, height: height) } + var buffer = Buffer(width: width, height: height) let snapshot = level.snapshot - let pathLines = wrap(focusedChild(level)?.path ?? snapshot.path, width: max(1, safeWidth - 9)) - let visibleRows = visibleRowCount(snapshot: snapshot, selected: level.selected, width: safeWidth, height: safeHeight) - let upperBound = min(snapshot.children.count, level.offset + visibleRows) - let rows = level.offset < upperBound - ? snapshot.children[level.offset.. 0 ? Term.red("Folder contents are inaccessible.") : Term.dim("No measurable items.")] - : rows) - lines.append(String(repeating: "─", count: safeWidth)) - lines.append(Term.dim("↑↓ move Enter/→ open O reveal")) - lines.append(Term.dim("←/⌫ back q/Esc exit")) - for (index, line) in pathLines.enumerated() { - lines.append((index == 0 ? Term.dim("Focused: ") : String(repeating: " ", count: 9)) + line) + window.render(in: buffer.area, buffer: &buffer) + let layout = layout(snapshot: snapshot, selected: level.selected, width: width, height: height) + + buffer.write( + Term.truncate(snapshot.path, to: layout.header.width, middle: true), + x: layout.header.x, + y: layout.header.y, + style: TextStyle(bold: true) + ) + buffer.write( + statusLine(snapshot, width: layout.header.width), + x: layout.header.x, + y: layout.header.y + 1, + style: TextStyle(dim: true) + ) + window.renderDivider(atRow: layout.divider.y, in: buffer.area, buffer: &buffer) + renderRows(level: level, in: layout.list, buffer: &buffer) + Scrollbar(total: snapshot.children.count, visible: layout.visibleRows, offset: level.offset) + .render(column: width - 1, rows: layout.list.y..<(layout.list.y + layout.list.height), buffer: &buffer) + + for (index, line) in layout.pathLines.prefix(layout.path.height).enumerated() { + let label = index == 0 ? focusedLabel : String(repeating: " ", count: focusedLabel.count) + buffer.write( + [Span(label, TextStyle(dim: true)), Span(line)], + x: layout.path.x, + y: layout.path.y + index, + maxWidth: layout.path.width + ) } if let error = snapshot.errors.first { - lines.append(Term.red("! ") + Term.truncate(error, to: max(1, safeWidth - 2), middle: true)) + let area = layout.error + buffer.write( + [Span("! ", TextStyle(color: .red)), Span(Term.truncate(error, to: max(1, area.width - 2), middle: true))], + x: area.x, + y: area.y, + maxWidth: area.width + ) + } + browserHints.render(in: layout.footer, buffer: &buffer) + return buffer + } + + private static func renderRows(level: BrowserLevel, in list: Rect, buffer: inout Buffer) { + let snapshot = level.snapshot + let upperBound = min(snapshot.children.count, level.offset + list.height) + guard level.offset < upperBound else { + let inaccessible = snapshot.inaccessibleCount > 0 + buffer.write( + inaccessible ? "Folder contents are inaccessible." : "No measurable items.", + x: list.x, + y: list.y, + style: inaccessible ? TextStyle(color: .red) : TextStyle(dim: true), + maxWidth: list.width + ) + return + } + for (offset, child) in snapshot.children[level.offset.. Int { - let focusedPath = snapshot.children.indices.contains(selected) ? snapshot.children[selected].path : snapshot.path - let pathLines = wrap(focusedPath, width: max(1, max(1, width) - 9)).count - return max(1, height - 7 - pathLines - (snapshot.errors.isEmpty ? 0 : 1)) + layout(snapshot: snapshot, selected: selected, width: width, height: height).visibleRows } static func adjustedOffset(_ offset: Int, selected: Int, count: Int, visibleRows: Int) -> Int { @@ -366,16 +452,27 @@ struct Analyze: ParsableCommand { return level.snapshot.children[level.selected] } - private static func row(_ child: Child, focused: Bool, total: Int64, width: Int) -> String { + private static func renderRow(_ child: Child, focused: Bool, total: Int64, in rect: Rect, buffer: inout Buffer) { let fraction = total > 0 ? Double(child.size) / Double(total) : 0 - let size = Render.pad(ByteCount.human(child.size), 10) - let barWidth = min(20, max(6, (width - 32) / 3)) + let barWidth = min(maximumGaugeWidth, max(minimumGaugeWidth, (rect.width - gaugeReservedWidth) / 3)) let suffix = child.isDir && !child.isPackage ? "/" : (child.isPackage ? " [package]" : "") let partial = child.isPartial ? " !" : "" - let nameWidth = max(1, width - 14 - barWidth - partial.count) + let nameColumn = rect.width - rowPrefixWidth - barWidth + let nameWidth = max(1, nameColumn - partial.count) let name = Term.truncate(URL(fileURLWithPath: child.path).lastPathComponent + suffix, to: nameWidth, middle: true) - let line = "\(focused ? "›" : " ") \(size) \(Term.bar(fraction: fraction, width: barWidth)) \(name)\(partial)" - return focused ? Term.inverse(Term.pad(line, to: width)) : line + let rowStyle = TextStyle(inverse: focused) + let gauge = Gauge(fraction: fraction).spans(width: barWidth).map { + Span($0.text, TextStyle(dim: $0.style.dim, inverse: focused)) + } + buffer.write( + [FocusPointer.span(focused: focused), + Span(" " + Render.sizeCol(child.size) + " ", rowStyle)] + + gauge + + [Span(" " + Term.pad(name + partial, to: nameColumn), rowStyle)], + x: rect.x, + y: rect.y, + maxWidth: rect.width + ) } private static func statusLine(_ snapshot: FolderSnapshot, width: Int) -> String { diff --git a/cli/Sources/puremac/Commands/Clean.swift b/cli/Sources/puremac/Commands/Clean.swift index b791f74..09c440b 100644 --- a/cli/Sources/puremac/Commands/Clean.swift +++ b/cli/Sources/puremac/Commands/Clean.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI struct Clean: ParsableCommand { static let configuration = CommandConfiguration( diff --git a/cli/Sources/puremac/Commands/Config.swift b/cli/Sources/puremac/Commands/Config.swift index a510e42..57b1571 100644 --- a/cli/Sources/puremac/Commands/Config.swift +++ b/cli/Sources/puremac/Commands/Config.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI struct Config: ParsableCommand { static let configuration = CommandConfiguration( diff --git a/cli/Sources/puremac/Commands/Ignore.swift b/cli/Sources/puremac/Commands/Ignore.swift index 8276f42..4a78825 100644 --- a/cli/Sources/puremac/Commands/Ignore.swift +++ b/cli/Sources/puremac/Commands/Ignore.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI struct Ignore: ParsableCommand { static let configuration = CommandConfiguration( diff --git a/cli/Sources/puremac/Commands/Optimize.swift b/cli/Sources/puremac/Commands/Optimize.swift index eeda248..0a0497d 100644 --- a/cli/Sources/puremac/Commands/Optimize.swift +++ b/cli/Sources/puremac/Commands/Optimize.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI struct Optimize: ParsableCommand { static let configuration = CommandConfiguration( diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 8c2cba8..82909c4 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI struct Purge: ParsableCommand { static let configuration = CommandConfiguration( diff --git a/cli/Sources/puremac/Core/FocusPointer.swift b/cli/Sources/puremac/Core/FocusPointer.swift new file mode 100644 index 0000000..897dd41 --- /dev/null +++ b/cli/Sources/puremac/Core/FocusPointer.swift @@ -0,0 +1,7 @@ +import TerminalUI + +enum FocusPointer { + static func span(focused: Bool) -> Span { + Span(focused ? "›" : " ", TextStyle(color: focused ? .cyan : nil, inverse: focused)) + } +} diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index 65c3c21..b4b3d3b 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -1,4 +1,5 @@ import Foundation +import TerminalUI struct ReviewAddress: Hashable { let category: Int @@ -214,7 +215,7 @@ enum InteractiveReview { var model = InteractiveReviewModel(categories: categories) while true { - session.draw(lines: render(model: model, title: title, width: session.width, height: session.height)) + session.draw(render(model: model, title: title, width: session.width, height: session.height)) let key = session.readKey() if model.isSearching { @@ -292,125 +293,151 @@ enum InteractiveReview { } } + private static let itemPrefixWidth = 5 + Render.sizeColumnWidth + private static let summaryGap = 2 + static func render( model: InteractiveReviewModel, title: String, width: Int, height: Int - ) -> [String] { - let safeWidth = max(1, width) - let safeHeight = max(1, height) - if safeWidth < 40 || safeHeight < 12 { - return compactScreen(width: safeWidth, height: safeHeight) + ) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: "PureMac", exitHint: "Esc/q cancel", width: width, height: height) } - let titleText = Term.truncate(title, to: safeWidth - 2) - let selection = "\(model.selectedCount) selected · \(ByteCount.human(model.selectedBytes))" - let found = "\(model.matchingAddresses.count) shown · \(ByteCount.human(model.allBytes))" - var lines = [ - Term.dim("PUREMAC / \(model.isReviewing ? "FINAL REVIEW" : "SELECT ITEMS")"), - Term.bold(Term.cyan(titleText)), - statusLine(left: found, right: selection, width: safeWidth) - ] - - if model.isSearching { - let query = Term.truncate(model.query, to: max(1, safeWidth - 10)) - lines.append(Term.cyan("Search ") + query + Term.inverse(" ")) - } else if !model.status.isEmpty { - lines.append(Term.yellow(Term.truncate(model.status, to: safeWidth))) - } else if model.query.isEmpty { - lines.append("") - } else { - lines.append(Term.dim("Filter ") + Term.truncate(model.query, to: max(1, safeWidth - 9))) + var buffer = Buffer(width: width, height: height) + let reviewing = model.isReviewing + let accent = TextStyle(color: .yellow) + let window = Window( + title: reviewing ? "Final review" : title, + info: "\(model.selectedCount) selected · \(ByteCount.human(model.selectedBytes))", + borderStyle: reviewing ? accent : TextStyle(dim: true), + titleStyle: TextStyle(color: reviewing ? .yellow : .cyan, bold: true) + ) + let content = window.render(in: buffer.area, buffer: &buffer) + let hints = KeyHints(reviewing ? reviewHints : selectHints) + let areas = content.splitRows( + [.length(1), .fill, .length(1), .length(1), .length(hints.rows(width: content.width).count), .length(reviewing ? 1 : 0)] + ) + let (header, list, divider, path, footer, confirmation) = (areas[0], areas[1], areas[2], areas[3], areas[4], areas[5]) + + renderHeader(model: model, in: header, buffer: &buffer) + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + buffer.write(focusedPathSpans(model: model, width: path.width), x: path.x, y: path.y, maxWidth: path.width) + hints.render(in: footer, buffer: &buffer) + if reviewing { + buffer.write("Command confirmation follows", x: confirmation.x, y: confirmation.y, style: accent, maxWidth: confirmation.width) } - let footerHeight = 5 - let bodyHeight = max(3, safeHeight - lines.count - footerHeight) - let rows = model.displayRows(reviewing: model.isReviewing) + let rows = model.displayRows(reviewing: reviewing) let focusedAddress = model.focusedAddress let focusedRow = rows.firstIndex { row in if case .item(let address) = row { return address == focusedAddress } return false } ?? 0 - let start = max(0, min(max(0, rows.count - bodyHeight), focusedRow - bodyHeight / 2)) - let visibleRows = rows.dropFirst(start).prefix(bodyHeight) - - for row in visibleRows { - switch row { - case .category(let categoryIndex): - let category = model.categories[categoryIndex] - let label = Term.truncate(Term.sanitize(category.title).uppercased(), to: safeWidth - 4) - lines.append(" " + Term.bold(Term.cyan(label))) - case .group(let categoryIndex, let groupIndex): - let group = model.categories[categoryIndex].groups[groupIndex] - let suffix = "\(group.items.count) \(group.items.count == 1 ? "item" : "items")" - let available = max(1, safeWidth - 8 - suffix.count) - lines.append(" " + Term.dim(Term.pad(Term.truncate(group.tool, to: available), to: available) + suffix)) - case .item(let address): - let item = model.item(at: address) - let focused = address == focusedAddress - let mark = item.selected ? Term.cyan("●") : Term.dim("○") - let pointer = focused ? Term.cyan("›") : " " - let size = Term.pad(ByteCount.human(item.sizeBytes), to: 10) - let pathWidth = max(6, safeWidth - 17) - let path = Term.truncate(Render.shorten(item.path), to: pathWidth, middle: true) - let content = "\(pointer) \(mark) \(size) \(path)" - lines.append(focused ? Term.inverse(content) : content) - } - } - - while lines.count < safeHeight - footerHeight { - lines.append("") + let start = Scrollbar.centeredOffset(total: rows.count, visible: list.height, focus: focusedRow) + for (index, row) in rows.enumerated().dropFirst(start).prefix(list.height) { + let rect = Rect(x: list.x, y: list.y + index - start, width: list.width, height: 1) + renderRow(row, focused: focusedAddress, model: model, in: rect, buffer: &buffer) } + Scrollbar(total: rows.count, visible: list.height, offset: start) + .render(column: width - 1, rows: list.y..<(list.y + list.height), buffer: &buffer) + return buffer + } - let divider = String(repeating: "─", count: safeWidth) - lines.append(Term.dim(divider)) - lines.append(focusedPathLine(model: model, width: safeWidth)) - if model.isReviewing { - lines.append(Term.dim("↑↓ scroll ←→ path")) - lines.append(Term.dim("Enter confirm Esc edit")) - lines.append(Term.yellow("q cancel command confirmation follows")) + private static let selectHints = [ + KeyHint("↑↓", "move"), + KeyHint("←→", "path"), + KeyHint("Space", "toggle"), + KeyHint("A", "all"), + KeyHint("N", "none"), + KeyHint("/", "search"), + KeyHint("Enter", "review"), + KeyHint("Esc/q", "cancel") + ] + + private static let reviewHints = [ + KeyHint("↑↓", "scroll"), + KeyHint("←→", "path"), + KeyHint("Enter", "confirm"), + KeyHint("Esc", "edit"), + KeyHint("q", "cancel") + ] + + private static func renderHeader(model: InteractiveReviewModel, in rect: Rect, buffer: inout Buffer) { + let dim = TextStyle(dim: true) + let found = "\(model.matchingAddresses.count) shown · \(ByteCount.human(model.allBytes))" + let left: [Span] + if model.isSearching { + let label = "Search " + let query = Term.truncate(model.query, to: max(1, rect.width - label.count - 1)) + left = [Span(label, TextStyle(color: .cyan)), Span(query), Span(" ", TextStyle(inverse: true))] + } else if !model.status.isEmpty { + left = [Span(Term.truncate(model.status, to: rect.width), TextStyle(color: .yellow))] + } else if !model.query.isEmpty { + let label = "Filter " + left = [Span(label + Term.truncate(model.query, to: max(1, rect.width - label.count)), dim)] } else { - lines.append(Term.dim("↑↓ move ←→ path Space toggle")) - lines.append(Term.dim("A all N none / search")) - lines.append(Term.dim("Enter review Esc/q cancel")) + buffer.write(Term.truncate(found, to: rect.width), x: rect.x, y: rect.y, style: dim) + return + } + let leftWidth = buffer.write(left, x: rect.x, y: rect.y, maxWidth: rect.width) + let foundWidth = Term.displayWidth(found) + if leftWidth + summaryGap + foundWidth <= rect.width { + buffer.write(found, x: rect.x + rect.width - foundWidth, y: rect.y, style: dim) } - return Array(lines.prefix(safeHeight)) - } - - private static func compactScreen(width: Int, height: Int) -> [String] { - let lines = [ - Term.bold(Term.cyan(Term.truncate("PureMac", to: width))), - Term.truncate("Terminal too small", to: width), - Term.dim(Term.truncate("Resize to at least 40 x 12", to: width)), - "", - Term.dim(Term.truncate("Esc/q cancel", to: width)) - ] - return Array(lines.prefix(height)) } - static func statusLine(left: String, right: String, width: Int) -> String { - let available = max(1, width - 2) - let leftWidth = Term.displayWidth(left) - let rightWidth = Term.displayWidth(right) - if leftWidth + rightWidth <= available { - return Term.pad(left, to: available - rightWidth) + " " + Term.bold(right) + private static func renderRow( + _ row: ReviewDisplayRow, + focused focusedAddress: ReviewAddress?, + model: InteractiveReviewModel, + in rect: Rect, + buffer: inout Buffer + ) { + switch row { + case .category(let categoryIndex): + let title = Term.truncate(model.categories[categoryIndex].title, to: rect.width) + buffer.write(title, x: rect.x, y: rect.y, style: TextStyle(bold: true), maxWidth: rect.width) + case .group(let categoryIndex, let groupIndex): + let group = model.categories[categoryIndex].groups[groupIndex] + let suffix = "\(group.items.count) \(group.items.count == 1 ? "item" : "items")" + let label = Term.truncate(group.tool, to: max(1, rect.width - suffix.count - 1)) + buffer.write( + Term.pad(label, to: rect.width - suffix.count) + suffix, + x: rect.x, + y: rect.y, + style: TextStyle(dim: true), + maxWidth: rect.width + ) + case .item(let address): + let item = model.item(at: address) + let focused = address == focusedAddress + let rowStyle = TextStyle(inverse: focused) + let pathWidth = max(1, rect.width - itemPrefixWidth) + let path = Term.truncate(Render.shorten(item.path), to: pathWidth, middle: true) + buffer.write( + [ + FocusPointer.span(focused: focused), + Span(" ", rowStyle), + Span(item.selected ? "●" : "○", TextStyle(color: item.selected ? .cyan : nil, dim: !item.selected, inverse: focused)), + Span(" " + Render.sizeCol(item.sizeBytes) + " " + Term.pad(path, to: pathWidth), rowStyle) + ], + x: rect.x, + y: rect.y, + maxWidth: rect.width + ) } - - let rightBudget = min(rightWidth, max(1, available / 2)) - let leftBudget = max(1, available - rightBudget) - let clippedLeft = Term.truncate(left, to: leftBudget) - let clippedRight = Term.truncate(right, to: rightBudget) - return Term.pad(clippedLeft, to: leftBudget) + " " + Term.bold(clippedRight) } - private static func focusedPathLine(model: InteractiveReviewModel, width: Int) -> String { + private static func focusedPathSpans(model: InteractiveReviewModel, width: Int) -> [Span] { + let label = TextStyle(dim: true) guard let address = model.focusedAddress else { - return Term.dim("Path No matching item") + return [Span("Path No matching item", label)] } let path = Render.shorten(model.item(at: address).path) - let available = max(1, width - 6) - let window = horizontalWindow(path, offset: model.pathOffset, width: available) - return Term.dim("Path ") + window + let window = horizontalWindow(path, offset: model.pathOffset, width: max(1, width - 6)) + return [Span("Path ", label), Span(window)] } static func horizontalWindow(_ value: String, offset: Int, width: Int) -> String { diff --git a/cli/Sources/puremac/Core/Render.swift b/cli/Sources/puremac/Core/Render.swift index 0d4a6ca..1710e39 100644 --- a/cli/Sources/puremac/Core/Render.swift +++ b/cli/Sources/puremac/Core/Render.swift @@ -1,8 +1,10 @@ import Darwin import Foundation +import TerminalUI enum Render { static let rule = String(repeating: "─", count: 60) + static let sizeColumnWidth = 10 static func scanResults(_ categories: [CategoryScan]) { let total = categories.reduce(Int64(0)) { $0 + $1.allBytes } @@ -104,7 +106,7 @@ enum Render { } static func sizeCol(_ bytes: Int64) -> String { - pad(ByteCount.human(bytes), 10) + pad(ByteCount.human(bytes), sizeColumnWidth) } static func pad(_ string: String, _ width: Int) -> String { diff --git a/cli/Sources/puremac/Core/TerminalMenu.swift b/cli/Sources/puremac/Core/TerminalMenu.swift index 1eb06b2..9255757 100644 --- a/cli/Sources/puremac/Core/TerminalMenu.swift +++ b/cli/Sources/puremac/Core/TerminalMenu.swift @@ -1,4 +1,5 @@ import Foundation +import TerminalUI struct TerminalMenuModel { let optionCount: Int @@ -38,7 +39,7 @@ enum TerminalMenu { var model = TerminalMenuModel(optionCount: options.count) while true { session.draw( - lines: render( + render( title: title, subtitle: subtitle, options: options, @@ -86,50 +87,65 @@ enum TerminalMenu { selection: Int, width: Int, height: Int - ) -> [String] { - let safeWidth = max(1, width) - let safeHeight = max(1, height) - if safeWidth < 40 || safeHeight < 12 { - let compact = [ - Term.bold(Term.cyan(Term.truncate("PureMac", to: safeWidth))), - Term.truncate("Terminal too small", to: safeWidth), - Term.dim(Term.truncate("Resize to at least 40 x 12", to: safeWidth)), - "", - Term.dim(Term.truncate("Esc/q cancel", to: safeWidth)) - ] - return Array(compact.prefix(safeHeight)) + ) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: "PureMac", exitHint: "Esc/q cancel", width: width, height: height) } - let safeSelection = min(max(0, selection), max(0, options.count - 1)) - var lines = [ - Term.dim("PUREMAC / CHOOSE A TOOL"), - Term.bold(Term.cyan(Term.truncate(title, to: safeWidth))), - Term.dim(Term.truncate(subtitle, to: safeWidth)), - "" - ] - - let footerHeight = 3 - let rowHeight = 2 - let visibleCount = max(1, (safeHeight - lines.count - footerHeight) / rowHeight) - let start = max(0, min(max(0, options.count - visibleCount), safeSelection - visibleCount / 2)) - let visible = options.enumerated().dropFirst(start).prefix(visibleCount) + var buffer = Buffer(width: width, height: height) + let window = Window(title: title) + let content = window.render(in: buffer.area, buffer: &buffer) + let hints = KeyHints([ + KeyHint("↑↓", "move"), + KeyHint("PgUp/PgDn", "page"), + KeyHint("1-9", "open"), + KeyHint("Enter", "open"), + KeyHint("Esc/q", "cancel") + ]) + let areas = content.splitRows([.length(2), .fill, .length(1), .length(hints.rows(width: content.width).count)]) + let (header, list, divider, footer) = (areas[0], areas[1], areas[2], areas[3]) - for (index, option) in visible { - let focused = index == safeSelection - let number = Term.pad("\(index + 1).", to: 4) - let titleWidth = max(1, safeWidth - 6) - let titleLine = "\(focused ? "›" : " ") \(number)\(Term.truncate(option.title, to: titleWidth))" - let detailLine = " " + Term.truncate(option.detail, to: max(1, safeWidth - 6)) - lines.append(focused ? Term.inverse(titleLine) : titleLine) - lines.append(focused ? Term.bold(detailLine) : Term.dim(detailLine)) - } + buffer.write(Term.truncate(subtitle, to: header.width), x: header.x, y: header.y, style: TextStyle(dim: true)) + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + hints.render(in: footer, buffer: &buffer) - while lines.count < safeHeight - footerHeight { - lines.append("") + let safeSelection = min(max(0, selection), max(0, options.count - 1)) + let rowHeight = 2 + let visibleCount = max(1, list.height / rowHeight) + let start = Scrollbar.centeredOffset(total: options.count, visible: visibleCount, focus: safeSelection) + for (index, option) in options.enumerated().dropFirst(start).prefix(visibleCount) { + let rect = Rect(x: list.x, y: list.y + (index - start) * rowHeight, width: list.width, height: rowHeight) + renderOption(option, number: index + 1, focused: index == safeSelection, in: rect, buffer: &buffer) } + Scrollbar(total: options.count, visible: visibleCount, offset: start) + .render(column: width - 1, rows: list.y..<(list.y + visibleCount * rowHeight), buffer: &buffer) + return buffer + } - lines.append(Term.dim(String(repeating: "─", count: safeWidth))) - lines.append(Term.dim("↑↓ move PgUp/PgDn page 1-9 open")) - lines.append(Term.dim("Enter open Esc/q cancel")) - return Array(lines.prefix(safeHeight)) + private static func renderOption( + _ option: (title: String, detail: String), + number: Int, + focused: Bool, + in rect: Rect, + buffer: inout Buffer + ) { + let indent = 6 + let textWidth = max(1, rect.width - indent) + let rowStyle = TextStyle(inverse: focused) + buffer.write( + [ + FocusPointer.span(focused: focused), + Span(" " + Term.pad("\(number).", to: 4) + Term.pad(Term.truncate(option.title, to: textWidth), to: textWidth), rowStyle) + ], + x: rect.x, + y: rect.y, + maxWidth: rect.width + ) + buffer.write( + Term.truncate(option.detail, to: textWidth), + x: rect.x + indent, + y: rect.y + 1, + style: TextStyle(dim: !focused), + maxWidth: textWidth + ) } } diff --git a/cli/Sources/puremac/Core/TooSmallScreen.swift b/cli/Sources/puremac/Core/TooSmallScreen.swift new file mode 100644 index 0000000..9068568 --- /dev/null +++ b/cli/Sources/puremac/Core/TooSmallScreen.swift @@ -0,0 +1,25 @@ +import TerminalUI + +enum TooSmallScreen { + static let minimumWidth = 40 + static let minimumHeight = 12 + + static func fits(width: Int, height: Int) -> Bool { + width >= minimumWidth && height >= minimumHeight + } + + static func render(title: String, exitHint: String, width: Int, height: Int) -> Buffer { + var buffer = Buffer(width: width, height: height) + let rows: [(String, TextStyle)] = [ + (title, TextStyle(color: .cyan, bold: true)), + ("Terminal too small", .plain), + ("Resize to at least \(minimumWidth) x \(minimumHeight)", TextStyle(dim: true)), + ("", .plain), + (exitHint, TextStyle(dim: true)) + ] + for (row, (text, style)) in rows.enumerated() { + buffer.write(Term.truncate(text, to: width), x: 0, y: row, style: style) + } + return buffer + } +} diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index e755d75..109eea8 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -1,5 +1,6 @@ import ArgumentParser import Foundation +import TerminalUI let puremacVersion = "1.1.1" diff --git a/cli/Tests/TerminalUITests/BufferTests.swift b/cli/Tests/TerminalUITests/BufferTests.swift new file mode 100644 index 0000000..86363d4 --- /dev/null +++ b/cli/Tests/TerminalUITests/BufferTests.swift @@ -0,0 +1,165 @@ +import XCTest +@testable import TerminalUI + +final class BufferTests: XCTestCase { + private let esc = "\u{1B}" + + func testSplitRowsLengthsAndFills() { + let rect = Rect(x: 3, y: 2, width: 10, height: 10) + let rows = rect.splitRows([.length(2), .fill, .length(3)]) + XCTAssertEqual(rows, [ + Rect(x: 3, y: 2, width: 10, height: 2), + Rect(x: 3, y: 4, width: 10, height: 5), + Rect(x: 3, y: 9, width: 10, height: 3) + ]) + } + + func testSplitRowsFillsShareRemainderToFirst() { + let rows = Rect(x: 0, y: 0, width: 4, height: 7).splitRows([.fill, .fill, .fill]) + XCTAssertEqual(rows.map(\.height), [3, 2, 2]) + XCTAssertEqual(rows.map(\.y), [0, 3, 5]) + } + + func testSplitRowsOverflowGivesLaterItemsNoHeight() { + let rows = Rect(x: 0, y: 0, width: 4, height: 5).splitRows([.length(3), .length(4), .length(2), .fill]) + XCTAssertEqual(rows.map(\.height), [3, 2, 0, 0]) + XCTAssertEqual(rows.map(\.y), [0, 3, 5, 5]) + } + + func testNewBufferIsBlankAndClamped() { + let buffer = Buffer(width: 3, height: 2) + XCTAssertEqual(buffer.area, Rect(x: 0, y: 0, width: 3, height: 2)) + XCTAssertEqual(buffer.plainLines(), [" ", " "]) + XCTAssertEqual(buffer[1, 1], Cell(symbol: " ", style: .plain)) + let empty = Buffer(width: -4, height: -1) + XCTAssertEqual(empty.area, Rect(x: 0, y: 0, width: 0, height: 0)) + XCTAssertEqual(empty.plainLines(), []) + } + + func testWriteReturnsColumnsAndPlacesText() { + var buffer = Buffer(width: 6, height: 2) + XCTAssertEqual(buffer.write("abc", x: 1, y: 1), 3) + XCTAssertEqual(buffer.plainLines(), [" ", " abc "]) + } + + func testWriteClipsAtMaxWidthAndEdge() { + var buffer = Buffer(width: 5, height: 1) + XCTAssertEqual(buffer.write("abcdef", x: 0, y: 0, maxWidth: 2), 2) + XCTAssertEqual(buffer.plainLines(), ["ab "]) + XCTAssertEqual(buffer.write("wxyz", x: 3, y: 0), 2) + XCTAssertEqual(buffer.plainLines(), ["ab wx"]) + } + + func testWriteOutOfRangeWritesNothing() { + var buffer = Buffer(width: 3, height: 1) + XCTAssertEqual(buffer.write("a", x: 3, y: 0), 0) + XCTAssertEqual(buffer.write("a", x: -1, y: 0), 0) + XCTAssertEqual(buffer.write("a", x: 0, y: 1), 0) + XCTAssertEqual(buffer.write("a", x: 0, y: -1), 0) + XCTAssertEqual(buffer.write("a", x: 0, y: 0, maxWidth: 0), 0) + XCTAssertEqual(buffer.plainLines(), [" "]) + } + + func testWideCharacterTakesTwoColumns() { + var buffer = Buffer(width: 4, height: 1) + XCTAssertEqual(buffer.write("界a", x: 0, y: 0), 3) + XCTAssertEqual(buffer[0, 0].symbol, "界") + XCTAssertEqual(buffer[1, 0].symbol, "") + XCTAssertEqual(buffer.plainLines(), ["界a "]) + } + + func testWideCharacterThatDoesNotFitIsNotDrawn() { + var buffer = Buffer(width: 3, height: 1) + XCTAssertEqual(buffer.write("ab界", x: 0, y: 0), 2) + XCTAssertEqual(buffer.plainLines(), ["ab "]) + XCTAssertEqual(buffer.write("界", x: 0, y: 0, maxWidth: 1), 0) + XCTAssertEqual(buffer.plainLines(), ["ab "]) + } + + func testOverwritingEitherHalfOfWideCharacterBlanksTheOther() { + var first = Buffer(width: 4, height: 1) + first.write("界", x: 0, y: 0) + first.write("x", x: 0, y: 0) + XCTAssertEqual(first.plainLines(), ["x "]) + XCTAssertEqual(first[1, 0], Cell(symbol: " ", style: .plain)) + + var second = Buffer(width: 4, height: 1) + second.write("界", x: 0, y: 0, style: TextStyle(bold: true)) + second.write("x", x: 1, y: 0) + XCTAssertEqual(second.plainLines(), [" x "]) + XCTAssertEqual(second[0, 0], Cell(symbol: " ", style: .plain)) + } + + func testOverwritingWideWithWideAcrossBoundary() { + var buffer = Buffer(width: 6, height: 1) + buffer.write("界界", x: 0, y: 0) + buffer.write("界", x: 1, y: 0) + XCTAssertEqual(buffer.plainLines(), [" 界 "]) + } + + func testWriteSanitizesControlCharacters() { + var buffer = Buffer(width: 8, height: 1) + XCTAssertEqual(buffer.write("a\u{1B}[2Jb", x: 0, y: 0), 6) + XCTAssertEqual(buffer.plainLines(), ["a�[2Jb "]) + XCTAssertFalse(buffer.lines(colors: true)[0].contains("\u{1B}[2J")) + } + + func testZeroWidthCharactersAreSkipped() { + var buffer = Buffer(width: 4, height: 1) + XCTAssertEqual(buffer.write("a\u{200B}b", x: 0, y: 0), 2) + XCTAssertEqual(buffer.plainLines(), ["ab "]) + } + + func testWriteSpansAppliesEachStyleAndReturnsTotal() { + var buffer = Buffer(width: 6, height: 1) + let bold = TextStyle(bold: true) + XCTAssertEqual(buffer.write([Span("ab", bold), Span("cd")], x: 1, y: 0, maxWidth: 4), 4) + XCTAssertEqual(buffer[1, 0].style, bold) + XCTAssertEqual(buffer[3, 0].style, .plain) + XCTAssertEqual(buffer.plainLines(), [" abcd "]) + XCTAssertEqual(buffer.write([Span("xy"), Span("zw")], x: 0, y: 0, maxWidth: 3), 3) + XCTAssertEqual(buffer.plainLines(), ["xyzcd "]) + } + + func testLinesWithoutColorsHaveNoEscapes() { + var buffer = Buffer(width: 4, height: 1) + buffer.write("ab", x: 0, y: 0, style: TextStyle(color: .red, bold: true)) + XCTAssertEqual(buffer.lines(colors: false), ["ab "]) + XCTAssertEqual(buffer.plainLines(), ["ab "]) + } + + func testLinesMergeEqualStylesIntoOneSequence() { + var buffer = Buffer(width: 4, height: 1) + buffer.write("ab", x: 0, y: 0, style: TextStyle(color: .cyan)) + XCTAssertEqual(buffer.lines(colors: true), ["\(esc)[0m\(esc)[36mab\(esc)[0m "]) + } + + func testLinesSwitchBetweenStyles() { + var buffer = Buffer(width: 3, height: 1) + buffer.write([Span("a", TextStyle(bold: true)), Span("b", TextStyle(dim: true)), Span("c")], x: 0, y: 0) + XCTAssertEqual(buffer.lines(colors: true), ["\(esc)[0m\(esc)[1ma\(esc)[0m\(esc)[2mb\(esc)[0mc"]) + } + + func testRowEndingStyledEndsWithReset() { + var buffer = Buffer(width: 2, height: 1) + buffer.write("ab", x: 0, y: 0, style: TextStyle(bold: true)) + XCTAssertEqual(buffer.lines(colors: true), ["\(esc)[0m\(esc)[1mab\(esc)[0m"]) + } + + func testStyleDoesNotCarryAcrossRows() { + var buffer = Buffer(width: 1, height: 2) + buffer.write("a", x: 0, y: 0, style: TextStyle(bold: true)) + buffer.write("b", x: 0, y: 1) + XCTAssertEqual(buffer.lines(colors: true), ["\(esc)[0m\(esc)[1ma\(esc)[0m", "b"]) + } + + func testRowsKeepExactWidthWithWideCharacters() { + var buffer = Buffer(width: 5, height: 2) + buffer.write("界界", x: 0, y: 0, style: TextStyle(color: .green)) + buffer.write("a界", x: 0, y: 1) + for line in buffer.lines(colors: true) + buffer.plainLines() { + XCTAssertEqual(Term.displayWidth(line), 5) + } + XCTAssertEqual(buffer.plainLines(), ["界界 ", "a界 "]) + } +} diff --git a/cli/Tests/TerminalUITests/GaugeTests.swift b/cli/Tests/TerminalUITests/GaugeTests.swift new file mode 100644 index 0000000..07abe70 --- /dev/null +++ b/cli/Tests/TerminalUITests/GaugeTests.swift @@ -0,0 +1,35 @@ +import XCTest +@testable import TerminalUI + +final class GaugeTests: XCTestCase { + private let dim = TextStyle(dim: true) + + func testFilledAndRestSpans() { + XCTAssertEqual(Gauge(fraction: 0.5).spans(width: 10), [Span("█████"), Span("░░░░░", dim)]) + } + + func testEmptyAndFullHaveSingleSpan() { + XCTAssertEqual(Gauge(fraction: 0).spans(width: 4), [Span("░░░░", dim)]) + XCTAssertEqual(Gauge(fraction: 1).spans(width: 4), [Span("████")]) + } + + func testFractionIsClamped() { + XCTAssertEqual(Gauge(fraction: 2).spans(width: 3), [Span("███")]) + XCTAssertEqual(Gauge(fraction: -1).spans(width: 3), [Span("░░░", dim)]) + } + + func testNonPositiveWidthHasNoSpans() { + XCTAssertEqual(Gauge(fraction: 0.5).spans(width: 0), []) + XCTAssertEqual(Gauge(fraction: 0.5).spans(width: -3), []) + } + + func testRoundingMatchesTermBar() { + for width in [1, 5, 12, 24] { + for step in 0...40 { + let fraction = Double(step) / 40 + let text = Gauge(fraction: fraction).spans(width: width).map(\.text).joined() + XCTAssertEqual(text, Term.bar(fraction: fraction, width: width)) + } + } + } +} diff --git a/cli/Tests/TerminalUITests/KeyHintsTests.swift b/cli/Tests/TerminalUITests/KeyHintsTests.swift new file mode 100644 index 0000000..a9a025f --- /dev/null +++ b/cli/Tests/TerminalUITests/KeyHintsTests.swift @@ -0,0 +1,74 @@ +import XCTest +@testable import TerminalUI + +final class KeyHintsTests: XCTestCase { + private let menu = KeyHints([ + KeyHint("↑↓", "move"), + KeyHint("PgUp/PgDn", "page"), + KeyHint("1-9", "open"), + KeyHint("Enter", "open"), + KeyHint("Esc/q", "cancel") + ]) + + private func text(_ rows: [[Span]]) -> [String] { + rows.map { $0.map(\.text).joined() } + } + + func testNoHintsNoRows() { + XCTAssertEqual(KeyHints([]).rows(width: 40), []) + } + + func testWrapsAtThirtySixColumns() { + XCTAssertEqual(text(menu.rows(width: 36)), [ + "↑↓ move PgUp/PgDn page 1-9 open", + "Enter open Esc/q cancel" + ]) + } + + func testStaysOnOneRowAtSeventySixColumns() { + XCTAssertEqual(text(menu.rows(width: 76)), ["↑↓ move PgUp/PgDn page 1-9 open Enter open Esc/q cancel"]) + } + + func testRowFitsExactly() { + XCTAssertEqual(text(KeyHints([KeyHint("a", "b"), KeyHint("c", "d")]).rows(width: 8)), ["a b c d"]) + XCTAssertEqual(text(KeyHints([KeyHint("a", "b"), KeyHint("c", "d")]).rows(width: 7)), ["a b", "c d"]) + } + + func testHintWiderThanWidthSitsAlone() { + let hints = KeyHints([KeyHint("Enter", "open"), KeyHint("q", "x"), KeyHint("w", "y")]) + XCTAssertEqual(text(hints.rows(width: 5)), ["Enter open", "q x", "w y"]) + } + + func testKeyIsPlainAndActionIsDim() { + let row = KeyHints([KeyHint("a", "b"), KeyHint("c", "d")]).rows(width: 20)[0] + XCTAssertEqual(row, [ + Span("a"), Span(" b", TextStyle(dim: true)), + Span(" "), + Span("c"), Span(" d", TextStyle(dim: true)) + ]) + } + + func testRenderWritesRowsIntoRect() { + var buffer = Buffer(width: 12, height: 5) + KeyHints([KeyHint("a", "b"), KeyHint("c", "d"), KeyHint("e", "f")]) + .render(in: Rect(x: 2, y: 1, width: 8, height: 2), buffer: &buffer) + XCTAssertEqual(buffer.plainLines(), [ + " ", + " a b c d ", + " e f ", + " ", + " " + ]) + XCTAssertEqual(buffer[2, 1].style, .plain) + XCTAssertEqual(buffer[3, 1].style, TextStyle(dim: true)) + } + + func testRenderDropsRowsBeyondRectHeightAndClipsWidth() { + var buffer = Buffer(width: 10, height: 4) + KeyHints([KeyHint("Enter", "open"), KeyHint("q", "x"), KeyHint("w", "y")]) + .render(in: Rect(x: 0, y: 0, width: 5, height: 2), buffer: &buffer) + XCTAssertEqual(buffer.plainLines()[0], "Enter ") + XCTAssertEqual(buffer.plainLines()[1], "q x ") + XCTAssertEqual(buffer.plainLines()[2], " ") + } +} diff --git a/cli/Tests/TerminalUITests/ScrollbarTests.swift b/cli/Tests/TerminalUITests/ScrollbarTests.swift new file mode 100644 index 0000000..7e3d633 --- /dev/null +++ b/cli/Tests/TerminalUITests/ScrollbarTests.swift @@ -0,0 +1,47 @@ +import XCTest +@testable import TerminalUI + +final class ScrollbarTests: XCTestCase { + func testCenteredOffsetCentersFocusAndClamps() { + XCTAssertEqual(Scrollbar.centeredOffset(total: 30, visible: 4, focus: 17), 15) + XCTAssertEqual(Scrollbar.centeredOffset(total: 30, visible: 4, focus: 0), 0) + XCTAssertEqual(Scrollbar.centeredOffset(total: 30, visible: 4, focus: 29), 26) + XCTAssertEqual(Scrollbar.centeredOffset(total: 3, visible: 4, focus: 2), 0) + } + + func testNoThumbWhenEverythingFitsOrTrackIsEmpty() { + XCTAssertNil(Scrollbar(total: 5, visible: 5, offset: 0).thumb(trackHeight: 5)) + XCTAssertNil(Scrollbar(total: 3, visible: 5, offset: 0).thumb(trackHeight: 5)) + XCTAssertNil(Scrollbar(total: 10, visible: 5, offset: 0).thumb(trackHeight: 0)) + } + + func testThumbAtTopMiddleAndBottom() { + XCTAssertEqual(Scrollbar(total: 100, visible: 10, offset: 0).thumb(trackHeight: 10), 0..<1) + XCTAssertEqual(Scrollbar(total: 100, visible: 10, offset: 45).thumb(trackHeight: 10), 5..<6) + XCTAssertEqual(Scrollbar(total: 100, visible: 10, offset: 90).thumb(trackHeight: 10), 9..<10) + XCTAssertEqual(Scrollbar(total: 20, visible: 10, offset: 5).thumb(trackHeight: 8), 2..<6) + XCTAssertEqual(Scrollbar(total: 20, visible: 10, offset: 10).thumb(trackHeight: 8), 4..<8) + } + + func testOffsetIsClamped() { + XCTAssertEqual(Scrollbar(total: 20, visible: 10, offset: 99).thumb(trackHeight: 8), 4..<8) + XCTAssertEqual(Scrollbar(total: 20, visible: 10, offset: -4).thumb(trackHeight: 8), 0..<4) + } + + func testThumbIsAtLeastOneRow() { + XCTAssertEqual(Scrollbar(total: 1000, visible: 1, offset: 0).thumb(trackHeight: 5), 0..<1) + } + + func testRenderDrawsThumbOverTrackRows() { + var buffer = Buffer(width: 3, height: 8) + Scrollbar(total: 8, visible: 4, offset: 0).render(column: 2, rows: 2..<6, buffer: &buffer, style: TextStyle(dim: true)) + XCTAssertEqual(buffer.plainLines().map { $0.suffix(1) }, [" ", " ", "┃", "┃", " ", " ", " ", " "]) + XCTAssertEqual(buffer[2, 2].style, TextStyle(dim: true)) + } + + func testRenderDrawsNothingWhenEverythingFits() { + var buffer = Buffer(width: 3, height: 4) + Scrollbar(total: 2, visible: 4, offset: 0).render(column: 2, rows: 0..<4, buffer: &buffer) + XCTAssertEqual(buffer, Buffer(width: 3, height: 4)) + } +} diff --git a/cli/Tests/TerminalUITests/StyleTests.swift b/cli/Tests/TerminalUITests/StyleTests.swift new file mode 100644 index 0000000..9ea7220 --- /dev/null +++ b/cli/Tests/TerminalUITests/StyleTests.swift @@ -0,0 +1,28 @@ +import XCTest +@testable import TerminalUI + +final class StyleTests: XCTestCase { + func testPlainStyleHasNoParameters() { + XCTAssertEqual(TextStyle.plain.sgrParameters, "") + XCTAssertEqual(TextStyle(), .plain) + } + + func testParametersFollowFixedOrder() { + XCTAssertEqual(TextStyle(color: .cyan, bold: true, dim: true, inverse: true).sgrParameters, "1;2;7;36") + XCTAssertEqual(TextStyle(color: .red).sgrParameters, "31") + XCTAssertEqual(TextStyle(dim: true).sgrParameters, "2") + XCTAssertEqual(TextStyle(inverse: true).sgrParameters, "7") + } + + func testColorCodes() { + let codes: [(TerminalColor, String)] = [(.red, "31"), (.green, "32"), (.yellow, "33"), (.cyan, "36")] + for (color, code) in codes { + XCTAssertEqual(TextStyle(color: color).sgrParameters, code) + } + } + + func testSpanDefaultsToPlain() { + XCTAssertEqual(Span("a").style, .plain) + XCTAssertEqual(Span("a", TextStyle(bold: true)).style.bold, true) + } +} diff --git a/cli/Tests/TerminalUITests/TermTests.swift b/cli/Tests/TerminalUITests/TermTests.swift new file mode 100644 index 0000000..a1c3831 --- /dev/null +++ b/cli/Tests/TerminalUITests/TermTests.swift @@ -0,0 +1,30 @@ +import XCTest +import TerminalUI + +final class TermTests: XCTestCase { + func testANSIAndUnicodeDisplayWidth() { + XCTAssertEqual(Term.displayWidth("\u{1B}[31mclean\u{1B}[0m"), 5) + XCTAssertEqual(Term.displayWidth("界"), 2) + XCTAssertEqual(Term.displayWidth("a\u{301}"), 1) + } + + func testTerminalControlCharactersAreSanitized() { + XCTAssertEqual(Term.sanitize("safe\u{1B}[2Jname\n"), "safe�[2Jname�") + XCTAssertEqual(Term.sanitize("one\ttwo"), "one two") + } + + func testMiddleTruncationRespectsVisibleWidth() { + let value = Term.truncate("/Users/example/Library/Caches/tool", to: 18, middle: true) + XCTAssertLessThanOrEqual(Term.displayWidth(value), 18) + XCTAssertTrue(value.contains("…")) + XCTAssertTrue(value.hasPrefix("/Users/e")) + XCTAssertTrue(value.hasSuffix("ches/tool")) + } + + func testTermBarOutputIsUnchanged() { + XCTAssertEqual(Term.bar(fraction: 0.25, width: 8), "██░░░░░░") + XCTAssertEqual(Term.bar(fraction: 3, width: 3), "███") + XCTAssertEqual(Term.bar(fraction: 0.5, width: -2), "") + XCTAssertEqual(Term.bar(fraction: 0.5).count, 24) + } +} diff --git a/cli/Tests/TerminalUITests/TerminalSessionTests.swift b/cli/Tests/TerminalUITests/TerminalSessionTests.swift new file mode 100644 index 0000000..527ba3c --- /dev/null +++ b/cli/Tests/TerminalUITests/TerminalSessionTests.swift @@ -0,0 +1,13 @@ +import XCTest +@testable import TerminalUI + +final class TerminalSessionTests: XCTestCase { + private let esc = "\u{1B}" + + func testFrameClearsBelowOnlyWhenFrameIsShorterThanScreen() { + XCTAssertTrue(TerminalSession.frame(lines: ["a", "b"], height: 3).hasSuffix("\(esc)[J")) + XCTAssertFalse(TerminalSession.frame(lines: ["a", "b", "c"], height: 3).hasSuffix("\(esc)[J")) + XCTAssertTrue(TerminalSession.frame(lines: ["a", "b", "c", "d"], height: 3).contains("c")) + XCTAssertFalse(TerminalSession.frame(lines: ["a", "b", "c", "d"], height: 3).contains("d")) + } +} diff --git a/cli/Tests/TerminalUITests/WindowTests.swift b/cli/Tests/TerminalUITests/WindowTests.swift new file mode 100644 index 0000000..e07ec91 --- /dev/null +++ b/cli/Tests/TerminalUITests/WindowTests.swift @@ -0,0 +1,131 @@ +import XCTest +@testable import TerminalUI + +final class WindowTests: XCTestCase { + private func render(_ window: Window, width: Int, height: Int = 3) -> (lines: [String], buffer: Buffer, content: Rect) { + var buffer = Buffer(width: width, height: height) + let content = window.render(in: buffer.area, buffer: &buffer) + return (buffer.plainLines(), buffer, content) + } + + func testFrameWithoutInfo() { + let result = render(Window(title: "Title"), width: 16) + XCTAssertEqual(result.lines, [ + "╭─ Title ──────╮", + "│ │", + "╰──────────────╯" + ]) + } + + func testFrameWithInfo() { + let result = render(Window(title: "Title", info: "info"), width: 20) + XCTAssertEqual(result.lines[0], "╭─ Title ─── info ─╮") + } + + func testSidesAndBottomBorder() { + let result = render(Window(title: "T"), width: 7) + XCTAssertEqual(result.lines, ["╭─ T ─╮", "│ │", "╰─────╯"]) + } + + func testLongTitleIsTruncatedToSpaceLeftOfInfo() { + let result = render(Window(title: "A very long title indeed", info: "info"), width: 20) + XCTAssertEqual(result.lines[0], "╭─ A very… ─ info ─╮") + } + + func testInfoStaysWholeWhileTitleHasFourColumns() { + let result = render(Window(title: "Long title", info: "info"), width: 17) + XCTAssertEqual(result.lines[0], "╭─ Lon… ─ info ─╮") + } + + func testInfoIsDroppedWhenTitleWouldGetLessThanFourColumns() { + let result = render(Window(title: "Long title here", info: "info"), width: 16) + XCTAssertEqual(result.lines[0], "╭─ Long titl… ─╮") + } + + func testLongTitleWithoutInfoKeepsDashBeforeCorner() { + let result = render(Window(title: "PureMac cleaner"), width: 12) + XCTAssertEqual(result.lines[0], "╭─ PureM… ─╮") + } + + func testTopBorderAlwaysEndsWithDashBeforeCorner() { + XCTAssertEqual(render(Window(title: "Title"), width: 10).lines[0], "╭─ Tit… ─╮") + XCTAssertEqual(render(Window(title: "Title"), width: 11).lines[0], "╭─ Title ─╮") + } + + func testStylesPerPart() { + let window = Window(title: "Title", info: "info") + let buffer = render(window, width: 20).buffer + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + XCTAssertEqual(buffer[0, 1].style, TextStyle(dim: true)) + XCTAssertEqual(buffer[3, 0].style, TextStyle(color: .cyan, bold: true)) + XCTAssertEqual(buffer[13, 0].style, TextStyle(bold: true)) + XCTAssertEqual(buffer[19, 2].style, TextStyle(dim: true)) + XCTAssertEqual(buffer[2, 0].style, .plain) + } + + func testCustomStyles() { + let yellow = TextStyle(color: .yellow) + let window = Window(title: "T", borderStyle: yellow, titleStyle: yellow) + let buffer = render(window, width: 7).buffer + XCTAssertEqual(buffer[0, 1].style, yellow) + XCTAssertEqual(buffer[3, 0].style, yellow) + } + + func testContentRectHasOneColumnOfPadding() { + var buffer = Buffer(width: 30, height: 10) + let content = Window(title: "T").render(in: Rect(x: 2, y: 1, width: 20, height: 6), buffer: &buffer) + XCTAssertEqual(content, Rect(x: 4, y: 2, width: 16, height: 4)) + } + + func testContentRectMatchesRenderWithoutDrawing() { + var buffer = Buffer(width: 30, height: 10) + let rect = Rect(x: 2, y: 1, width: 20, height: 6) + let window = Window(title: "T") + XCTAssertEqual(window.contentRect(in: rect), window.render(in: rect, buffer: &buffer)) + XCTAssertEqual(window.contentRect(in: Rect(x: 0, y: 0, width: 2, height: 2)), Rect(x: 2, y: 1, width: 0, height: 0)) + } + + func testContentRectOfTinyRectIsEmptyAtOrigin() { + let window = Window(title: "T") + XCTAssertEqual(window.contentRect(in: Rect(x: 3, y: 4, width: 1, height: 9)), Rect(x: 3, y: 4, width: 0, height: 0)) + XCTAssertEqual(window.contentRect(in: Rect(x: 3, y: 4, width: 9, height: 1)), Rect(x: 3, y: 4, width: 0, height: 0)) + } + + func testFrameIsDrawnAtRectOrigin() { + var buffer = Buffer(width: 11, height: 5) + Window(title: "T").render(in: Rect(x: 2, y: 1, width: 7, height: 3), buffer: &buffer) + XCTAssertEqual(buffer.plainLines(), [ + " ", + " ╭─ T ─╮ ", + " │ │ ", + " ╰─────╯ ", + " " + ]) + } + + func testTinyRectDrawsNothing() { + var buffer = Buffer(width: 6, height: 4) + let blank = buffer + let window = Window(title: "T") + XCTAssertEqual(window.render(in: Rect(x: 1, y: 1, width: 1, height: 3), buffer: &buffer), Rect(x: 1, y: 1, width: 0, height: 0)) + XCTAssertEqual(window.render(in: Rect(x: 0, y: 0, width: 6, height: 1), buffer: &buffer), Rect(x: 0, y: 0, width: 0, height: 0)) + XCTAssertEqual(buffer, blank) + } + + func testSmallestFrameHasNonNegativeContent() { + var buffer = Buffer(width: 2, height: 2) + let content = Window(title: "T").render(in: buffer.area, buffer: &buffer) + XCTAssertEqual(buffer.plainLines(), ["╭╮", "╰╯"]) + XCTAssertEqual(content, Rect(x: 2, y: 1, width: 0, height: 0)) + } + + func testDividerSpansWindowWidth() { + var buffer = Buffer(width: 10, height: 5) + let window = Window(title: "T") + let rect = Rect(x: 2, y: 0, width: 6, height: 5) + window.render(in: rect, buffer: &buffer) + window.renderDivider(atRow: 2, in: rect, buffer: &buffer) + XCTAssertEqual(buffer.plainLines()[2], " ├────┤ ") + XCTAssertEqual(buffer[2, 2].style, TextStyle(dim: true)) + } +} diff --git a/cli/Tests/puremacTests/AnalyzeTests.swift b/cli/Tests/puremacTests/AnalyzeTests.swift index 349feb3..e703d7c 100644 --- a/cli/Tests/puremacTests/AnalyzeTests.swift +++ b/cli/Tests/puremacTests/AnalyzeTests.swift @@ -1,6 +1,7 @@ import Darwin import XCTest @testable import puremac +import TerminalUI final class AnalyzeTests: XCTestCase { private var root: URL! @@ -84,35 +85,223 @@ final class AnalyzeTests: XCTestCase { XCTAssertFalse(snapshot.errors.isEmpty) } - func testViewportKeepsSelectionVisibleAndWithinHeight() { - let children = (0..<20).map { - Analyze.Child( - path: "/tmp/item-\($0)", - size: Int64(20 - $0) * 1_024, - isDir: true, - isPackage: false, - inaccessibleCount: 0, - skippedCount: 0 - ) - } - let snapshot = Analyze.FolderSnapshot( - path: "/tmp", + private func child(_ path: String, size: Int64, isDir: Bool = true, isPackage: Bool = false, skipped: Int = 0) -> Analyze.Child { + Analyze.Child(path: path, size: size, isDir: isDir, isPackage: isPackage, inaccessibleCount: 0, skippedCount: skipped) + } + + private func snapshot( + path: String = "/tmp", + children: [Analyze.Child], + inaccessible: Int = 0, + skipped: Int = 0, + errors: [String] = [] + ) -> Analyze.FolderSnapshot { + Analyze.FolderSnapshot( + path: path, children: children, total: children.reduce(Int64(0)) { $0 + $1.size }, - inaccessibleCount: 0, - skippedCount: 0, - errors: [] + inaccessibleCount: inaccessible, + skippedCount: skipped, + errors: errors ) + } + + private func manyChildren(_ count: Int) -> [Analyze.Child] { + (0.. [(title: String, detail: String)] { + (1...count).map { (title: "Tool \($0)", detail: "Description \($0)") } + } + + private func renderMenu( + options: [(title: String, detail: String)], + selection: Int, + width: Int, + height: Int + ) -> Buffer { + TerminalMenu.render( + title: "PureMac", + subtitle: "Choose a task", + options: options, + selection: selection, + width: width, + height: height + ) + } + + private func renderReview(_ model: InteractiveReviewModel, width: Int, height: Int) -> Buffer { + InteractiveReview.render(model: model, title: "Review removable files", width: width, height: height) + } + + private func manyItemsCategories(_ count: Int) -> [CategoryScan] { + [ + CategoryScan( + id: "many", + title: "Many", + groups: [ + ToolGroup( + tool: "Items", + items: (0.. [CategoryScan] { + [ + CategoryScan( + id: "dev", + title: "Developer", + groups: [ + ToolGroup( + tool: "Build caches", + items: [ + ScanItem(path: "/tmp/first", sizeBytes: 1_000, modified: nil, selected: true), + ScanItem(path: "/tmp/second", sizeBytes: 2_000, modified: nil, selected: true) + ] + ), + ToolGroup( + tool: "Package caches", + items: [ + ScanItem(path: "/tmp/third", sizeBytes: 3_000, modified: nil, selected: false) + ] + ) + ] + ) + ] + } +} diff --git a/cli/Tests/puremacTests/TerminalUITests.swift b/cli/Tests/puremacTests/TerminalUITests.swift deleted file mode 100644 index 1e9fe6b..0000000 --- a/cli/Tests/puremacTests/TerminalUITests.swift +++ /dev/null @@ -1,201 +0,0 @@ -import XCTest -@testable import puremac - -final class TerminalUITests: XCTestCase { - func testANSIAndUnicodeDisplayWidth() { - XCTAssertEqual(Term.displayWidth("\u{1B}[31mclean\u{1B}[0m"), 5) - XCTAssertEqual(Term.displayWidth("界"), 2) - XCTAssertEqual(Term.displayWidth("a\u{301}"), 1) - } - - func testTerminalControlCharactersAreSanitized() { - XCTAssertEqual(Term.sanitize("safe\u{1B}[2Jname\n"), "safe�[2Jname�") - XCTAssertEqual(Term.sanitize("one\ttwo"), "one two") - } - - func testMiddleTruncationRespectsVisibleWidth() { - let value = Term.truncate("/Users/example/Library/Caches/tool", to: 18, middle: true) - XCTAssertLessThanOrEqual(Term.displayWidth(value), 18) - XCTAssertTrue(value.contains("…")) - XCTAssertTrue(value.hasPrefix("/Users/e")) - XCTAssertTrue(value.hasSuffix("ches/tool")) - } - - func testReviewStartsWithNothingSelected() { - let model = InteractiveReviewModel(categories: fixtureCategories()) - XCTAssertEqual(model.selectedCount, 0) - XCTAssertEqual(model.selectedBytes, 0) - XCTAssertEqual(model.matchingAddresses.count, 3) - } - - func testReviewSelectionAndSearchPreserveExactItems() { - var model = InteractiveReviewModel(categories: fixtureCategories()) - model.toggleFocused() - model.move(1) - model.toggleFocused() - XCTAssertEqual(model.selectedCount, 2) - XCTAssertEqual(model.selectedBytes, 3_000) - - model.updateQuery("second") - XCTAssertEqual(model.matchingAddresses.count, 1) - XCTAssertEqual(model.item(at: model.matchingAddresses[0]).path, "/tmp/second") - - model.selectNone() - model.selectAllMatching() - XCTAssertEqual(model.selectedCount, 1) - XCTAssertEqual(model.selectedResult()[0].selectedItems.map(\.path), ["/tmp/second"]) - } - - func testReviewRequiresSelectionBeforeFinalReview() { - var model = InteractiveReviewModel(categories: fixtureCategories()) - XCTAssertFalse(model.beginReview()) - XCTAssertFalse(model.isReviewing) - XCTAssertFalse(model.status.isEmpty) - - model.toggleFocused() - XCTAssertTrue(model.beginReview()) - XCTAssertTrue(model.isReviewing) - } - - func testReviewRenderIsBoundedAndKeepsControlsVisible() { - var model = InteractiveReviewModel(categories: fixtureCategories()) - model.selectAllMatching() - for (width, height) in [(40, 12), (58, 14), (80, 24)] { - let lines = InteractiveReview.render( - model: model, - title: "Review removable files", - width: width, - height: height - ) - - XCTAssertEqual(lines.count, height) - XCTAssertTrue(lines.contains { $0.contains("Space toggle") }) - XCTAssertTrue(lines.contains { $0.contains("Enter review") }) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= width }) - } - } - - func testReviewHeaderFitsFortyColumnsWithDifferentCountsAndSizes() { - let categories = [ - CategoryScan( - id: "cache", - title: "Caches", - groups: [ - ToolGroup( - tool: "Applications", - items: [ - ScanItem(path: "/tmp/one", sizeBytes: 138_300, modified: nil), - ScanItem(path: "/tmp/two", sizeBytes: 1_000, modified: nil) - ] - ) - ] - ) - ] - let model = InteractiveReviewModel(categories: categories) - let lines = InteractiveReview.render( - model: model, - title: "Review removable files", - width: 40, - height: 12 - ) - - XCTAssertEqual(Term.displayWidth(lines[2]), 40) - XCTAssertTrue(lines[2].contains("2 shown")) - XCTAssertTrue(lines[2].contains("0 selected")) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= 40 }) - } - - func testFinalReviewControlsFitAtMinimumSupportedWidth() { - var model = InteractiveReviewModel(categories: fixtureCategories()) - model.selectAllMatching() - XCTAssertTrue(model.beginReview()) - let lines = InteractiveReview.render( - model: model, - title: "Review removable files", - width: 40, - height: 12 - ) - XCTAssertEqual(lines.count, 12) - XCTAssertTrue(lines.contains { $0.contains("Enter confirm") }) - XCTAssertTrue(lines.contains { $0.contains("q cancel") }) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= 40 }) - } - - func testCompactReviewDoesNotLieAboutTerminalDimensions() { - let model = InteractiveReviewModel(categories: fixtureCategories()) - let lines = InteractiveReview.render( - model: model, - title: "Review", - width: 18, - height: 4 - ) - - XCTAssertEqual(lines.count, 4) - XCTAssertTrue(lines.contains { $0.contains("too small") }) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= 18 }) - } - - func testFocusedPathWindowCanRevealEntirePath() { - let path = "/Users/example/Library/Caches/application/data" - let first = InteractiveReview.horizontalWindow(path, offset: 0, width: 20) - let last = InteractiveReview.horizontalWindow(path, offset: 30, width: 20) - - XCTAssertTrue(first.hasSuffix("›")) - XCTAssertTrue(last.hasPrefix("‹")) - XCTAssertLessThanOrEqual(Term.displayWidth(first), 20) - XCTAssertLessThanOrEqual(Term.displayWidth(last), 20) - } - - func testMenuSelectionClampsAndRenderPaginates() { - var model = TerminalMenuModel(optionCount: 8) - model.move(99) - XCTAssertEqual(model.selection, 7) - model.move(-99) - XCTAssertEqual(model.selection, 0) - XCTAssertEqual(model.select(number: 7), 6) - XCTAssertEqual(model.selection, 6) - XCTAssertNil(model.select(number: 9)) - XCTAssertNil(model.select(number: 0)) - - let options = (1...8).map { (title: "Tool \($0)", detail: "Description \($0)") } - for (width, height) in [(40, 12), (80, 24)] { - let lines = TerminalMenu.render( - title: "PureMac", - subtitle: "Choose a task", - options: options, - selection: 6, - width: width, - height: height - ) - XCTAssertEqual(lines.count, height) - XCTAssertTrue(lines.contains { $0.contains("Tool 7") }) - XCTAssertTrue(lines.contains { $0.contains("Enter open") }) - XCTAssertTrue(lines.contains { $0.contains("1-9 open") }) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= width }) - } - } - - private func fixtureCategories() -> [CategoryScan] { - [ - CategoryScan( - id: "dev", - title: "Developer", - groups: [ - ToolGroup( - tool: "Build caches", - items: [ - ScanItem(path: "/tmp/first", sizeBytes: 1_000, modified: nil, selected: true), - ScanItem(path: "/tmp/second", sizeBytes: 2_000, modified: nil, selected: true) - ] - ), - ToolGroup( - tool: "Package caches", - items: [ - ScanItem(path: "/tmp/third", sizeBytes: 3_000, modified: nil, selected: false) - ] - ) - ] - ) - ] - } -} From 1a71869df81f4cfbdb70def278efcb55d1e54b1f Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 11:14:06 +0000 Subject: [PATCH 02/21] feat(cli): color sizes by magnitude in review and storage screens --- cli/Sources/TerminalUI/Gauge.swift | 8 +++--- cli/Sources/puremac/Commands/Analyze.swift | 9 ++++--- .../puremac/Core/InteractiveReview.swift | 5 +++- cli/Sources/puremac/Core/SizeLevel.swift | 25 +++++++++++++++++++ cli/Tests/TerminalUITests/GaugeTests.swift | 7 ++++++ cli/Tests/puremacTests/AnalyzeTests.swift | 19 ++++++++++++++ .../InteractiveScreensTests.swift | 21 ++++++++++++++++ cli/Tests/puremacTests/SizeLevelTests.swift | 18 +++++++++++++ 8 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 cli/Sources/puremac/Core/SizeLevel.swift create mode 100644 cli/Tests/puremacTests/SizeLevelTests.swift diff --git a/cli/Sources/TerminalUI/Gauge.swift b/cli/Sources/TerminalUI/Gauge.swift index 9cd9097..9100a4d 100644 --- a/cli/Sources/TerminalUI/Gauge.swift +++ b/cli/Sources/TerminalUI/Gauge.swift @@ -5,11 +5,11 @@ public struct Gauge { self.fraction = fraction } - public func spans(width: Int) -> [Span] { - let filled = Term.filledCount(fraction: fraction, width: width) + public func spans(width: Int, filled filledStyle: TextStyle = .plain) -> [Span] { + let filledCount = Term.filledCount(fraction: fraction, width: width) return [ - Span(String(repeating: "█", count: filled)), - Span(String(repeating: "░", count: max(0, width) - filled), TextStyle(dim: true)) + Span(String(repeating: "█", count: filledCount), filledStyle), + Span(String(repeating: "░", count: max(0, width) - filledCount), TextStyle(dim: true)) ].filter { !$0.text.isEmpty } } } diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index 2980b42..1021549 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -461,12 +461,15 @@ struct Analyze: ParsableCommand { let nameWidth = max(1, nameColumn - partial.count) let name = Term.truncate(URL(fileURLWithPath: child.path).lastPathComponent + suffix, to: nameWidth, middle: true) let rowStyle = TextStyle(inverse: focused) - let gauge = Gauge(fraction: fraction).spans(width: barWidth).map { - Span($0.text, TextStyle(dim: $0.style.dim, inverse: focused)) + let sizeStyle = SizeLevel.style(bytes: child.size, focused: focused) + let gauge = Gauge(fraction: fraction).spans(width: barWidth, filled: sizeStyle).map { + Span($0.text, TextStyle(color: $0.style.color, dim: $0.style.dim, inverse: focused)) } buffer.write( [FocusPointer.span(focused: focused), - Span(" " + Render.sizeCol(child.size) + " ", rowStyle)] + Span(" ", rowStyle), + Span(Render.sizeCol(child.size), sizeStyle), + Span(" ", rowStyle)] + gauge + [Span(" " + Term.pad(name + partial, to: nameColumn), rowStyle)], x: rect.x, diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index b4b3d3b..4837986 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -414,6 +414,7 @@ enum InteractiveReview { let item = model.item(at: address) let focused = address == focusedAddress let rowStyle = TextStyle(inverse: focused) + let sizeStyle = SizeLevel.style(bytes: item.sizeBytes, focused: focused) let pathWidth = max(1, rect.width - itemPrefixWidth) let path = Term.truncate(Render.shorten(item.path), to: pathWidth, middle: true) buffer.write( @@ -421,7 +422,9 @@ enum InteractiveReview { FocusPointer.span(focused: focused), Span(" ", rowStyle), Span(item.selected ? "●" : "○", TextStyle(color: item.selected ? .cyan : nil, dim: !item.selected, inverse: focused)), - Span(" " + Render.sizeCol(item.sizeBytes) + " " + Term.pad(path, to: pathWidth), rowStyle) + Span(" ", rowStyle), + Span(Render.sizeCol(item.sizeBytes), sizeStyle), + Span(" " + Term.pad(path, to: pathWidth), rowStyle) ], x: rect.x, y: rect.y, diff --git a/cli/Sources/puremac/Core/SizeLevel.swift b/cli/Sources/puremac/Core/SizeLevel.swift new file mode 100644 index 0000000..eadc1ab --- /dev/null +++ b/cli/Sources/puremac/Core/SizeLevel.swift @@ -0,0 +1,25 @@ +import TerminalUI + +enum SizeLevel { + case small, medium, large + + init(bytes: Int64) { + switch bytes { + case ..<100_000_000: self = .small + case ..<1_000_000_000: self = .medium + default: self = .large + } + } + + var color: TerminalColor { + switch self { + case .small: return .green + case .medium: return .yellow + case .large: return .red + } + } + + static func style(bytes: Int64, focused: Bool) -> TextStyle { + focused ? TextStyle(inverse: true) : TextStyle(color: SizeLevel(bytes: bytes).color) + } +} diff --git a/cli/Tests/TerminalUITests/GaugeTests.swift b/cli/Tests/TerminalUITests/GaugeTests.swift index 07abe70..0a2d2af 100644 --- a/cli/Tests/TerminalUITests/GaugeTests.swift +++ b/cli/Tests/TerminalUITests/GaugeTests.swift @@ -8,6 +8,13 @@ final class GaugeTests: XCTestCase { XCTAssertEqual(Gauge(fraction: 0.5).spans(width: 10), [Span("█████"), Span("░░░░░", dim)]) } + func testFilledPartTakesGivenStyleAndRestStaysDim() { + let green = TextStyle(color: .green) + XCTAssertEqual(Gauge(fraction: 0.5).spans(width: 10, filled: green), [Span("█████", green), Span("░░░░░", dim)]) + XCTAssertEqual(Gauge(fraction: 1).spans(width: 4, filled: green), [Span("████", green)]) + XCTAssertEqual(Gauge(fraction: 0).spans(width: 4, filled: green), [Span("░░░░", dim)]) + } + func testEmptyAndFullHaveSingleSpan() { XCTAssertEqual(Gauge(fraction: 0).spans(width: 4), [Span("░░░░", dim)]) XCTAssertEqual(Gauge(fraction: 1).spans(width: 4), [Span("████")]) diff --git a/cli/Tests/puremacTests/AnalyzeTests.swift b/cli/Tests/puremacTests/AnalyzeTests.swift index e703d7c..b5a4f83 100644 --- a/cli/Tests/puremacTests/AnalyzeTests.swift +++ b/cli/Tests/puremacTests/AnalyzeTests.swift @@ -194,6 +194,25 @@ final class AnalyzeTests: XCTestCase { XCTAssertTrue(buffer[column(empty), 3].style.dim) } + func testSizeAndGaugeFillAreColoredByMagnitudeExceptOnFocusedRow() { + let snapshot = snapshot(children: [ + child("/tmp/big", size: 2_000_000_000), + child("/tmp/mid", size: 150_000_000), + child("/tmp/small", size: 99_000_000), + ]) + let buffer = Analyze.renderBrowser(level: Analyze.BrowserLevel(snapshot: snapshot, selected: 0), width: 120, height: 14) + let gaugeColumn = { (row: Int) in + Term.displayWidth(String(buffer.plainLines()[row].prefix { $0 != "█" && $0 != "░" })) + } + + XCTAssertEqual(buffer[7, 3].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[gaugeColumn(3), 3].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[7, 4].style, TextStyle(color: .yellow)) + XCTAssertEqual(buffer[gaugeColumn(4), 4].style, TextStyle(color: .yellow)) + XCTAssertEqual(buffer[7, 5].style, TextStyle(color: .green)) + XCTAssertEqual(buffer[gaugeColumn(5), 5].style, TextStyle(color: .green)) + } + func testScrollbarOnlyOverListRowsAndOnlyWhenRowsOverflow() { let overflowing = Analyze.renderBrowser( level: Analyze.BrowserLevel(snapshot: snapshot(children: manyChildren(30))), width: 60, height: 14 diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index fda579f..058405c 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -152,6 +152,27 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(buffer[16, 5].style, .plain) } + func testReviewItemSizeIsColoredByMagnitudeExceptOnFocusedRow() { + let sizes: [Int64] = [5, 150_000_000, 2_000_000_000] + let items = sizes.enumerated().map { ScanItem(path: "/tmp/\($0.offset)", sizeBytes: $0.element, modified: nil, selected: false) } + var model = InteractiveReviewModel(categories: [ + CategoryScan(id: "c", title: "C", groups: [ToolGroup(tool: "T", items: items)]) + ]) + model.selectAllMatching() + model.move(2) + let buffer = renderReview(model, width: 60, height: 24) + XCTAssertEqual(buffer[7, 4].style, TextStyle(color: .green)) + XCTAssertEqual(buffer[7, 5].style, TextStyle(color: .yellow)) + XCTAssertEqual(buffer[7, 6].style, TextStyle(inverse: true)) + + XCTAssertTrue(model.beginReview()) + model.move(2) + let review = renderReview(model, width: 60, height: 24) + XCTAssertEqual(review[7, 4].style, TextStyle(color: .green)) + XCTAssertEqual(review[7, 5].style, TextStyle(color: .yellow)) + XCTAssertEqual(review[7, 6].style, TextStyle(inverse: true)) + } + func testReviewFocusedPathLineSitsBelowDividerAndHintsFollow() { let lines = renderReview(InteractiveReviewModel(categories: fixtureCategories()), width: 80, height: 24).plainLines() let divider = lines.firstIndex { $0.hasPrefix("├") }! diff --git a/cli/Tests/puremacTests/SizeLevelTests.swift b/cli/Tests/puremacTests/SizeLevelTests.swift new file mode 100644 index 0000000..ddcb698 --- /dev/null +++ b/cli/Tests/puremacTests/SizeLevelTests.swift @@ -0,0 +1,18 @@ +import XCTest +@testable import puremac +import TerminalUI + +final class SizeLevelTests: XCTestCase { + func testThresholdsUseDecimalUnits() { + XCTAssertEqual(SizeLevel(bytes: 0).color, .green) + XCTAssertEqual(SizeLevel(bytes: 99_999_999).color, .green) + XCTAssertEqual(SizeLevel(bytes: 100_000_000).color, .yellow) + XCTAssertEqual(SizeLevel(bytes: 999_999_999).color, .yellow) + XCTAssertEqual(SizeLevel(bytes: 1_000_000_000).color, .red) + } + + func testStyleIsColoredWhenUnfocusedAndInverseWhenFocused() { + XCTAssertEqual(SizeLevel.style(bytes: 150_000_000, focused: false), TextStyle(color: .yellow)) + XCTAssertEqual(SizeLevel.style(bytes: 150_000_000, focused: true), TextStyle(inverse: true)) + } +} From 1ac5d2eeee504e61cf23d724c776e932406ea91a Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 12:05:39 +0000 Subject: [PATCH 03/21] feat(cli): keep the cleanup flow inside the UI with confirmation and result dialogs --- cli/README.md | 6 +- cli/Sources/TerminalUI/Buffer.swift | 17 ++ cli/Sources/TerminalUI/Dialog.swift | 127 +++++++++ cli/Sources/TerminalUI/Term.swift | 65 +++++ cli/Sources/TerminalUI/TerminalSession.swift | 26 +- cli/Sources/puremac/Commands/Analyze.swift | 49 +--- cli/Sources/puremac/Commands/Clean.swift | 36 ++- cli/Sources/puremac/Commands/Purge.swift | 29 +- .../puremac/Core/CategoryScanner.swift | 24 +- cli/Sources/puremac/Core/CleanupFlow.swift | 154 +++++++++++ .../puremac/Core/InteractiveReview.swift | 143 ++++++++-- cli/Sources/puremac/Core/Render.swift | 30 +- cli/Sources/puremac/Core/StatusScreen.swift | 47 ++++ cli/Sources/puremac/PureMac.swift | 5 + cli/Tests/TerminalUITests/BufferTests.swift | 41 +++ cli/Tests/TerminalUITests/DialogTests.swift | 210 ++++++++++++++ cli/Tests/TerminalUITests/TermTests.swift | 28 +- .../TerminalSessionTests.swift | 12 + cli/Tests/puremacTests/AnalyzeTests.swift | 9 - cli/Tests/puremacTests/CaptureSupport.swift | 40 +++ cli/Tests/puremacTests/CleanupFlowTests.swift | 220 +++++++++++++++ .../InteractiveScreensTests.swift | 259 +++++++++++++++++- .../puremacTests/ScanProgressTests.swift | 23 ++ .../puremacTests/StatusScreenTests.swift | 67 +++++ 24 files changed, 1554 insertions(+), 113 deletions(-) create mode 100644 cli/Sources/TerminalUI/Dialog.swift create mode 100644 cli/Sources/puremac/Core/CleanupFlow.swift create mode 100644 cli/Sources/puremac/Core/StatusScreen.swift create mode 100644 cli/Tests/TerminalUITests/DialogTests.swift create mode 100644 cli/Tests/puremacTests/CaptureSupport.swift create mode 100644 cli/Tests/puremacTests/CleanupFlowTests.swift create mode 100644 cli/Tests/puremacTests/ScanProgressTests.swift create mode 100644 cli/Tests/puremacTests/StatusScreenTests.swift diff --git a/cli/README.md b/cli/README.md index dc514a0..39de8e5 100644 --- a/cli/README.md +++ b/cli/README.md @@ -36,7 +36,7 @@ puremac purge ~/Projects puremac analyze ~/Projects ``` -Cleanup opens a selection screen. Nothing is selected when the interactive review begins. Move through the list, choose individual paths, and check the running size total. Press Return to review the selection, then confirm permanent deletion separately. +Cleanup opens a selection screen. Nothing is selected when the interactive review begins. Move through the list, choose individual paths, and check the running size total. Press Return to review the selection, then confirm permanent deletion in a separate dialog. | Key | Action | |---|---| @@ -47,9 +47,9 @@ Cleanup opens a selection screen. Nothing is selected when the interactive revie | Return | Review the selection | | Esc / Q | Cancel | -Use Left and Right to scroll a long focused path. The final confirmation prints every selected path in full. Selection is by path, including recent project artifacts that earlier versions only displayed. +Use Left and Right to scroll a long focused path. The final review lists every selected item. Return opens the confirmation dialog with Cancel selected; choose Remove or press Y to delete, Esc to go back. Selection is by path, including recent project artifacts that earlier versions only displayed. -Prefer an ordinary scrolling terminal? Use `--plain` for numbered selection and a text review: +Prefer an ordinary scrolling terminal? Use `--plain` for numbered selection and a text review that prints every selected path in full: ```bash puremac purge ~/Projects --plain diff --git a/cli/Sources/TerminalUI/Buffer.swift b/cli/Sources/TerminalUI/Buffer.swift index 92cad97..37f79da 100644 --- a/cli/Sources/TerminalUI/Buffer.swift +++ b/cli/Sources/TerminalUI/Buffer.swift @@ -89,6 +89,23 @@ public struct Buffer: Equatable { return column - x } + public mutating func clear(_ rect: Rect) { + let left = max(0, rect.x) + let right = min(width, rect.x + rect.width) + let top = max(0, rect.y) + let bottom = min(height, rect.y + rect.height) + guard right > left, bottom > top else { return } + let blanks = String(repeating: " ", count: right - left) + for row in top.. [String] { (0.. Int { + max(1, area.width - 8) + } + + public func frame(in area: Rect) -> Rect { + placement(in: area).frame + } + + public func render(in area: Rect, buffer: inout Buffer) { + let (frame, layout) = placement(in: area) + buffer.clear(frame) + let content = Window(title: title, borderStyle: borderStyle, titleStyle: titleStyle) + .render(in: frame, buffer: &buffer) + var row = content.y + for message in layout.messageRows { + buffer.write([message], x: content.x, y: row, maxWidth: content.width) + row += 1 + } + row += layout.blankRows + if !buttons.isEmpty { + renderButtons(in: content, row: row, buffer: &buffer) + row += 1 + } + hints?.render(in: Rect(x: content.x, y: row, width: content.width, height: layout.hintRows), buffer: &buffer) + } + + private struct Layout { + var messageRows: [Span] + var blankRows: Int + var hintRows: Int + var buttonRows: Int + var height: Int { messageRows.count + blankRows + buttonRows + hintRows } + } + + private func placement(in area: Rect) -> (frame: Rect, layout: Layout) { + let contentWidth = self.contentWidth(maxWidth: Dialog.maxContentWidth(in: area)) + let layout = layout(contentWidth: contentWidth, maxRows: area.height - 4) + let width = contentWidth + 4 + let height = layout.height + 2 + let frame = Rect( + x: area.x + (area.width - width) / 2, + y: area.y + (area.height - height) / 2, + width: width, + height: height + ) + return (frame, layout) + } + + private var buttonLabels: [String] { + buttons.indices.map { index in + let title = Term.sanitize(buttons[index].title) + return index == focusedButton ? "› \(title) ‹" : "[ \(title) ]" + } + } + + private var buttonsWidth: Int { + guard !buttons.isEmpty else { return 0 } + return buttonLabels.reduce(0) { $0 + Term.displayWidth($1) } + 2 * (buttons.count - 1) + } + + private func contentWidth(maxWidth: Int) -> Int { + let titleWidth = Term.displayWidth(Term.sanitize(title)) + 2 + let messageWidth = message.map { Term.displayWidth(Term.sanitize($0.text)) }.max() ?? 0 + let hintWidth = hints?.rows(width: .max).first?.reduce(0) { $0 + Term.displayWidth($1.text) } ?? 0 + return max(1, min(max(titleWidth, messageWidth, buttonsWidth, hintWidth), maxWidth)) + } + + private func layout(contentWidth: Int, maxRows: Int) -> Layout { + let hintRows = hints?.rows(width: contentWidth).count ?? 0 + let buttonRows = buttons.isEmpty ? 0 : 1 + let tailRows = buttonRows + hintRows + let wrapped = message.flatMap { paragraph in + Term.wordWrap(paragraph.text, width: contentWidth).map { Span($0, paragraph.style) } + } + let blankRows = tailRows > 0 && wrapped.count + 1 + tailRows <= maxRows ? 1 : 0 + let messageRows = Array(wrapped.prefix(max(0, maxRows - blankRows - tailRows))) + return Layout(messageRows: messageRows, blankRows: blankRows, hintRows: hintRows, buttonRows: buttonRows) + } + + private func renderButtons(in content: Rect, row: Int, buffer: inout Buffer) { + var column = max(content.x, content.x + content.width - buttonsWidth) + for (index, label) in buttonLabels.enumerated() { + let focused = index == focusedButton + let style = TextStyle(color: buttons[index].role == .destructive ? .red : nil, inverse: focused) + column += buffer.write(label, x: column, y: row, style: style, maxWidth: content.x + content.width - column) + 2 + } + } +} diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 69d358c..15e20eb 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -138,3 +138,68 @@ public enum Term { return String(characters.reversed()) } } + +extension Term { + public static func wrap(_ string: String, width: Int) -> [String] { + let safe = sanitize(string) + guard !safe.isEmpty else { return [""] } + var lines: [String] = [] + var current = "" + var used = 0 + for character in safe { + let characterWidth = max(0, displayWidth(String(character))) + if used + characterWidth > width && !current.isEmpty { + lines.append(current) + current = "" + used = 0 + } + current.append(character) + used += characterWidth + } + if !current.isEmpty { lines.append(current) } + return lines.isEmpty ? [""] : lines + } + + static func wordWrap(_ string: String, width: Int) -> [String] { + var lines: [String] = [] + var current = "" + var gap = "" + for token in wordTokens(sanitize(string)) { + guard !token.isSpaces else { + gap = token.text + continue + } + let word = token.text + if displayWidth(word) <= width { + if current.isEmpty { + current = word + } else if displayWidth(current) + displayWidth(gap) + displayWidth(word) <= width { + current += gap + word + } else { + lines.append(current) + current = word + } + continue + } + if !current.isEmpty { lines.append(current) } + let pieces = wrap(word, width: width) + lines += pieces.dropLast() + current = pieces[pieces.count - 1] + } + lines.append(current) + return lines + } + + private static func wordTokens(_ string: String) -> [(text: String, isSpaces: Bool)] { + var tokens: [(text: String, isSpaces: Bool)] = [] + for character in string { + let isSpace = character == " " + if let last = tokens.last, last.isSpaces == isSpace { + tokens[tokens.count - 1].text.append(character) + } else { + tokens.append((String(character), isSpace)) + } + } + return tokens + } +} diff --git a/cli/Sources/TerminalUI/TerminalSession.swift b/cli/Sources/TerminalUI/TerminalSession.swift index ee79841..d84c374 100644 --- a/cli/Sources/TerminalUI/TerminalSession.swift +++ b/cli/Sources/TerminalUI/TerminalSession.swift @@ -13,6 +13,7 @@ public enum TerminalKey: Equatable { case enter case escape case space + case tab case backspace case delete case character(Character) @@ -152,19 +153,18 @@ public final class TerminalSession { public func readKey() -> TerminalKey { guard !isClosed, let first = readByte() else { return .escape } - switch first { - case 0x0A, 0x0D: - return .enter - case 0x20: - return .space - case 0x08, 0x7F: - return .backspace - case 0x1B: - return readEscapeSequence() - case 0x01...0x1A: - return .unknown - default: - return decodeCharacter(firstByte: first) + if let key = Self.key(forSimpleByte: first) { return key } + return first == 0x1B ? readEscapeSequence() : decodeCharacter(firstByte: first) + } + + static func key(forSimpleByte byte: UInt8) -> TerminalKey? { + switch byte { + case 0x0A, 0x0D: return .enter + case 0x20: return .space + case 0x09: return .tab + case 0x08, 0x7F: return .backspace + case 0x01...0x1A: return .unknown + default: return nil } } diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index 1021549..cd997c0 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -285,27 +285,21 @@ struct Analyze: ParsableCommand { if let child = Self.focusedChild(levels[index]) { Self.revealInFinder(child.path) } default: break } - case .delete, .space, .unknown: + case .delete, .space, .tab, .unknown: break } } } static func renderMeasuring(_ path: String, width: Int, height: Int) -> Buffer { - guard TooSmallScreen.fits(width: width, height: height) else { - return TooSmallScreen.render(title: windowTitle, exitHint: "Ctrl+C cancel", width: width, height: height) - } - var buffer = Buffer(width: width, height: height) - let content = window.render(in: buffer.area, buffer: &buffer) - let cancelHint = KeyHints([KeyHint("Ctrl+C", "cancel")]) - let areas = content.splitRows([.length(2), .fill, .length(1), .length(cancelHint.rows(width: content.width).count)]) - let (header, divider, footer) = (areas[0], areas[2], areas[3]) - - buffer.write("Measuring allocated space...", x: header.x, y: header.y, style: TextStyle(dim: true), maxWidth: header.width) - buffer.write(Term.truncate(path, to: header.width, middle: true), x: header.x, y: header.y + 1) - window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) - cancelHint.render(in: footer, buffer: &buffer) - return buffer + StatusScreen.render( + title: windowTitle, + message: "Measuring allocated space...", + detail: path, + hint: StatusScreen.cancelHint, + width: width, + height: height + ) } private static let windowTitle = "PureMac Space Explorer" @@ -345,11 +339,11 @@ struct Analyze: ParsableCommand { let hintRows = browserHints.rows(width: content.width).count let errorRows = snapshot.errors.isEmpty ? 0 : 1 let spareRows = content.height - headerRows - dividerRows - errorRows - hintRows - minimumListRows - var pathLines = wrap(focusedPath, width: pathWidth) + var pathLines = Term.wrap(focusedPath, width: pathWidth) let pathRows = min(pathLines.count, max(1, spareRows)) var budget = pathRows * pathWidth while pathLines.count > pathRows && budget > 1 { - pathLines = wrap(Term.truncate(focusedPath, to: budget, middle: true), width: pathWidth) + pathLines = Term.wrap(Term.truncate(focusedPath, to: budget, middle: true), width: pathWidth) budget -= 1 } let areas = content.splitRows( @@ -485,27 +479,6 @@ struct Analyze: ParsableCommand { return Term.truncate(parts.joined(separator: " · "), to: width) } - static func wrap(_ string: String, width: Int) -> [String] { - let safe = Term.sanitize(string) - guard !safe.isEmpty else { return [""] } - var lines: [String] = [] - var current = "" - var used = 0 - for character in safe { - let value = String(character) - let characterWidth = max(0, Term.displayWidth(value)) - if used + characterWidth > width && !current.isEmpty { - lines.append(current) - current = "" - used = 0 - } - current.append(character) - used += characterWidth - } - if !current.isEmpty { lines.append(current) } - return lines.isEmpty ? [""] : lines - } - private static func revealInFinder(_ path: String) { let process = Process() process.executableURL = URL(fileURLWithPath: "/usr/bin/open") diff --git a/cli/Sources/puremac/Commands/Clean.swift b/cli/Sources/puremac/Commands/Clean.swift index 09c440b..669ffd8 100644 --- a/cli/Sources/puremac/Commands/Clean.swift +++ b/cli/Sources/puremac/Commands/Clean.swift @@ -53,12 +53,28 @@ struct Clean: ParsableCommand { let ids = category.map { [$0] } ?? Clean.validIDs let ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) + let scanning = "Scanning " + ids.map(Clean.title).joined(separator: ", ") + " …" + let progress = ScanProgress.forMode(mode) + let scan = { + ids.map { id in + CategoryScanner.scan(categoryID: id, title: Clean.title(id), ignore: ignore, progress: progress) + }.filter { !$0.groups.isEmpty } + } + if mode == .fullscreen { + let labels = CleanupFlow.Labels( + scanning: scanning, + empty: Clean.emptyMessage, + reviewTitle: "Choose items to clean", + noun: "item" + ) + let result = try CleanupFlow.run(labels: labels, ignore: ignore, scan: scan) + try CleanupFlow.finish(result, labels: labels) + return + } if !json { - Term.err(Term.dim("Scanning " + ids.map(Clean.title).joined(separator: ", ") + " …")) + Term.err(Term.dim(scanning)) } - let cats = ids.map { id in - CategoryScanner.scan(categoryID: id, title: Clean.title(id), ignore: ignore) - }.filter { !$0.groups.isEmpty } + let cats = scan() if json { print(try JSONReport.string(cats)) @@ -66,7 +82,7 @@ struct Clean: ParsableCommand { } if cats.isEmpty { - print(Term.green("No cleanup candidates found in readable locations.")) + print(Term.green(Clean.emptyMessage)) return } @@ -85,19 +101,13 @@ struct Clean: ParsableCommand { reviewed = cats Render.scanResults(cats) Render.selectionLine(cats) - case .fullscreen: - guard let selection = try InteractiveReview.select(cats, title: "Choose items to clean") else { - print(Term.dim("Cancelled. Nothing removed.")) - return - } - reviewed = selection case .plain: guard let selection = try PlainSelectionReview.select(cats, title: "Choose items to clean") else { print(Term.dim("Cancelled. Nothing removed.")) return } reviewed = selection - case .reportOnly, .unavailable: + case .fullscreen, .reportOnly, .unavailable: return } @@ -121,6 +131,8 @@ struct Clean: ParsableCommand { if out.hadFailures { throw ExitCode.failure } } + static let emptyMessage = "No cleanup candidates found in readable locations." + static func title(_ id: String) -> String { Catalog.categoryTitles.first { $0.id == id }?.title ?? id.capitalized } diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 82909c4..0b0d10a 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -60,13 +60,28 @@ struct Purge: ParsableCommand { ? Purger.defaultRoots : paths.map { Safety.absolutePath($0) } - if !json { Term.err(Term.dim("Scanning " + roots.map { Render.shorten($0) }.joined(separator: ", ") + " …")) } + let scanning = "Scanning " + roots.map { Render.shorten($0) }.joined(separator: ", ") + " …" + if mode == .fullscreen { + let labels = CleanupFlow.Labels( + scanning: scanning, + empty: Purge.emptyMessage, + reviewTitle: "Choose project artifacts", + noun: "artifact" + ) + let result = try CleanupFlow.run(labels: labels, ignore: ignore) { + let cat = Purger.scan(roots: roots, olderThanDays: days, ignore: ignore) + return cat.groups.isEmpty ? [] : [cat] + } + try CleanupFlow.finish(result, labels: labels) + return + } + if !json { Term.err(Term.dim(scanning)) } let cat = Purger.scan(roots: roots, olderThanDays: days, ignore: ignore) if json { print(try JSONReport.string([cat])); return } if cat.groups.isEmpty { - print(Term.green("No project artifacts found in readable locations.")) + print(Term.green(Purge.emptyMessage)) return } @@ -83,19 +98,13 @@ struct Purge: ParsableCommand { case .forced: reviewed = [cat] renderScan(cat, days: days) - case .fullscreen: - guard let selection = try InteractiveReview.select([cat], title: "Choose project artifacts") else { - print(Term.dim("Cancelled. Nothing removed.")) - return - } - reviewed = selection case .plain: guard let selection = try PlainSelectionReview.select([cat], title: "Choose project artifacts") else { print(Term.dim("Cancelled. Nothing removed.")) return } reviewed = selection - case .reportOnly, .unavailable: + case .fullscreen, .reportOnly, .unavailable: return } @@ -115,6 +124,8 @@ struct Purge: ParsableCommand { if out.hadFailures { throw ExitCode.failure } } + static let emptyMessage = "No project artifacts found in readable locations." + private func resolvedDays() throws -> Int { if olderThanDays >= 0 { return olderThanDays } let config = try ConfigStore(fileURL: AppPaths.configFile) diff --git a/cli/Sources/puremac/Core/CategoryScanner.swift b/cli/Sources/puremac/Core/CategoryScanner.swift index 1a3cf01..6cd0c9d 100644 --- a/cli/Sources/puremac/Core/CategoryScanner.swift +++ b/cli/Sources/puremac/Core/CategoryScanner.swift @@ -1,12 +1,30 @@ import Foundation +enum ScanProgress: Equatable { + case stderr, silent + + static func forMode(_ mode: CleanupCommandMode) -> ScanProgress { + mode == .fullscreen ? .silent : .stderr + } + + func write(_ text: String) { + guard self == .stderr else { return } + FileHandle.standardError.write(Data(text.utf8)) + } +} + enum CategoryScanner { static let minSize: Int64 = 1024 - static func scan(categoryID id: String, title: String, ignore: IgnoreStore) -> CategoryScan { - FileHandle.standardError.write(Data(" scanning \(title)…\r".utf8)) + static func scan( + categoryID id: String, + title: String, + ignore: IgnoreStore, + progress: ScanProgress = .stderr + ) -> CategoryScan { + progress.write(" scanning \(title)…\r") let groups = id == "trash" ? scanTrash(ignore: ignore) : scanCatalog(id: id, ignore: ignore) - FileHandle.standardError.write(Data(" \r".utf8)) + progress.write(" \r") return CategoryScan(id: id, title: title, groups: groups) } diff --git a/cli/Sources/puremac/Core/CleanupFlow.swift b/cli/Sources/puremac/Core/CleanupFlow.swift new file mode 100644 index 0000000..0339943 --- /dev/null +++ b/cli/Sources/puremac/Core/CleanupFlow.swift @@ -0,0 +1,154 @@ +import ArgumentParser +import TerminalUI + +enum CleanupFlowResult { + case nothingFound + case cancelled + case finished(CleanOutcome) +} + +enum CleanupFlow { + struct Labels { + let scanning: String + let empty: String + let reviewTitle: String + let noun: String + } + + static func run( + labels: Labels, + ignore: IgnoreStore, + scan: () -> [CategoryScan] + ) throws -> CleanupFlowResult { + let session = try TerminalSession() + defer { session.close() } + + session.draw(scanningScreen(labels: labels, width: session.width, height: session.height)) + let categories = scan() + guard !categories.isEmpty else { + session.draw(emptyScreen(labels: labels, width: session.width, height: session.height)) + while !closesInfoDialog(session.readKey()) {} + return .nothingFound + } + + guard let review = InteractiveReview.select( + categories, session: session, title: labels.reviewTitle, noun: labels.noun + ) else { return .cancelled } + + let items = review.selectedResult().flatMap { $0.selectedItems } + session.draw(removingScreen(review: review, labels: labels, width: session.width, height: session.height)) + let outcome = Cleaner.remove(items, ignore: ignore, dryRun: false) + session.draw(resultScreen(outcome: outcome, review: review, labels: labels, width: session.width, height: session.height)) + while !closesInfoDialog(session.readKey()) {} + return .finished(outcome) + } + + static func finish(_ result: CleanupFlowResult, labels: Labels) throws { + switch result { + case .nothingFound: + print(Term.green(labels.empty)) + case .cancelled: + print(Term.dim("Cancelled. Nothing removed.")) + case .finished(let outcome): + Render.cleanupSummary(outcome, dryRun: false) + if outcome.hadFailures { throw ExitCode.failure } + } + } + + static func closesInfoDialog(_ key: TerminalKey) -> Bool { + switch key { + case .enter, .escape: return true + case .character(let character): return character.lowercased() == "q" + default: return false + } + } + + static func scanningScreen(labels: Labels, width: Int, height: Int) -> Buffer { + StatusScreen.render( + title: "PureMac", + message: labels.scanning, + detail: nil, + hint: StatusScreen.cancelHint, + width: width, + height: height + ) + } + + static func emptyScreen(labels: Labels, width: Int, height: Int) -> Buffer { + let dialog = Dialog( + title: "Nothing to clean", + message: [Span(labels.empty)], + buttons: [DialogButton("OK")], + focusedButton: 0 + ) + return StatusScreen.overlay( + dialog, + on: scanningScreen(labels: labels, width: width, height: height), + tooSmallExitHint: closeHint + ) + } + + static func removingScreen(review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { + let dialog = removingDialog(count: review.selectedCount, total: review.selectedBytes, noun: labels.noun) + return StatusScreen.overlay( + dialog, + on: finalReview(review, labels: labels, width: width, height: height), + tooSmallExitHint: "Removing…" + ) + } + + static func resultScreen(outcome: CleanOutcome, review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { + StatusScreen.overlay( + resultDialog(outcome, area: Rect(x: 0, y: 0, width: width, height: height)), + on: finalReview(review, labels: labels, width: width, height: height), + tooSmallExitHint: closeHint + ) + } + + static func counted(_ count: Int, _ noun: String) -> String { + "\(count) \(noun)\(count == 1 ? "" : "s")" + } + + static func removingDialog(count: Int, total: Int64, noun: String) -> Dialog { + Dialog( + title: "Removing \(counted(count, noun))…", + titleStyle: StatusScreen.warningTitle, + borderStyle: StatusScreen.warningBorder, + message: [Span(ByteCount.human(total))] + ) + } + + private static let closeHint = "Enter close" + + private static func resultDialog(_ outcome: CleanOutcome, area: Rect) -> Dialog { + var message = [Span(ByteCount.human(outcome.freedBytes) + Render.removedDetail(outcome))] + if !outcome.skipped.isEmpty { + message.append(Span(Render.skippedLabel(outcome) + Render.skippedNote, TextStyle(color: .yellow))) + } + if !outcome.failed.isEmpty { + let red = TextStyle(color: .red) + message.append(Span(Render.failedLabel(outcome), red)) + let rowWidth = Dialog.maxContentWidth(in: area) + message += outcome.failed.prefix(3).map { + Span(Term.truncate("! " + Render.shorten($0.path), to: rowWidth, middle: true), red) + } + } + return Dialog( + title: Render.cleanupCompleteTitle, + titleStyle: TextStyle(color: .green, bold: true), + message: message, + buttons: [DialogButton("Done")], + focusedButton: 0 + ) + } + + private static func finalReview(_ review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { + InteractiveReview.render( + model: review, + title: labels.reviewTitle, + noun: labels.noun, + width: width, + height: height + ) + } +} diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index 4837986..1f53c90 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -13,6 +13,14 @@ enum ReviewDisplayRow { case item(ReviewAddress) } +enum ConfirmationButton: Int { + case cancel, remove +} + +enum ReviewKeyRoute: Equatable { + case handled, remove, quit, passthrough +} + struct InteractiveReviewModel { var categories: [CategoryScan] var query = "" @@ -22,6 +30,9 @@ struct InteractiveReviewModel { var pathOffset = 0 private(set) var focus = 0 private(set) var reviewFocus = 0 + private(set) var confirmation: ConfirmationButton? + + var isConfirming: Bool { confirmation != nil } init(categories: [CategoryScan]) { self.categories = categories.map { category in @@ -155,6 +166,73 @@ struct InteractiveReviewModel { return true } + mutating func beginConfirmation() -> Bool { + guard isReviewing else { return false } + confirmation = .cancel + return true + } + + mutating func cancelConfirmation() { + confirmation = nil + } + + mutating func moveConfirmationFocus(_ delta: Int) { + guard let current = confirmation else { return } + let moved = min(ConfirmationButton.remove.rawValue, max(ConfirmationButton.cancel.rawValue, current.rawValue + delta)) + confirmation = ConfirmationButton(rawValue: moved) + } + + mutating func cycleConfirmationFocus() { + guard let current = confirmation else { return } + confirmation = current == .cancel ? .remove : .cancel + } + + mutating func handleConfirmationKey(_ key: TerminalKey) -> ReviewKeyRoute { + guard let focused = confirmation else { return .passthrough } + switch key { + case .left: + moveConfirmationFocus(-1) + case .right: + moveConfirmationFocus(1) + case .tab: + cycleConfirmationFocus() + case .enter: + if focused == .remove { return .remove } + cancelConfirmation() + case .escape: + cancelConfirmation() + case .character(let character): + switch character.lowercasedString { + case "y": return .remove + case "n": cancelConfirmation() + case "q": return .quit + default: break + } + default: + break + } + return .handled + } + + mutating func routeKey(_ key: TerminalKey) -> ReviewKeyRoute { + if isConfirming { return handleConfirmationKey(key) } + if isReviewing, key == .enter { + _ = beginConfirmation() + return .handled + } + return .passthrough + } + + func acceptsKey(_ key: TerminalKey, tooSmall: Bool) -> Bool { + guard tooSmall, let focused = confirmation else { return true } + switch key { + case .escape: return true + case .enter: return focused == .cancel + case .character(let character): return ["n", "q"].contains(character.lowercasedString) + default: return false + } + } + mutating func endReview() { isReviewing = false pathOffset = 0 @@ -209,15 +287,29 @@ struct InteractiveReviewModel { } enum InteractiveReview { - static func select(_ categories: [CategoryScan], title: String) throws -> [CategoryScan]? { - let session = try TerminalSession() - defer { session.close() } - + static func select( + _ categories: [CategoryScan], + session: TerminalSession, + title: String, + noun: String + ) -> InteractiveReviewModel? { var model = InteractiveReviewModel(categories: categories) while true { - session.draw(render(model: model, title: title, width: session.width, height: session.height)) + session.draw(render(model: model, title: title, noun: noun, width: session.width, height: session.height)) let key = session.readKey() + guard model.acceptsKey(key, tooSmall: !TooSmallScreen.fits(width: session.width, height: session.height)) else { + continue + } + switch model.routeKey(key) { + case .remove: + model.cancelConfirmation() + return model + case .quit: return nil + case .handled: continue + case .passthrough: break + } + if model.isSearching { switch key { case .enter: @@ -261,9 +353,6 @@ enum InteractiveReview { case .space: model.toggleFocused() case .enter: - if model.isReviewing { - return model.selectedResult() - } _ = model.beginReview() case .escape: if model.isReviewing { @@ -299,6 +388,7 @@ enum InteractiveReview { static func render( model: InteractiveReviewModel, title: String, + noun: String, width: Int, height: Int ) -> Buffer { @@ -307,27 +397,24 @@ enum InteractiveReview { } var buffer = Buffer(width: width, height: height) let reviewing = model.isReviewing - let accent = TextStyle(color: .yellow) + let accent = StatusScreen.warningBorder let window = Window( title: reviewing ? "Final review" : title, info: "\(model.selectedCount) selected · \(ByteCount.human(model.selectedBytes))", borderStyle: reviewing ? accent : TextStyle(dim: true), - titleStyle: TextStyle(color: reviewing ? .yellow : .cyan, bold: true) + titleStyle: reviewing ? StatusScreen.warningTitle : TextStyle(color: .cyan, bold: true) ) let content = window.render(in: buffer.area, buffer: &buffer) let hints = KeyHints(reviewing ? reviewHints : selectHints) let areas = content.splitRows( - [.length(1), .fill, .length(1), .length(1), .length(hints.rows(width: content.width).count), .length(reviewing ? 1 : 0)] + [.length(1), .fill, .length(1), .length(1), .length(hints.rows(width: content.width).count)] ) - let (header, list, divider, path, footer, confirmation) = (areas[0], areas[1], areas[2], areas[3], areas[4], areas[5]) + let (header, list, divider, path, footer) = (areas[0], areas[1], areas[2], areas[3], areas[4]) renderHeader(model: model, in: header, buffer: &buffer) window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) buffer.write(focusedPathSpans(model: model, width: path.width), x: path.x, y: path.y, maxWidth: path.width) hints.render(in: footer, buffer: &buffer) - if reviewing { - buffer.write("Command confirmation follows", x: confirmation.x, y: confirmation.y, style: accent, maxWidth: confirmation.width) - } let rows = model.displayRows(reviewing: reviewing) let focusedAddress = model.focusedAddress @@ -342,9 +429,33 @@ enum InteractiveReview { } Scrollbar(total: rows.count, visible: list.height, offset: start) .render(column: width - 1, rows: list.y..<(list.y + list.height), buffer: &buffer) - return buffer + guard let focus = model.confirmation else { return buffer } + let dialog = confirmationDialog(count: model.selectedCount, total: model.selectedBytes, noun: noun, focus: focus) + return StatusScreen.overlay(dialog, on: buffer) } + static func confirmationDialog(count: Int, total: Int64, noun: String, focus: ConfirmationButton) -> Dialog { + Dialog( + title: "Remove \(CleanupFlow.counted(count, noun))?", + titleStyle: StatusScreen.warningTitle, + borderStyle: StatusScreen.warningBorder, + message: [ + Span("\(ByteCount.human(total)) will be permanently deleted."), + Span("This cannot be undone.") + ], + buttons: [DialogButton("Cancel"), DialogButton("Remove", role: .destructive)], + focusedButton: focus.rawValue, + hints: KeyHints(confirmationHints) + ) + } + + private static let confirmationHints = [ + KeyHint("←→", "choose"), + KeyHint("Enter", "select"), + KeyHint("Y", "remove"), + KeyHint("Esc", "back") + ] + private static let selectHints = [ KeyHint("↑↓", "move"), KeyHint("←→", "path"), diff --git a/cli/Sources/puremac/Core/Render.swift b/cli/Sources/puremac/Core/Render.swift index 1710e39..10a6b36 100644 --- a/cli/Sources/puremac/Core/Render.swift +++ b/cli/Sources/puremac/Core/Render.swift @@ -81,22 +81,22 @@ enum Render { print(Term.bold("Dry run complete")) print( Term.cyan(ByteCount.human(outcome.freedBytes)) - + Term.dim(" reclaimable across \(outcome.removed) item\(outcome.removed == 1 ? "" : "s")") + + Term.dim(" reclaimable across \(itemCount(outcome.removed))") ) print(Term.dim("Nothing was deleted.")) } else { - print(Term.green(Term.bold("Cleanup complete"))) + print(Term.green(Term.bold(cleanupCompleteTitle))) print( Term.bold(ByteCount.human(outcome.freedBytes)) - + Term.dim(" removed across \(outcome.removed) item\(outcome.removed == 1 ? "" : "s")") + + Term.dim(removedDetail(outcome)) ) } if !outcome.skipped.isEmpty { - print(Term.yellow("\(outcome.skipped.count) skipped") + Term.dim(" protected or ignored")) + print(Term.yellow(skippedLabel(outcome)) + Term.dim(skippedNote)) } if !outcome.failed.isEmpty { - print(Term.red("\(outcome.failed.count) failed")) + print(Term.red(failedLabel(outcome))) for failure in outcome.failed.prefix(10) { Term.err(" ! \(Term.sanitize(failure.path))") Term.err(" \(Term.sanitize(failure.error))") @@ -105,6 +105,26 @@ enum Render { print("") } + static let cleanupCompleteTitle = "Cleanup complete" + + static func itemCount(_ count: Int) -> String { + CleanupFlow.counted(count, "item") + } + + static func removedDetail(_ outcome: CleanOutcome) -> String { + " removed across \(itemCount(outcome.removed))" + } + + static func skippedLabel(_ outcome: CleanOutcome) -> String { + "\(outcome.skipped.count) skipped" + } + + static let skippedNote = " protected or ignored" + + static func failedLabel(_ outcome: CleanOutcome) -> String { + "\(outcome.failed.count) failed" + } + static func sizeCol(_ bytes: Int64) -> String { pad(ByteCount.human(bytes), sizeColumnWidth) } diff --git a/cli/Sources/puremac/Core/StatusScreen.swift b/cli/Sources/puremac/Core/StatusScreen.swift new file mode 100644 index 0000000..27819ee --- /dev/null +++ b/cli/Sources/puremac/Core/StatusScreen.swift @@ -0,0 +1,47 @@ +import TerminalUI + +enum StatusScreen { + static let warningTitle = TextStyle(color: .yellow, bold: true) + static let cancelHint = KeyHint("Ctrl+C", "cancel") + static let warningBorder = TextStyle(color: .yellow) + + static func render( + title: String, + message: String, + detail: String?, + hint: KeyHint, + width: Int, + height: Int + ) -> Buffer { + let hints = KeyHints([hint]) + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: title, exitHint: "\(hint.key) \(hint.action)", width: width, height: height) + } + var buffer = Buffer(width: width, height: height) + let window = Window(title: title) + let content = window.render(in: buffer.area, buffer: &buffer) + let areas = content.splitRows([.length(2), .fill, .length(1), .length(hints.rows(width: content.width).count)]) + let (header, divider, footer) = (areas[0], areas[2], areas[3]) + + buffer.write(Term.truncate(message, to: header.width), x: header.x, y: header.y, style: TextStyle(dim: true)) + if let detail { + buffer.write(Term.truncate(detail, to: header.width, middle: true), x: header.x, y: header.y + 1) + } + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + hints.render(in: footer, buffer: &buffer) + return buffer + } + + static func overlay(_ dialog: Dialog, on background: Buffer, tooSmallExitHint: String? = nil) -> Buffer { + guard TooSmallScreen.fits(width: background.width, height: background.height) else { + guard let tooSmallExitHint else { return background } + return TooSmallScreen.render( + title: "PureMac", exitHint: tooSmallExitHint, width: background.width, height: background.height + ) + } + var buffer = background + buffer.fade() + dialog.render(in: buffer.area, buffer: &buffer) + return buffer + } +} diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index 109eea8..c85ea08 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -64,8 +64,13 @@ enum HomeMenu { case 5: try Ignore.List.parse([]).run() default: return } + guard waitsForReturn(afterChoice: choice) else { continue } print(Term.dim("\nPress Return to return to PureMac."), terminator: " ") guard readLine() != nil else { return } } } + + static func waitsForReturn(afterChoice choice: Int) -> Bool { + choice != 0 && choice != 1 + } } diff --git a/cli/Tests/TerminalUITests/BufferTests.swift b/cli/Tests/TerminalUITests/BufferTests.swift index 86363d4..d965c4d 100644 --- a/cli/Tests/TerminalUITests/BufferTests.swift +++ b/cli/Tests/TerminalUITests/BufferTests.swift @@ -162,4 +162,45 @@ final class BufferTests: XCTestCase { } XCTAssertEqual(buffer.plainLines(), ["界界 ", "a界 "]) } + + func testClearBlanksRectAndKeepsOutside() { + var buffer = Buffer(width: 5, height: 3) + for row in 0..<3 { buffer.write("xxxxx", x: 0, y: row, style: TextStyle(bold: true)) } + buffer.clear(Rect(x: 1, y: 1, width: 3, height: 1)) + XCTAssertEqual(buffer.plainLines(), ["xxxxx", "x x", "xxxxx"]) + XCTAssertEqual(buffer[2, 1], Cell(symbol: " ", style: .plain)) + } + + func testClearIsClippedToBuffer() { + var buffer = Buffer(width: 3, height: 2) + for row in 0..<2 { buffer.write("xxx", x: 0, y: row) } + buffer.clear(Rect(x: -2, y: 1, width: 4, height: 5)) + XCTAssertEqual(buffer.plainLines(), ["xxx", " x"]) + buffer.clear(Rect(x: 5, y: 5, width: 2, height: 2)) + buffer.clear(Rect(x: 0, y: 0, width: 0, height: 2)) + XCTAssertEqual(buffer.plainLines(), ["xxx", " x"]) + } + + func testClearBlanksOutsideHalfOfWideCharacterOnEdges() { + var buffer = Buffer(width: 6, height: 1) + buffer.write("界界界", x: 0, y: 0) + buffer.clear(Rect(x: 1, y: 0, width: 4, height: 1)) + XCTAssertEqual(buffer.plainLines(), [" "]) + var inner = Buffer(width: 6, height: 1) + inner.write("界界界", x: 0, y: 0) + inner.clear(Rect(x: 2, y: 0, width: 2, height: 1)) + XCTAssertEqual(inner.plainLines(), ["界 界"]) + } + + func testFadeKeepsSymbolsAndMakesEverythingDim() { + var buffer = Buffer(width: 4, height: 2) + buffer.write("a界", x: 0, y: 0, style: TextStyle(color: .red, bold: true, inverse: true)) + buffer.fade() + let dim = TextStyle(dim: true) + XCTAssertEqual(buffer.plainLines(), ["a界 ", " "]) + XCTAssertEqual(buffer[0, 0], Cell(symbol: "a", style: dim)) + XCTAssertEqual(buffer[1, 0], Cell(symbol: "界", style: dim)) + XCTAssertEqual(buffer[2, 0], Cell(symbol: "", style: dim)) + XCTAssertEqual(buffer[0, 1], Cell(symbol: " ", style: dim)) + } } diff --git a/cli/Tests/TerminalUITests/DialogTests.swift b/cli/Tests/TerminalUITests/DialogTests.swift new file mode 100644 index 0000000..f09236b --- /dev/null +++ b/cli/Tests/TerminalUITests/DialogTests.swift @@ -0,0 +1,210 @@ +import XCTest +@testable import TerminalUI + +final class DialogTests: XCTestCase { + private let area = Rect(x: 0, y: 0, width: 40, height: 12) + + private func render(_ dialog: Dialog, in area: Rect, fill: String? = nil) -> (frame: Rect, buffer: Buffer, rows: [String]) { + var buffer = Buffer(width: area.width, height: area.height) + if let fill { + for row in 0.. Dialog { + Dialog(title: "Hi", message: [Span(message)], buttons: buttons) + } + + func testMaxContentWidthLeavesTheMarginAroundTheFrame() { + XCTAssertEqual(Dialog.maxContentWidth(in: Rect(x: 0, y: 0, width: 80, height: 24)), 72) + XCTAssertEqual(Dialog.maxContentWidth(in: Rect(x: 0, y: 0, width: 4, height: 24)), 1) + } + + func testFrameIsCenteredAndSizedToContent() { + let dialog = simple() + XCTAssertEqual(dialog.frame(in: area), Rect(x: 15, y: 3, width: 10, height: 5)) + XCTAssertEqual(render(dialog, in: area).rows, [ + "╭─ Hi ───╮", + "│ Hello │", + "│ │", + "│ [ OK ] │", + "╰────────╯" + ]) + } + + func testFrameIsCenteredInOffsetArea() { + let frame = simple().frame(in: Rect(x: 10, y: 2, width: 40, height: 12)) + XCTAssertEqual(frame, Rect(x: 25, y: 5, width: 10, height: 5)) + } + + func testContentWidthIsWidestOfMessageButtonsAndHints() { + let wideButtons = simple(buttons: [DialogButton("Cancel"), DialogButton("Remove")]) + XCTAssertEqual(wideButtons.frame(in: area).width, 22 + 4) + var withHints = simple() + withHints.hints = KeyHints([KeyHint("Esc", "back"), KeyHint("Enter", "select")]) + XCTAssertEqual(withHints.frame(in: area).width, Term.displayWidth("Esc back Enter select") + 4) + } + + func testWidthIsCappedToMarginsAndMessageWraps() { + let dialog = simple(message: String(repeating: "word ", count: 30)) + let result = render(dialog, in: area) + XCTAssertEqual(result.frame.width, 36) + XCTAssertEqual(result.frame.x, 2) + XCTAssertTrue(result.rows[1].hasPrefix("│ word word")) + XCTAssertTrue(result.rows.allSatisfy { Term.displayWidth($0) == 36 }) + } + + func testMessageWrapsOnSpacesAndEachParagraphOnItsOwn() { + let dialog = Dialog( + title: "T", + message: [Span("aaa bbb ccc ddd"), Span("ee")], + buttons: [] + ) + let result = render(dialog, in: Rect(x: 0, y: 0, width: 16, height: 12)) + XCTAssertEqual(result.frame.width, 12) + XCTAssertEqual(Array(result.rows[1...3]), ["│ aaa bbb │", "│ ccc ddd │", "│ ee │"]) + } + + func testLongWordIsHardBrokenByDisplayWidth() { + let dialog = Dialog(title: "T", message: [Span("abcdefghij 界界界")], buttons: []) + let result = render(dialog, in: Rect(x: 0, y: 0, width: 13, height: 12)) + let rows = result.buffer.plainLines().dropFirst(result.frame.y + 1).prefix(4).map { String($0.dropFirst(2).dropLast(2)) } + XCTAssertEqual(rows, ["│ abcde │", "│ fghij │", "│ 界界 │", "│ 界 │"]) + } + + func testDropsBlankRowFirstWhenHeightIsShort() { + let message = (1...7).map { Span("line \($0)") } + let dialog = Dialog(title: "T", message: message, buttons: [DialogButton("OK")]) + let result = render(dialog, in: area) + XCTAssertEqual(result.frame.height, 10) + XCTAssertEqual(result.rows.count, 10) + XCTAssertTrue(result.rows[7].contains("line 7")) + XCTAssertTrue(result.rows[8].contains("[ OK ]")) + } + + func testDropsTrailingMessageRowsAfterBlankRow() { + let message = (1...10).map { Span("line \($0)") } + var dialog = Dialog(title: "T", message: message, buttons: [DialogButton("OK")]) + dialog.hints = KeyHints([KeyHint("Esc", "back")]) + let result = render(dialog, in: area) + XCTAssertEqual(result.frame, Rect(x: result.frame.x, y: 1, width: result.frame.width, height: 10)) + XCTAssertTrue(result.rows[6].contains("line 6")) + XCTAssertFalse(result.rows.joined().contains("line 7")) + XCTAssertTrue(result.rows[7].contains("[ OK ]")) + XCTAssertTrue(result.rows[8].contains("Esc back")) + } + + private func buttonStyles(focused: Int?, buttons: [DialogButton]) -> (start: Int, row: Int, buffer: Buffer) { + var dialog = simple(buttons: buttons) + dialog.focusedButton = focused + let result = render(dialog, in: area) + let rowIndex = result.frame.y + 3 + let line = result.buffer.plainLines()[rowIndex] + let start = line.distance(from: line.startIndex, to: line.range(of: "Cancel")!.lowerBound) - 2 + return (start, rowIndex, result.buffer) + } + + private let both = [DialogButton("Cancel"), DialogButton("Remove", role: .destructive)] + + func testButtonsAreRightAlignedTwoSpacesApart() { + let result = render(simple(buttons: both), in: area) + XCTAssertEqual(result.rows[3], "│ [ Cancel ] [ Remove ] │") + } + + func testFocusedButtonIsWrittenWithPointersAtTheSameWidth() { + var dialog = simple(buttons: both) + dialog.focusedButton = 0 + XCTAssertEqual(render(dialog, in: area).rows[3], "│ › Cancel ‹ [ Remove ] │") + dialog.focusedButton = 1 + XCTAssertEqual(render(dialog, in: area).rows[3], "│ [ Cancel ] › Remove ‹ │") + } + + func testFocusedNormalButtonIsInverse() { + let found = buttonStyles(focused: 0, buttons: both) + for column in found.start..<(found.start + 10) { + XCTAssertEqual(found.buffer[column, found.row].style, TextStyle(inverse: true)) + } + XCTAssertEqual(found.buffer[found.start + 12, found.row].style, TextStyle(color: .red)) + XCTAssertEqual(found.buffer[found.start + 10, found.row].style, .plain) + } + + func testFocusedDestructiveButtonIsRedAndInverse() { + let found = buttonStyles(focused: 1, buttons: both) + XCTAssertEqual(found.buffer[found.start, found.row].style, .plain) + for column in (found.start + 12)..<(found.start + 22) { + XCTAssertEqual(found.buffer[column, found.row].style, TextStyle(color: .red, inverse: true)) + } + } + + func testNoFocusLeavesButtonsUnhighlighted() { + let found = buttonStyles(focused: nil, buttons: both) + XCTAssertEqual(found.buffer[found.start, found.row].style, .plain) + XCTAssertEqual(found.buffer[found.start + 12, found.row].style, TextStyle(color: .red)) + } + + func testHintsRowsFollowButtons() { + var dialog = simple() + dialog.hints = KeyHints([KeyHint("Esc", "back")]) + let result = render(dialog, in: area) + XCTAssertEqual(result.rows[3], "│ [ OK ] │") + XCTAssertEqual(result.rows[4], "│ Esc back │") + XCTAssertEqual(result.rows[5], "╰──────────╯") + } + + func testBorderAndTitleStylesApply() { + var dialog = simple() + dialog.borderStyle = TextStyle(color: .yellow) + dialog.titleStyle = TextStyle(color: .yellow, bold: true) + let result = render(dialog, in: area) + XCTAssertEqual(result.buffer[result.frame.x, result.frame.y].style, TextStyle(color: .yellow)) + XCTAssertEqual(result.buffer[result.frame.x + 3, result.frame.y].style, TextStyle(color: .yellow, bold: true)) + XCTAssertEqual(Dialog(title: "T").borderStyle, .plain) + XCTAssertEqual(Dialog(title: "T").titleStyle, TextStyle(bold: true)) + } + + func testRenderClearsBackgroundInsideFrameOnly() { + let result = render(simple(), in: area, fill: "x") + let lines = result.buffer.plainLines() + XCTAssertEqual(lines[2], String(repeating: "x", count: 40)) + XCTAssertEqual(lines[4], String(repeating: "x", count: 15) + "│ Hello │" + String(repeating: "x", count: 15)) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(result.buffer.lines(colors: true).allSatisfy { Term.displayWidth($0) == 40 }) + } + + func testBlankBackgroundStyleIsResetInsideFrame() { + var buffer = Buffer(width: 40, height: 12) + buffer.fade() + simple().render(in: buffer.area, buffer: &buffer) + XCTAssertEqual(buffer[16, 4].style, .plain) + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + } + + func testStatusDialogWithoutButtonsOrHintsHasNoBlankRow() { + let dialog = Dialog(title: "Working", message: [Span("Removing 2 items…")]) + XCTAssertEqual(render(dialog, in: area).rows, [ + "╭─ Working ─────────╮", + "│ Removing 2 items… │", + "╰───────────────────╯" + ]) + } + + func testContentWidthFitsTitle() { + let shortMessage = Dialog(title: "Cleanup complete", message: [Span("1 KB removed")]) + XCTAssertEqual(render(shortMessage, in: area).rows, [ + "╭─ Cleanup complete ─╮", + "│ 1 KB removed │", + "╰────────────────────╯" + ]) + let titleOnly = Dialog(title: "Removing 2 items…") + XCTAssertEqual(render(titleOnly, in: area).rows, [ + "╭─ Removing 2 items… ─╮", + "╰─────────────────────╯" + ]) + } +} diff --git a/cli/Tests/TerminalUITests/TermTests.swift b/cli/Tests/TerminalUITests/TermTests.swift index a1c3831..cf0d666 100644 --- a/cli/Tests/TerminalUITests/TermTests.swift +++ b/cli/Tests/TerminalUITests/TermTests.swift @@ -1,5 +1,5 @@ import XCTest -import TerminalUI +@testable import TerminalUI final class TermTests: XCTestCase { func testANSIAndUnicodeDisplayWidth() { @@ -27,4 +27,30 @@ final class TermTests: XCTestCase { XCTAssertEqual(Term.bar(fraction: 0.5, width: -2), "") XCTAssertEqual(Term.bar(fraction: 0.5).count, 24) } + + func testWrapPreservesEveryCharacter() { + let path = "/Users/example/a folder/with/a/very-long-name/file.bin" + let lines = Term.wrap(path, width: 11) + + XCTAssertGreaterThan(lines.count, 1) + XCTAssertEqual(lines.joined(), path) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= 11 }) + } + + func testWordWrapKeepsSpaceRunsWithinALine() { + XCTAssertEqual(Term.wordWrap("one two three", width: 12), ["one two", "three"]) + XCTAssertEqual(Term.wordWrap("1 skipped protected or ignored", width: 40), ["1 skipped protected or ignored"]) + } + + func testWordWrapDropsSpaceRunAtALineBreak() { + XCTAssertEqual(Term.wordWrap("one two three", width: 7), ["one", "two", "three"]) + } + + func testWordWrapEmptyParagraphIsOneEmptyRow() { + XCTAssertEqual(Term.wordWrap("", width: 10), [""]) + } + + func testWordWrapHardBreaksLongWord() { + XCTAssertEqual(Term.wordWrap("ab abcdefg", width: 3), ["ab", "abc", "def", "g"]) + } } diff --git a/cli/Tests/TerminalUITests/TerminalSessionTests.swift b/cli/Tests/TerminalUITests/TerminalSessionTests.swift index 527ba3c..6c359e5 100644 --- a/cli/Tests/TerminalUITests/TerminalSessionTests.swift +++ b/cli/Tests/TerminalUITests/TerminalSessionTests.swift @@ -10,4 +10,16 @@ final class TerminalSessionTests: XCTestCase { XCTAssertTrue(TerminalSession.frame(lines: ["a", "b", "c", "d"], height: 3).contains("c")) XCTAssertFalse(TerminalSession.frame(lines: ["a", "b", "c", "d"], height: 3).contains("d")) } + + func testSimpleBytesDecodeToKeys() { + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x09), .tab) + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x0D), .enter) + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x0A), .enter) + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x20), .space) + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x7F), .backspace) + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x08), .backspace) + XCTAssertEqual(TerminalSession.key(forSimpleByte: 0x01), .unknown) + XCTAssertNil(TerminalSession.key(forSimpleByte: 0x1B)) + XCTAssertNil(TerminalSession.key(forSimpleByte: 0x61)) + } } diff --git a/cli/Tests/puremacTests/AnalyzeTests.swift b/cli/Tests/puremacTests/AnalyzeTests.swift index b5a4f83..1a07754 100644 --- a/cli/Tests/puremacTests/AnalyzeTests.swift +++ b/cli/Tests/puremacTests/AnalyzeTests.swift @@ -321,15 +321,6 @@ final class AnalyzeTests: XCTestCase { } } - func testFocusedPathWrappingPreservesEveryCharacter() { - let path = "/Users/example/a folder/with/a/very-long-name/file.bin" - let lines = Analyze.wrap(path, width: 11) - - XCTAssertGreaterThan(lines.count, 1) - XCTAssertEqual(lines.joined(), path) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) <= 11 }) - } - func testNarrowBrowserRenderStaysWithinViewport() { let path = "/Users/example/a folder/with/a/very-long-name/file.bin" let snapshot = snapshot(path: "/Users/example/a folder", children: [child(path, size: 8_192, isDir: false)]) diff --git a/cli/Tests/puremacTests/CaptureSupport.swift b/cli/Tests/puremacTests/CaptureSupport.swift new file mode 100644 index 0000000..ed23a9d --- /dev/null +++ b/cli/Tests/puremacTests/CaptureSupport.swift @@ -0,0 +1,40 @@ +import Foundation +import XCTest +@testable import puremac + +func capture(_ descriptor: Int32, _ body: () throws -> Void) throws -> String { + let url = FileManager.default.temporaryDirectory.appendingPathComponent("capture-\(UUID().uuidString)") + FileManager.default.createFile(atPath: url.path, contents: nil) + defer { try? FileManager.default.removeItem(at: url) } + let handle = try FileHandle(forWritingTo: url) + fflush(stdout) + let saved = dup(descriptor) + dup2(handle.fileDescriptor, descriptor) + defer { + fflush(stdout) + dup2(saved, descriptor) + close(saved) + } + try body() + fflush(stdout) + try handle.close() + return String(decoding: try Data(contentsOf: url), as: UTF8.self) +} + +func captureStdout(_ body: () throws -> Void) throws -> String { try capture(STDOUT_FILENO, body) } +func captureStderr(_ body: () throws -> Void) throws -> String { try capture(STDERR_FILENO, body) } + +extension InteractiveReviewModel { + static func reviewing(_ categories: [CategoryScan], selecting indices: [Int], query: String = "") -> InteractiveReviewModel { + var model = InteractiveReviewModel(categories: categories) + if !query.isEmpty { model.updateQuery(query) } + var position = 0 + for index in indices { + model.move(index - position) + position = index + model.toggleFocused() + } + XCTAssertTrue(model.beginReview()) + return model + } +} diff --git a/cli/Tests/puremacTests/CleanupFlowTests.swift b/cli/Tests/puremacTests/CleanupFlowTests.swift new file mode 100644 index 0000000..ceedc70 --- /dev/null +++ b/cli/Tests/puremacTests/CleanupFlowTests.swift @@ -0,0 +1,220 @@ +import ArgumentParser +import XCTest +@testable import puremac +import TerminalUI + +final class CleanupFlowTests: XCTestCase { + private let labels = CleanupFlow.Labels( + scanning: "Scanning Developer caches …", + empty: "No cleanup candidates found in readable locations.", + reviewTitle: "Choose items to clean", + noun: "item" + ) + + func testScanningScreenUsesPureMacTitleMessageAndCancelHint() { + let lines = CleanupFlow.scanningScreen(labels: labels, width: 60, height: 14).plainLines() + XCTAssertTrue(lines[0].hasPrefix("╭─ PureMac ")) + XCTAssertTrue(lines[1].contains("Scanning Developer caches …")) + XCTAssertTrue(lines.contains { $0.contains("Ctrl+C cancel") }) + } + + func testEmptyScreenShowsInfoDialogOverFadedScanningScreen() { + let buffer = CleanupFlow.emptyScreen(labels: labels, width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertTrue(lines.contains { $0.contains("Nothing to clean") }) + XCTAssertTrue(lines.contains { $0.contains("No cleanup candidates found in readable locations.") }) + XCTAssertTrue(lines.contains { $0.contains("› OK ‹") }) + XCTAssertTrue(lines.contains { $0.contains("Scanning Developer caches …") }) + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + XCTAssertTrue(buffer.lines(colors: true).joined().contains("\u{1B}[7m› OK ‹")) + } + + func testEmptyScreenClosesOnEnterEscapeAndQOnly() { + XCTAssertTrue(CleanupFlow.closesInfoDialog(.enter)) + XCTAssertTrue(CleanupFlow.closesInfoDialog(.escape)) + XCTAssertTrue(CleanupFlow.closesInfoDialog(.character("q"))) + XCTAssertTrue(CleanupFlow.closesInfoDialog(.character("Q"))) + XCTAssertFalse(CleanupFlow.closesInfoDialog(.space)) + XCTAssertFalse(CleanupFlow.closesInfoDialog(.character("y"))) + XCTAssertFalse(CleanupFlow.closesInfoDialog(.up)) + } + + func testRemovingScreenShowsStatusDialogWithoutButtonsOverFadedFinalReview() { + let buffer = CleanupFlow.removingScreen(review: review(), labels: labels, width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertTrue(lines.contains { $0.contains("Removing 2 items…") }) + XCTAssertTrue(lines.contains { $0.contains("3 KB") }) + let dialog = CleanupFlow.removingDialog(count: 2, total: 3_000, noun: "item") + XCTAssertTrue(dialog.buttons.isEmpty) + XCTAssertNil(dialog.focusedButton) + XCTAssertTrue(lines.contains { $0.contains("╭─ Final review ") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) + XCTAssertFalse(lines.contains { $0.contains("/tmp/third") }) + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + let frame = CleanupFlow.removingDialog(count: 2, total: 3_000, noun: "item").frame(in: buffer.area) + XCTAssertEqual(buffer[frame.x, frame.y].style, TextStyle(color: .yellow)) + XCTAssertEqual(buffer[frame.x + 3, frame.y].style, TextStyle(color: .yellow, bold: true)) + } + + func testRemovingTitleUsesSingularForOneItem() { + XCTAssertEqual(CleanupFlow.removingDialog(count: 1, total: 1_000, noun: "item").title, "Removing 1 item…") + XCTAssertEqual(CleanupFlow.removingDialog(count: 1, total: 1_000, noun: "artifact").title, "Removing 1 artifact…") + XCTAssertEqual(CleanupFlow.removingDialog(count: 0, total: 0, noun: "item").title, "Removing 0 items…") + XCTAssertEqual(CleanupFlow.removingDialog(count: 2, total: 1_000, noun: "artifact").title, "Removing 2 artifacts…") + } + + func testRemovingDialogUsesTheNoun() { + let lines = CleanupFlow.removingScreen( + review: review(), + labels: CleanupFlow.Labels(scanning: "s", empty: "e", reviewTitle: "t", noun: "artifact"), + width: 80, + height: 24 + ).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Removing 2 artifacts…") }) + } + + func testResultScreenShowsSummaryRowsAndFocusedDoneButton() { + let outcome = CleanOutcome(removed: 2, freedBytes: 1_500, skipped: [], failed: []) + let buffer = CleanupFlow.resultScreen(outcome: outcome, review: review(), labels: labels, width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertTrue(lines.contains { $0.contains("Cleanup complete") }) + XCTAssertTrue(lines.contains { $0.contains("1.5 KB removed across 2 items") }) + XCTAssertFalse(lines.contains { $0.contains("skipped") }) + XCTAssertFalse(lines.contains { $0.contains("failed") }) + XCTAssertTrue(lines.contains { $0.contains("› Done ‹") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) + let colored = buffer.lines(colors: true).joined() + XCTAssertTrue(colored.contains("\u{1B}[1;32mCleanup complete")) + XCTAssertTrue(colored.contains("\u{1B}[7m› Done ‹")) + } + + func testResultDialogSingularItemAndSkippedRow() { + let outcome = CleanOutcome(removed: 1, freedBytes: 1_000, skipped: [(path: "/tmp/a", reason: "symlink")], failed: []) + let lines = CleanupFlow.resultScreen(outcome: outcome, review: review(), labels: labels, width: 80, height: 24) + XCTAssertTrue(lines.plainLines().contains { $0.contains("1 KB removed across 1 item ") }) + XCTAssertTrue(lines.plainLines().contains { $0.contains("1 skipped protected or ignored") }) + XCTAssertTrue(lines.lines(colors: true).joined().contains("\u{1B}[33m1 skipped protected or ignored")) + } + + func testResultDialogListsFailureCountAndUpToThreePaths() { + let failures = (1...4).map { (path: "/tmp/fail\($0)", error: "denied") } + let outcome = CleanOutcome(removed: 0, freedBytes: 0, skipped: [], failed: failures) + let buffer = CleanupFlow.resultScreen(outcome: outcome, review: review(), labels: labels, width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertTrue(lines.contains { $0.contains("4 failed") }) + XCTAssertTrue(lines.contains { $0.contains("! /tmp/fail1") }) + XCTAssertTrue(lines.contains { $0.contains("! /tmp/fail3") }) + XCTAssertFalse(lines.contains { $0.contains("fail4") }) + let colored = buffer.lines(colors: true).joined() + XCTAssertTrue(colored.contains("\u{1B}[31m4 failed")) + XCTAssertTrue(colored.contains("\u{1B}[31m! /tmp/fail1")) + } + + func testResultScreenFitsMinimumSize() { + let failures = (1...4).map { (path: "/tmp/fail\($0)", error: "denied") } + let outcome = CleanOutcome(removed: 3, freedBytes: 5_000, skipped: [(path: "/tmp/a", reason: "x")], failed: failures) + let lines = CleanupFlow.resultScreen(outcome: outcome, review: review(), labels: labels, width: 40, height: 12) + .plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines.contains { $0.contains("› Done ‹") }) + } + + func testOutcomeTextIsSharedWithTheTerminalSummary() { + let outcome = CleanOutcome(removed: 2, freedBytes: 1_500, skipped: [(path: "/a", reason: "x")], failed: [(path: "/b", error: "y")]) + XCTAssertEqual(Render.removedDetail(outcome), " removed across 2 items") + XCTAssertEqual(Render.removedDetail(CleanOutcome(removed: 1)), " removed across 1 item") + XCTAssertEqual(Render.skippedLabel(outcome), "1 skipped") + XCTAssertEqual(Render.skippedNote, " protected or ignored") + XCTAssertEqual(Render.failedLabel(outcome), "1 failed") + } + + func testFinishPrintsTheCopyForEachResultAndKeepsExitStatus() throws { + XCTAssertEqual( + try captureStdout { try CleanupFlow.finish(.nothingFound, labels: labels) }, + "No cleanup candidates found in readable locations.\n" + ) + XCTAssertEqual( + try captureStdout { try CleanupFlow.finish(.cancelled, labels: labels) }, + "Cancelled. Nothing removed.\n" + ) + XCTAssertEqual( + try captureStdout { try CleanupFlow.finish(.finished(CleanOutcome(removed: 1, freedBytes: 10)), labels: labels) }, + "\nCleanup complete\n10 bytes removed across 1 item\n\n" + ) + let failed = CleanOutcome(failed: [(path: "/x", error: "e")]) + var thrown: Error? + let printed = try captureStdout { + do { try CleanupFlow.finish(.finished(failed), labels: labels) } catch { thrown = error } + } + XCTAssertEqual(thrown as? ExitCode, ExitCode.failure) + XCTAssertTrue(printed.contains("1 failed")) + let skipped = CleanOutcome(skipped: [(path: "/x", reason: "r")]) + var skippedError: Error? + let skippedPrinted = try captureStdout { + do { try CleanupFlow.finish(.finished(skipped), labels: labels) } catch { skippedError = error } + } + XCTAssertEqual(skippedError as? ExitCode, ExitCode.failure) + XCTAssertTrue(skippedPrinted.contains("1 skipped protected or ignored")) + } + + func testLongFailurePathsStayOnOneRowEach() { + let long = "/Users/someone/Library/Developer/Xcode/DerivedData/" + String(repeating: "very-long-name/", count: 6) + let failures = (1...3).map { (path: long + "f\($0)", error: "denied") } + let outcome = CleanOutcome(removed: 0, freedBytes: 0, skipped: [], failed: failures) + for (width, height) in [(40, 12), (80, 24)] { + let buffer = CleanupFlow.resultScreen(outcome: outcome, review: review(), labels: labels, width: width, height: height) + let lines = buffer.plainLines() + XCTAssertEqual(lines.filter { $0.contains("! ") }.count, 3, "\(width)x\(height)") + XCTAssertFalse(lines.contains { $0.contains("!") && !$0.contains("! ") }, "\(width)x\(height)") + XCTAssertTrue(lines.contains { $0.contains("› Done ‹") }) + } + } + + func testTooSmallInfoScreensShowTheKeyThatClosesThem() { + let empty = CleanupFlow.emptyScreen(labels: labels, width: 30, height: 8).plainLines() + XCTAssertTrue(empty.contains { $0.contains("Enter close") }) + XCTAssertFalse(empty.contains { $0.contains("Ctrl+C") }) + let outcome = CleanOutcome(removed: 1, freedBytes: 1_000) + let result = CleanupFlow.resultScreen(outcome: outcome, review: review(), labels: labels, width: 30, height: 8).plainLines() + XCTAssertTrue(result.contains { $0.contains("Enter close") }) + XCTAssertFalse(result.contains { $0.contains("cancel") }) + } + + func testTooSmallRemovingScreenMakesNoCancelPromise() { + let lines = CleanupFlow.removingScreen(review: review(), labels: labels, width: 30, height: 8).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Removing") }) + XCTAssertFalse(lines.contains { $0.contains("Esc") || $0.contains("cancel") }) + } + + func testBackgroundKeepsTheReviewFilter() { + let model = InteractiveReviewModel.reviewing(selection(), selecting: [0], query: "first") + let lines = CleanupFlow.resultScreen( + outcome: CleanOutcome(removed: 1, freedBytes: 1_000), review: model, labels: labels, width: 80, height: 24 + ).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Filter first") }) + } + + private func review() -> InteractiveReviewModel { + .reviewing(selection(), selecting: [0, 1]) + } + + private func selection() -> [CategoryScan] { + [ + CategoryScan( + id: "dev", + title: "Developer", + groups: [ + ToolGroup( + tool: "Build caches", + items: [ + ScanItem(path: "/tmp/first", sizeBytes: 1_000, modified: nil, selected: true), + ScanItem(path: "/tmp/second", sizeBytes: 2_000, modified: nil, selected: true), + ScanItem(path: "/tmp/third", sizeBytes: 3_000, modified: nil, selected: false) + ] + ) + ] + ) + ] + } +} diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index 058405c..c5b0d06 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -252,7 +252,7 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(lines.count, 12) XCTAssertTrue(lines.contains { $0.contains("Enter confirm") }) XCTAssertTrue(lines.contains { $0.contains("q cancel") }) - XCTAssertTrue(lines.contains { $0.contains("Command confirmation follows") }) + XCTAssertFalse(lines.contains { $0.contains("Command confirmation follows") }) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) } @@ -269,8 +269,7 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) XCTAssertFalse(lines.contains { $0.contains("/tmp/second") }) XCTAssertTrue(lines.contains { $0.contains("↑↓ scroll ←→ path Enter confirm Esc edit q cancel") }) - let confirmation = lines.firstIndex { $0.contains("Command confirmation follows") }! - XCTAssertEqual(buffer[2, confirmation].style, TextStyle(color: .yellow)) + XCTAssertFalse(lines.contains { $0.contains("Command confirmation follows") }) XCTAssertFalse(lines.contains { $0.contains("Space toggle") }) } @@ -419,6 +418,258 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(Term.displayWidth(Render.sizeCol(1_024)), Render.sizeColumnWidth) } + func testConfirmationOpensOnlyFromFinalReviewWithCancelFocused() { + var selecting = InteractiveReviewModel(categories: fixtureCategories()) + selecting.selectAllMatching() + XCTAssertFalse(selecting.beginConfirmation()) + XCTAssertFalse(selecting.isConfirming) + + var model = reviewingModel() + XCTAssertFalse(model.isConfirming) + XCTAssertTrue(model.beginConfirmation()) + XCTAssertTrue(model.isConfirming) + XCTAssertEqual(model.confirmation, .cancel) + } + + func testConfirmationFocusMovesWithClamping() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + model.moveConfirmationFocus(-1) + XCTAssertEqual(model.confirmation, .cancel) + model.moveConfirmationFocus(1) + XCTAssertEqual(model.confirmation, .remove) + model.moveConfirmationFocus(1) + XCTAssertEqual(model.confirmation, .remove) + model.moveConfirmationFocus(-1) + XCTAssertEqual(model.confirmation, .cancel) + } + + func testCancelConfirmationReturnsToFinalReviewAndReopensOnCancel() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + model.moveConfirmationFocus(1) + model.cancelConfirmation() + XCTAssertFalse(model.isConfirming) + XCTAssertTrue(model.isReviewing) + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.confirmation, .cancel) + } + + func testEnterRightAfterOpeningOnlyClosesTheDialog() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(.enter), .handled) + XCTAssertFalse(model.isConfirming) + XCTAssertTrue(model.isReviewing) + } + + func testEnterOnRemoveConfirms() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(.right), .handled) + XCTAssertEqual(model.handleConfirmationKey(.enter), .remove) + } + + func testTabAndArrowsMoveConfirmationFocus() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(.tab), .handled) + XCTAssertEqual(model.confirmation, .remove) + XCTAssertEqual(model.handleConfirmationKey(.left), .handled) + XCTAssertEqual(model.confirmation, .cancel) + XCTAssertEqual(model.handleConfirmationKey(.right), .handled) + XCTAssertEqual(model.confirmation, .remove) + } + + func testYConfirmsInOpenDialog() { + for key in [TerminalKey.character("y"), .character("Y")] { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(key), .remove) + } + } + + func testNAndEscapeCloseTheDialogOnly() { + for key in [TerminalKey.character("n"), .character("N"), .escape] { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(key), .handled) + XCTAssertFalse(model.isConfirming) + XCTAssertTrue(model.isReviewing) + } + } + + func testQCancelsTheWholeFlowFromTheDialog() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(.character("q")), .quit) + } + + func testOtherKeysDoNothingWhileDialogIsOpen() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + let before = model.selectedAddresses.count + let keys: [TerminalKey] = [ + .up, .down, .pageUp, .pageDown, .home, .end, .space, .backspace, .delete, .unknown, + .character("a"), .character("/"), .character("x") + ] + for key in keys { + XCTAssertEqual(model.handleConfirmationKey(key), .handled) + XCTAssertTrue(model.isConfirming) + XCTAssertEqual(model.confirmation, .cancel) + } + XCTAssertEqual(model.selectedAddresses.count, before) + XCTAssertTrue(model.isReviewing) + } + + func testConfirmationKeysAreIgnoredWhenDialogIsClosed() { + var model = reviewingModel() + XCTAssertEqual(model.handleConfirmationKey(.character("y")), .passthrough) + XCTAssertEqual(model.handleConfirmationKey(.enter), .passthrough) + XCTAssertEqual(model.handleConfirmationKey(.character("q")), .passthrough) + } + + func testTabCyclesBetweenButtons() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.handleConfirmationKey(.tab), .handled) + XCTAssertEqual(model.confirmation, .remove) + XCTAssertEqual(model.handleConfirmationKey(.tab), .handled) + XCTAssertEqual(model.confirmation, .cancel) + } + + func testConfirmationTitleUsesSingularForOneItem() { + for (count, noun, title) in [(1, "item", "Remove 1 item?"), (1, "artifact", "Remove 1 artifact?"), + (0, "item", "Remove 0 items?"), (2, "artifact", "Remove 2 artifacts?")] { + XCTAssertEqual( + InteractiveReview.confirmationDialog(count: count, total: 1_000, noun: noun, focus: .cancel).title, + title + ) + } + } + + func testConfirmationDialogIsDrawnOverFadedFinalReview() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + let buffer = renderReview(model, width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertTrue(lines.contains { $0.contains("Remove 2 items?") }) + XCTAssertTrue(lines.contains { $0.contains("3 KB will be permanently deleted.") }) + XCTAssertTrue(lines.contains { $0.contains("This cannot be undone.") }) + XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Remove ]") }) + XCTAssertTrue(lines.contains { $0.contains("←→ choose Enter select Y remove Esc back") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/second") }) + XCTAssertFalse(lines.contains { $0.contains("/tmp/third") }) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 80 }) + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + XCTAssertEqual(buffer[3, 0].style, TextStyle(dim: true)) + } + + func testConfirmationDialogUsesYellowTitleAndBorder() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + let buffer = renderReview(model, width: 80, height: 24) + let frame = InteractiveReview.confirmationDialog(count: 2, total: 3_000, noun: "item", focus: .cancel) + .frame(in: buffer.area) + XCTAssertEqual(buffer[frame.x, frame.y].style, TextStyle(color: .yellow)) + XCTAssertEqual(buffer[frame.x + 3, frame.y].style, TextStyle(color: .yellow, bold: true)) + } + + func testConfirmationDialogFocusStyles() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + let cancelFocused = renderReview(model, width: 80, height: 24).lines(colors: true).joined() + XCTAssertTrue(cancelFocused.contains("\u{1B}[7m› Cancel ‹")) + XCTAssertTrue(cancelFocused.contains("\u{1B}[31m[ Remove ]")) + + model.moveConfirmationFocus(1) + let removeFocused = renderReview(model, width: 80, height: 24).lines(colors: true).joined() + XCTAssertTrue(removeFocused.contains("\u{1B}[7;31m› Remove ‹")) + XCTAssertFalse(removeFocused.contains("\u{1B}[7m› Cancel ‹")) + } + + func testConfirmationDialogUsesTheGivenNoun() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + let lines = InteractiveReview.render( + model: model, title: "Choose project artifacts", noun: "artifact", width: 80, height: 24 + ).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Remove 2 artifacts?") }) + } + + func testConfirmationDialogFitsMinimumSize() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + let lines = renderReview(model, width: 40, height: 12).plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Remove ]") }) + XCTAssertTrue(lines.contains { $0.contains("Y remove") }) + } + + func testFinalReviewWithoutDialogIsNotFaded() { + let buffer = renderReview(reviewingModel(), width: 80, height: 24) + XCTAssertEqual(buffer[0, 0].style, TextStyle(color: .yellow)) + XCTAssertFalse(buffer.plainLines().contains { $0.contains("Cancel") }) + } + + func testHomeMenuWaitsForReturnOnlyAfterEntriesOutsideCleanup() { + XCTAssertFalse(HomeMenu.waitsForReturn(afterChoice: 0)) + XCTAssertFalse(HomeMenu.waitsForReturn(afterChoice: 1)) + for choice in 2...5 { + XCTAssertTrue(HomeMenu.waitsForReturn(afterChoice: choice)) + } + } + + func testEnterInFinalReviewOpensDialogAndNeverReturnsTheSelection() { + var model = reviewingModel() + XCTAssertEqual(model.routeKey(.enter), .handled) + XCTAssertTrue(model.isConfirming) + XCTAssertEqual(model.confirmation, .cancel) + XCTAssertEqual(model.routeKey(.enter), .handled) + XCTAssertFalse(model.isConfirming) + } + + func testRouteKeyReturnsRemoveOnlyFromTheOpenDialog() { + var model = reviewingModel() + XCTAssertEqual(model.routeKey(.character("y")), .passthrough) + _ = model.routeKey(.enter) + XCTAssertEqual(model.routeKey(.character("y")), .remove) + XCTAssertEqual(model.routeKey(.character("q")), .quit) + XCTAssertEqual(model.routeKey(.space), .handled) + } + + func testRouteKeyPassesEnterThroughOutsideTheFinalReview() { + var model = InteractiveReviewModel(categories: fixtureCategories()) + XCTAssertEqual(model.routeKey(.enter), .passthrough) + XCTAssertFalse(model.isConfirming) + } + + func testTooSmallScreenLetsOnlyCloseAndCancelKeysReachTheDialog() { + var model = reviewingModel() + XCTAssertTrue(model.beginConfirmation()) + for key in [TerminalKey.escape, .character("n"), .character("N"), .character("q"), .enter] { + XCTAssertTrue(model.acceptsKey(key, tooSmall: true), "\(key)") + } + for key in [TerminalKey.character("y"), .character("Y"), .tab, .right, .space, .left] { + XCTAssertFalse(model.acceptsKey(key, tooSmall: true), "\(key)") + } + _ = model.handleConfirmationKey(.right) + XCTAssertFalse(model.acceptsKey(.enter, tooSmall: true)) + XCTAssertTrue(model.acceptsKey(.character("y"), tooSmall: false)) + } + + func testTooSmallRuleDoesNotAffectOtherStates() { + let model = reviewingModel() + XCTAssertTrue(model.acceptsKey(.enter, tooSmall: true)) + XCTAssertTrue(model.acceptsKey(.down, tooSmall: true)) + } + + private func reviewingModel() -> InteractiveReviewModel { + .reviewing(fixtureCategories(), selecting: [0, 1]) + } + private func menuOptions(_ count: Int) -> [(title: String, detail: String)] { (1...count).map { (title: "Tool \($0)", detail: "Description \($0)") } } @@ -440,7 +691,7 @@ final class InteractiveScreensTests: XCTestCase { } private func renderReview(_ model: InteractiveReviewModel, width: Int, height: Int) -> Buffer { - InteractiveReview.render(model: model, title: "Review removable files", width: width, height: height) + InteractiveReview.render(model: model, title: "Review removable files", noun: "item", width: width, height: height) } private func manyItemsCategories(_ count: Int) -> [CategoryScan] { diff --git a/cli/Tests/puremacTests/ScanProgressTests.swift b/cli/Tests/puremacTests/ScanProgressTests.swift new file mode 100644 index 0000000..4e0a7c2 --- /dev/null +++ b/cli/Tests/puremacTests/ScanProgressTests.swift @@ -0,0 +1,23 @@ +import Foundation +import XCTest +@testable import puremac + +final class ScanProgressTests: XCTestCase { + func testFullscreenCleanupWritesNoScanProgress() { + XCTAssertEqual(ScanProgress.forMode(.fullscreen), .silent) + for mode in [CleanupCommandMode.plain, .forced, .reportOnly] { + XCTAssertEqual(ScanProgress.forMode(mode), .stderr) + } + } + + func testSilentScanWritesNothingToStderrAndDefaultKeepsTheProgressLine() throws { + let silent = try captureStderr { _ = CategoryScanner.scan(categoryID: "none", title: "None", ignore: ignore(), progress: .silent) } + XCTAssertEqual(silent, "") + let verbose = try captureStderr { _ = CategoryScanner.scan(categoryID: "none", title: "None", ignore: ignore()) } + XCTAssertTrue(verbose.hasPrefix(" scanning None…\r")) + } + + private func ignore() -> IgnoreStore { + try! IgnoreStore(fileURL: FileManager.default.temporaryDirectory.appendingPathComponent("scan-progress-\(UUID().uuidString)")) + } +} diff --git a/cli/Tests/puremacTests/StatusScreenTests.swift b/cli/Tests/puremacTests/StatusScreenTests.swift new file mode 100644 index 0000000..05e9fdd --- /dev/null +++ b/cli/Tests/puremacTests/StatusScreenTests.swift @@ -0,0 +1,67 @@ +import XCTest +@testable import puremac +import TerminalUI + +final class StatusScreenTests: XCTestCase { + private let hint = KeyHint("Ctrl+C", "cancel") + + func testRendersWindowMessageDetailDividerAndHint() { + let buffer = StatusScreen.render( + title: "PureMac", + message: "Working...", + detail: "/Users/example/" + String(repeating: "a", count: 60), + hint: hint, + width: 40, + height: 12 + ) + let lines = buffer.plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines[0].hasPrefix("╭─ PureMac ")) + XCTAssertTrue(lines[1].contains("Working...")) + XCTAssertTrue(lines[2].contains("…")) + XCTAssertTrue(lines.contains { $0.hasPrefix("├") && $0.hasSuffix("┤") }) + XCTAssertTrue(lines.contains { $0.contains("Ctrl+C cancel") }) + XCTAssertTrue(buffer[2, 1].style.dim) + } + + func testLongMessageEndsWithEllipsis() { + let message = "Scanning ~/Projects, ~/Code, ~/dev, ~/GitHub, ~/Workspace …" + let lines = StatusScreen.render( + title: "PureMac", message: message, detail: nil, hint: hint, width: 40, height: 12 + ).plainLines() + XCTAssertTrue(lines[1].contains("… │"), lines[1]) + XCTAssertFalse(lines[1].contains("Workspace")) + } + + func testDetailRowIsEmptyWithoutDetail() { + let lines = StatusScreen.render( + title: "PureMac", message: "Working...", detail: nil, hint: hint, width: 40, height: 12 + ).plainLines() + XCTAssertEqual(lines[2], "│" + String(repeating: " ", count: 38) + "│") + } + + func testBelowMinimumUsesTooSmallScreenWithHintAsExit() { + XCTAssertEqual( + StatusScreen.render(title: "PureMac", message: "x", detail: nil, hint: hint, width: 39, height: 11), + TooSmallScreen.render(title: "PureMac", exitHint: "Ctrl+C cancel", width: 39, height: 11) + ) + } + + func testOverlayFadesBackgroundAndCentersDialog() { + let background = StatusScreen.render( + title: "PureMac", message: "Working...", detail: nil, hint: hint, width: 60, height: 14 + ) + let dialog = Dialog(title: "Done", message: [Span("All good.")]) + let result = StatusScreen.overlay(dialog, on: background) + XCTAssertEqual(result[0, 0].style, TextStyle(dim: true)) + XCTAssertTrue(result.plainLines().contains { $0.contains("All good.") }) + XCTAssertTrue(result.plainLines().contains { $0.contains("Ctrl+C cancel") }) + } + + func testOverlayLeavesTooSmallBackgroundUntouched() { + let background = TooSmallScreen.render(title: "PureMac", exitHint: "Ctrl+C cancel", width: 30, height: 8) + let result = StatusScreen.overlay(Dialog(title: "Done", message: [Span("All good.")]), on: background) + XCTAssertEqual(result, background) + } +} From 5e018d689a97aa536af440cf91d37fb25e57ed3d Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 12:21:30 +0000 Subject: [PATCH 04/21] feat(cli): confirm removal directly from the selection screen with a minimal dialog --- cli/README.md | 8 +- cli/Sources/TerminalUI/Dialog.swift | 68 +++--- cli/Sources/TerminalUI/KeyHints.swift | 2 +- cli/Sources/TerminalUI/Term.swift | 4 + cli/Sources/puremac/Core/CleanupFlow.swift | 6 +- .../puremac/Core/InteractiveReview.swift | 127 ++++------- cli/Tests/TerminalUITests/DialogTests.swift | 121 ++++++++-- cli/Tests/TerminalUITests/TermTests.swift | 6 + cli/Tests/puremacTests/CaptureSupport.swift | 4 +- cli/Tests/puremacTests/CleanupFlowTests.swift | 13 +- .../InteractiveScreensTests.swift | 206 ++++++++++-------- 11 files changed, 331 insertions(+), 234 deletions(-) diff --git a/cli/README.md b/cli/README.md index 39de8e5..185cf40 100644 --- a/cli/README.md +++ b/cli/README.md @@ -36,7 +36,7 @@ puremac purge ~/Projects puremac analyze ~/Projects ``` -Cleanup opens a selection screen. Nothing is selected when the interactive review begins. Move through the list, choose individual paths, and check the running size total. Press Return to review the selection, then confirm permanent deletion in a separate dialog. +Cleanup opens a selection screen. Nothing is selected when the interactive review begins. Move through the list, choose individual paths, and check the running size total. Press Return to remove the selection; a confirmation dialog opens first. | Key | Action | |---|---| @@ -44,10 +44,10 @@ Cleanup opens a selection screen. Nothing is selected when the interactive revie | Space | Toggle the focused item | | A / N | Select matching results / clear the selection | | / | Search the results | -| Return | Review the selection | +| Return | Remove the selection after confirmation | | Esc / Q | Cancel | -Use Left and Right to scroll a long focused path. The final review lists every selected item. Return opens the confirmation dialog with Cancel selected; choose Remove or press Y to delete, Esc to go back. Selection is by path, including recent project artifacts that earlier versions only displayed. +Use Left and Right to scroll a long focused path. The confirmation dialog opens with Cancel selected and shows the total size, plus how many selected items the search hides. Choose Remove or press Y to delete, Esc to go back. Selection is by path, including recent project artifacts that earlier versions only displayed. Prefer an ordinary scrolling terminal? Use `--plain` for numbered selection and a text review that prints every selected path in full: @@ -115,7 +115,7 @@ The CLI has its own scan engine and safety checks. Its coverage is separate from ## Cleanup boundaries -- Cleanup is permanent. The selection review lists the exact paths before confirmation. +- Cleanup is permanent. The selection screen marks every selected path, and `--plain` prints them all in full before confirmation. - Critical filesystem roots, credential/configuration roots, and recognized cloud-provider state are protected. - Symlink checks and ignore-list checks run again before deletion. - A path containing an ignored descendant is also protected from removal. diff --git a/cli/Sources/TerminalUI/Dialog.swift b/cli/Sources/TerminalUI/Dialog.swift index 722b64c..e221dfd 100644 --- a/cli/Sources/TerminalUI/Dialog.swift +++ b/cli/Sources/TerminalUI/Dialog.swift @@ -50,25 +50,33 @@ public struct Dialog { buffer.clear(frame) let content = Window(title: title, borderStyle: borderStyle, titleStyle: titleStyle) .render(in: frame, buffer: &buffer) - var row = content.y + var row = content.y + layout.blankAboveMessage for message in layout.messageRows { - buffer.write([message], x: content.x, y: row, maxWidth: content.width) + renderCentered([message], in: content, row: row, buffer: &buffer) row += 1 } - row += layout.blankRows + row += layout.blankBelowMessage if !buttons.isEmpty { renderButtons(in: content, row: row, buffer: &buffer) row += 1 } - hints?.render(in: Rect(x: content.x, y: row, width: content.width, height: layout.hintRows), buffer: &buffer) + row += layout.blankBelowButtons + for spans in hints?.rows(width: content.width) ?? [] { + renderCentered(spans, in: content, row: row, buffer: &buffer) + row += 1 + } } private struct Layout { var messageRows: [Span] - var blankRows: Int + var blankAboveMessage = 0 + var blankBelowMessage = 0 + var blankBelowButtons = 0 var hintRows: Int var buttonRows: Int - var height: Int { messageRows.count + blankRows + buttonRows + hintRows } + var height: Int { + messageRows.count + blankAboveMessage + blankBelowMessage + blankBelowButtons + buttonRows + hintRows + } } private func placement(in area: Rect) -> (frame: Rect, layout: Layout) { @@ -85,22 +93,23 @@ public struct Dialog { return (frame, layout) } - private var buttonLabels: [String] { - buttons.indices.map { index in - let title = Term.sanitize(buttons[index].title) - return index == focusedButton ? "› \(title) ‹" : "[ \(title) ]" + private var buttonSpans: [Span] { + var spans: [Span] = [] + for (index, button) in buttons.enumerated() { + if index > 0 { spans.append(Span(" ")) } + let title = Term.sanitize(button.title) + let focused = index == focusedButton + let style = TextStyle(color: button.role == .destructive ? .red : nil, inverse: focused) + spans.append(Span(focused ? "› \(title) ‹" : "[ \(title) ]", style)) } - } - - private var buttonsWidth: Int { - guard !buttons.isEmpty else { return 0 } - return buttonLabels.reduce(0) { $0 + Term.displayWidth($1) } + 2 * (buttons.count - 1) + return spans } private func contentWidth(maxWidth: Int) -> Int { let titleWidth = Term.displayWidth(Term.sanitize(title)) + 2 let messageWidth = message.map { Term.displayWidth(Term.sanitize($0.text)) }.max() ?? 0 - let hintWidth = hints?.rows(width: .max).first?.reduce(0) { $0 + Term.displayWidth($1.text) } ?? 0 + let buttonsWidth = Term.displayWidth(buttonSpans) + let hintWidth = hints?.rows(width: .max).first.map(Term.displayWidth) ?? 0 return max(1, min(max(titleWidth, messageWidth, buttonsWidth, hintWidth), maxWidth)) } @@ -111,17 +120,26 @@ public struct Dialog { let wrapped = message.flatMap { paragraph in Term.wordWrap(paragraph.text, width: contentWidth).map { Span($0, paragraph.style) } } - let blankRows = tailRows > 0 && wrapped.count + 1 + tailRows <= maxRows ? 1 : 0 - let messageRows = Array(wrapped.prefix(max(0, maxRows - blankRows - tailRows))) - return Layout(messageRows: messageRows, blankRows: blankRows, hintRows: hintRows, buttonRows: buttonRows) + var layout = Layout(messageRows: wrapped, hintRows: hintRows, buttonRows: buttonRows) + if !wrapped.isEmpty { + layout.blankAboveMessage = 1 + layout.blankBelowMessage = tailRows > 0 ? 1 : 0 + } + layout.blankBelowButtons = buttonRows > 0 && hintRows > 0 ? 1 : 0 + if layout.height > maxRows { layout.blankBelowButtons = 0 } + if layout.height > maxRows { layout.blankBelowMessage = 0 } + if layout.height > maxRows { layout.blankAboveMessage = 0 } + layout.messageRows = Array(wrapped.prefix(max(0, maxRows - layout.height + wrapped.count))) + return layout + } + + private func renderCentered(_ spans: [Span], in content: Rect, row: Int, buffer: inout Buffer) { + let width = Term.displayWidth(spans) + let column = content.x + max(0, content.width - width) / 2 + buffer.write(spans, x: column, y: row, maxWidth: content.x + content.width - column) } private func renderButtons(in content: Rect, row: Int, buffer: inout Buffer) { - var column = max(content.x, content.x + content.width - buttonsWidth) - for (index, label) in buttonLabels.enumerated() { - let focused = index == focusedButton - let style = TextStyle(color: buttons[index].role == .destructive ? .red : nil, inverse: focused) - column += buffer.write(label, x: column, y: row, style: style, maxWidth: content.x + content.width - column) + 2 - } + renderCentered(buttonSpans, in: content, row: row, buffer: &buffer) } } diff --git a/cli/Sources/TerminalUI/KeyHints.swift b/cli/Sources/TerminalUI/KeyHints.swift index 7512bbc..c45151f 100644 --- a/cli/Sources/TerminalUI/KeyHints.swift +++ b/cli/Sources/TerminalUI/KeyHints.swift @@ -21,7 +21,7 @@ public struct KeyHints { var used = 0 for hint in hints { let spans = [Span(hint.key), Span(" " + hint.action, TextStyle(dim: true))] - let hintWidth = spans.reduce(0) { $0 + Term.displayWidth($1.text) } + let hintWidth = Term.displayWidth(spans) let needed = current.isEmpty ? hintWidth : used + separator.count + hintWidth if !current.isEmpty, needed > width { rows.append(current) diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 15e20eb..0bd9156 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -68,6 +68,10 @@ public enum Term { return output } + public static func displayWidth(_ spans: [Span]) -> Int { + spans.reduce(0) { $0 + displayWidth(sanitize($1.text)) } + } + public static func displayWidth(_ string: String) -> Int { _ = localeConfigured var width = 0 diff --git a/cli/Sources/puremac/Core/CleanupFlow.swift b/cli/Sources/puremac/Core/CleanupFlow.swift index 0339943..4a60f9c 100644 --- a/cli/Sources/puremac/Core/CleanupFlow.swift +++ b/cli/Sources/puremac/Core/CleanupFlow.swift @@ -92,7 +92,7 @@ enum CleanupFlow { let dialog = removingDialog(count: review.selectedCount, total: review.selectedBytes, noun: labels.noun) return StatusScreen.overlay( dialog, - on: finalReview(review, labels: labels, width: width, height: height), + on: selectionScreen(review, labels: labels, width: width, height: height), tooSmallExitHint: "Removing…" ) } @@ -100,7 +100,7 @@ enum CleanupFlow { static func resultScreen(outcome: CleanOutcome, review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { StatusScreen.overlay( resultDialog(outcome, area: Rect(x: 0, y: 0, width: width, height: height)), - on: finalReview(review, labels: labels, width: width, height: height), + on: selectionScreen(review, labels: labels, width: width, height: height), tooSmallExitHint: closeHint ) } @@ -142,7 +142,7 @@ enum CleanupFlow { ) } - private static func finalReview(_ review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { + private static func selectionScreen(_ review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { InteractiveReview.render( model: review, title: labels.reviewTitle, diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index 1f53c90..12b5a0c 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -25,11 +25,9 @@ struct InteractiveReviewModel { var categories: [CategoryScan] var query = "" var isSearching = false - var isReviewing = false var status = "" var pathOffset = 0 private(set) var focus = 0 - private(set) var reviewFocus = 0 private(set) var confirmation: ConfirmationButton? var isConfirming: Bool { confirmation != nil } @@ -91,44 +89,36 @@ struct InteractiveReviewModel { categories.reduce(Int64(0)) { $0 + $1.allBytes } } + var hiddenSelectedCount: Int { + let shown = Set(matchingAddresses) + return selectedAddresses.filter { !shown.contains($0) }.count + } + var focusedAddress: ReviewAddress? { - let addresses = isReviewing ? selectedAddresses : matchingAddresses - let index = isReviewing ? reviewFocus : focus - guard addresses.indices.contains(index) else { return nil } - return addresses[index] + let addresses = matchingAddresses + guard addresses.indices.contains(focus) else { return nil } + return addresses[focus] } mutating func move(_ delta: Int) { - let count = isReviewing ? selectedAddresses.count : matchingAddresses.count + let count = matchingAddresses.count guard count > 0 else { return } - if isReviewing { - reviewFocus = min(count - 1, max(0, reviewFocus + delta)) - } else { - focus = min(count - 1, max(0, focus + delta)) - } + focus = min(count - 1, max(0, focus + delta)) pathOffset = 0 } mutating func moveToStart() { - if isReviewing { - reviewFocus = 0 - } else { - focus = 0 - } + focus = 0 pathOffset = 0 } mutating func moveToEnd() { - if isReviewing { - reviewFocus = max(0, selectedAddresses.count - 1) - } else { - focus = max(0, matchingAddresses.count - 1) - } + focus = max(0, matchingAddresses.count - 1) pathOffset = 0 } mutating func toggleFocused() { - guard !isReviewing, let address = focusedAddress else { return } + guard let address = focusedAddress else { return } categories[address.category].groups[address.group].items[address.item].selected.toggle() } @@ -143,7 +133,6 @@ struct InteractiveReviewModel { for address in allAddresses { categories[address.category].groups[address.group].items[address.item].selected = false } - reviewFocus = 0 status = "Selection cleared" } @@ -154,20 +143,12 @@ struct InteractiveReviewModel { status = "" } - mutating func beginReview() -> Bool { + mutating func beginConfirmation() -> Bool { guard selectedCount > 0 else { status = "Select at least one item to continue" return false } - isReviewing = true - reviewFocus = 0 - pathOffset = 0 status = "" - return true - } - - mutating func beginConfirmation() -> Bool { - guard isReviewing else { return false } confirmation = .cancel return true } @@ -216,7 +197,7 @@ struct InteractiveReviewModel { mutating func routeKey(_ key: TerminalKey) -> ReviewKeyRoute { if isConfirming { return handleConfirmationKey(key) } - if isReviewing, key == .enter { + if key == .enter, !isSearching { _ = beginConfirmation() return .handled } @@ -233,18 +214,11 @@ struct InteractiveReviewModel { } } - mutating func endReview() { - isReviewing = false - pathOffset = 0 - status = "" - } - - func displayRows(reviewing: Bool) -> [ReviewDisplayRow] { - let addresses = reviewing ? selectedAddresses : matchingAddresses + var displayRows: [ReviewDisplayRow] { var rows: [ReviewDisplayRow] = [] var lastCategory: Int? var lastGroup: Int? - for address in addresses { + for address in matchingAddresses { if lastCategory != address.category { rows.append(.category(address.category)) lastCategory = address.category @@ -352,25 +326,17 @@ enum InteractiveReview { model.pathOffset += max(8, session.width / 3) case .space: model.toggleFocused() - case .enter: - _ = model.beginReview() case .escape: - if model.isReviewing { - model.endReview() - } else { - return nil - } + return nil case .character(let character): switch character.lowercasedString { case "a": - if !model.isReviewing { model.selectAllMatching() } + model.selectAllMatching() case "n": - if !model.isReviewing { model.selectNone() } + model.selectNone() case "/": - if !model.isReviewing { - model.isSearching = true - model.status = "" - } + model.isSearching = true + model.status = "" case "q": return nil default: @@ -396,16 +362,12 @@ enum InteractiveReview { return TooSmallScreen.render(title: "PureMac", exitHint: "Esc/q cancel", width: width, height: height) } var buffer = Buffer(width: width, height: height) - let reviewing = model.isReviewing - let accent = StatusScreen.warningBorder let window = Window( - title: reviewing ? "Final review" : title, - info: "\(model.selectedCount) selected · \(ByteCount.human(model.selectedBytes))", - borderStyle: reviewing ? accent : TextStyle(dim: true), - titleStyle: reviewing ? StatusScreen.warningTitle : TextStyle(color: .cyan, bold: true) + title: title, + info: "\(model.selectedCount) selected · \(ByteCount.human(model.selectedBytes))" ) let content = window.render(in: buffer.area, buffer: &buffer) - let hints = KeyHints(reviewing ? reviewHints : selectHints) + let hints = KeyHints(selectHints) let areas = content.splitRows( [.length(1), .fill, .length(1), .length(1), .length(hints.rows(width: content.width).count)] ) @@ -416,7 +378,7 @@ enum InteractiveReview { buffer.write(focusedPathSpans(model: model, width: path.width), x: path.x, y: path.y, maxWidth: path.width) hints.render(in: footer, buffer: &buffer) - let rows = model.displayRows(reviewing: reviewing) + let rows = model.displayRows let focusedAddress = model.focusedAddress let focusedRow = rows.firstIndex { row in if case .item(let address) = row { return address == focusedAddress } @@ -430,19 +392,30 @@ enum InteractiveReview { Scrollbar(total: rows.count, visible: list.height, offset: start) .render(column: width - 1, rows: list.y..<(list.y + list.height), buffer: &buffer) guard let focus = model.confirmation else { return buffer } - let dialog = confirmationDialog(count: model.selectedCount, total: model.selectedBytes, noun: noun, focus: focus) + let dialog = confirmationDialog( + count: model.selectedCount, + total: model.selectedBytes, + hidden: model.hiddenSelectedCount, + noun: noun, + focus: focus + ) return StatusScreen.overlay(dialog, on: buffer) } - static func confirmationDialog(count: Int, total: Int64, noun: String, focus: ConfirmationButton) -> Dialog { - Dialog( + static func confirmationDialog( + count: Int, + total: Int64, + hidden: Int, + noun: String, + focus: ConfirmationButton + ) -> Dialog { + var message = [Span("\(ByteCount.human(total)) will be deleted")] + if hidden > 0 { message.append(Span("\(hidden) hidden by search", TextStyle(dim: true))) } + return Dialog( title: "Remove \(CleanupFlow.counted(count, noun))?", titleStyle: StatusScreen.warningTitle, borderStyle: StatusScreen.warningBorder, - message: [ - Span("\(ByteCount.human(total)) will be permanently deleted."), - Span("This cannot be undone.") - ], + message: message, buttons: [DialogButton("Cancel"), DialogButton("Remove", role: .destructive)], focusedButton: focus.rawValue, hints: KeyHints(confirmationHints) @@ -450,9 +423,7 @@ enum InteractiveReview { } private static let confirmationHints = [ - KeyHint("←→", "choose"), KeyHint("Enter", "select"), - KeyHint("Y", "remove"), KeyHint("Esc", "back") ] @@ -463,18 +434,10 @@ enum InteractiveReview { KeyHint("A", "all"), KeyHint("N", "none"), KeyHint("/", "search"), - KeyHint("Enter", "review"), + KeyHint("Enter", "remove"), KeyHint("Esc/q", "cancel") ] - private static let reviewHints = [ - KeyHint("↑↓", "scroll"), - KeyHint("←→", "path"), - KeyHint("Enter", "confirm"), - KeyHint("Esc", "edit"), - KeyHint("q", "cancel") - ] - private static func renderHeader(model: InteractiveReviewModel, in rect: Rect, buffer: inout Buffer) { let dim = TextStyle(dim: true) let found = "\(model.matchingAddresses.count) shown · \(ByteCount.human(model.allBytes))" diff --git a/cli/Tests/TerminalUITests/DialogTests.swift b/cli/Tests/TerminalUITests/DialogTests.swift index f09236b..f00bc48 100644 --- a/cli/Tests/TerminalUITests/DialogTests.swift +++ b/cli/Tests/TerminalUITests/DialogTests.swift @@ -28,9 +28,10 @@ final class DialogTests: XCTestCase { func testFrameIsCenteredAndSizedToContent() { let dialog = simple() - XCTAssertEqual(dialog.frame(in: area), Rect(x: 15, y: 3, width: 10, height: 5)) + XCTAssertEqual(dialog.frame(in: area), Rect(x: 15, y: 3, width: 10, height: 6)) XCTAssertEqual(render(dialog, in: area).rows, [ "╭─ Hi ───╮", + "│ │", "│ Hello │", "│ │", "│ [ OK ] │", @@ -40,7 +41,7 @@ final class DialogTests: XCTestCase { func testFrameIsCenteredInOffsetArea() { let frame = simple().frame(in: Rect(x: 10, y: 2, width: 40, height: 12)) - XCTAssertEqual(frame, Rect(x: 25, y: 5, width: 10, height: 5)) + XCTAssertEqual(frame, Rect(x: 25, y: 5, width: 10, height: 6)) } func testContentWidthIsWidestOfMessageButtonsAndHints() { @@ -56,7 +57,7 @@ final class DialogTests: XCTestCase { let result = render(dialog, in: area) XCTAssertEqual(result.frame.width, 36) XCTAssertEqual(result.frame.x, 2) - XCTAssertTrue(result.rows[1].hasPrefix("│ word word")) + XCTAssertTrue(result.rows[2].contains("word word")) XCTAssertTrue(result.rows.allSatisfy { Term.displayWidth($0) == 36 }) } @@ -68,14 +69,14 @@ final class DialogTests: XCTestCase { ) let result = render(dialog, in: Rect(x: 0, y: 0, width: 16, height: 12)) XCTAssertEqual(result.frame.width, 12) - XCTAssertEqual(Array(result.rows[1...3]), ["│ aaa bbb │", "│ ccc ddd │", "│ ee │"]) + XCTAssertEqual(Array(result.rows[2...4]), ["│ aaa bbb │", "│ ccc ddd │", "│ ee │"]) } func testLongWordIsHardBrokenByDisplayWidth() { let dialog = Dialog(title: "T", message: [Span("abcdefghij 界界界")], buttons: []) let result = render(dialog, in: Rect(x: 0, y: 0, width: 13, height: 12)) - let rows = result.buffer.plainLines().dropFirst(result.frame.y + 1).prefix(4).map { String($0.dropFirst(2).dropLast(2)) } - XCTAssertEqual(rows, ["│ abcde │", "│ fghij │", "│ 界界 │", "│ 界 │"]) + let rows = result.buffer.plainLines().dropFirst(result.frame.y + 2).prefix(4).map { String($0.dropFirst(2).dropLast(2)) } + XCTAssertEqual(rows, ["│ abcde │", "│ fghij │", "│ 界界 │", "│ 界 │"]) } func testDropsBlankRowFirstWhenHeightIsShort() { @@ -104,7 +105,7 @@ final class DialogTests: XCTestCase { var dialog = simple(buttons: buttons) dialog.focusedButton = focused let result = render(dialog, in: area) - let rowIndex = result.frame.y + 3 + let rowIndex = result.frame.y + 4 let line = result.buffer.plainLines()[rowIndex] let start = line.distance(from: line.startIndex, to: line.range(of: "Cancel")!.lowerBound) - 2 return (start, rowIndex, result.buffer) @@ -112,17 +113,17 @@ final class DialogTests: XCTestCase { private let both = [DialogButton("Cancel"), DialogButton("Remove", role: .destructive)] - func testButtonsAreRightAlignedTwoSpacesApart() { + func testButtonsAreTwoSpacesApart() { let result = render(simple(buttons: both), in: area) - XCTAssertEqual(result.rows[3], "│ [ Cancel ] [ Remove ] │") + XCTAssertEqual(result.rows[4], "│ [ Cancel ] [ Remove ] │") } func testFocusedButtonIsWrittenWithPointersAtTheSameWidth() { var dialog = simple(buttons: both) dialog.focusedButton = 0 - XCTAssertEqual(render(dialog, in: area).rows[3], "│ › Cancel ‹ [ Remove ] │") + XCTAssertEqual(render(dialog, in: area).rows[4], "│ › Cancel ‹ [ Remove ] │") dialog.focusedButton = 1 - XCTAssertEqual(render(dialog, in: area).rows[3], "│ [ Cancel ] › Remove ‹ │") + XCTAssertEqual(render(dialog, in: area).rows[4], "│ [ Cancel ] › Remove ‹ │") } func testFocusedNormalButtonIsInverse() { @@ -148,13 +149,93 @@ final class DialogTests: XCTestCase { XCTAssertEqual(found.buffer[found.start + 12, found.row].style, TextStyle(color: .red)) } - func testHintsRowsFollowButtons() { + func testMessageButtonsAndHintsAreCenteredWithBlankRowsBetweenGroups() { var dialog = simple() dialog.hints = KeyHints([KeyHint("Esc", "back")]) - let result = render(dialog, in: area) - XCTAssertEqual(result.rows[3], "│ [ OK ] │") - XCTAssertEqual(result.rows[4], "│ Esc back │") - XCTAssertEqual(result.rows[5], "╰──────────╯") + XCTAssertEqual(render(dialog, in: area).rows, [ + "╭─ Hi ─────╮", + "│ │", + "│ Hello │", + "│ │", + "│ [ OK ] │", + "│ │", + "│ Esc back │", + "╰──────────╯" + ]) + } + + func testHintRowNarrowerThanContentIsCentered() { + var dialog = Dialog(title: "Hi", message: [Span("Hello, world!")]) + dialog.hints = KeyHints([KeyHint("Esc", "back")]) + XCTAssertEqual(render(dialog, in: area).rows, [ + "╭─ Hi ──────────╮", + "│ │", + "│ Hello, world! │", + "│ │", + "│ Esc back │", + "╰───────────────╯" + ]) + } + + func testWrappedHintRowsAreCenteredIndependently() { + var dialog = Dialog(title: "T", message: [Span(String(repeating: "x", count: 40))]) + dialog.hints = KeyHints([ + KeyHint("Enter", "select"), KeyHint("Esc", "back"), KeyHint("Tab", "next"), KeyHint("Space", "toggle") + ]) + let rows = render(dialog, in: Rect(x: 0, y: 0, width: 40, height: 14)).rows + XCTAssertEqual(Array(rows.suffix(3)), [ + "│ Enter select Esc back Tab next │", + "│ Space toggle │", + "╰──────────────────────────────────╯" + ]) + } + + func testBlankRowsAppearOnlyBetweenGroupsThatExist() { + var messageAndHints = Dialog(title: "T", message: [Span("Hello")]) + messageAndHints.hints = KeyHints([KeyHint("Esc", "back")]) + XCTAssertEqual(render(messageAndHints, in: area).rows, [ + "╭─ T ──────╮", + "│ │", + "│ Hello │", + "│ │", + "│ Esc back │", + "╰──────────╯" + ]) + XCTAssertEqual(render(Dialog(title: "Title", buttons: [DialogButton("OK")]), in: area).rows, [ + "╭─ Title ─╮", + "│ [ OK ] │", + "╰─────────╯" + ]) + var buttonsAndHints = Dialog(title: "T", buttons: [DialogButton("OK")]) + buttonsAndHints.hints = KeyHints([KeyHint("Esc", "back")]) + XCTAssertEqual(render(buttonsAndHints, in: area).rows, [ + "╭─ T ──────╮", + "│ [ OK ] │", + "│ │", + "│ Esc back │", + "╰──────────╯" + ]) + } + + func testDropsBlankRowsBottomUpBeforeAnyMessageRow() { + var dialog = Dialog(title: "T", message: (1...4).map { Span("line \($0)") }, buttons: [DialogButton("OK")]) + dialog.hints = KeyHints([KeyHint("Esc", "back")]) + let oneDropped = render(dialog, in: area).rows + XCTAssertEqual(oneDropped.count, 10) + XCTAssertTrue(oneDropped[1].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(oneDropped[2].contains("line 1")) + XCTAssertTrue(oneDropped[5].contains("line 4")) + XCTAssertTrue(oneDropped[6].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(oneDropped[7].contains("[ OK ]")) + XCTAssertTrue(oneDropped[8].contains("Esc back")) + + dialog.message = (1...5).map { Span("line \($0)") } + let twoDropped = render(dialog, in: area).rows + XCTAssertEqual(twoDropped.count, 10) + XCTAssertTrue(twoDropped[1].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(twoDropped[6].contains("line 5")) + XCTAssertTrue(twoDropped[7].contains("[ OK ]")) + XCTAssertTrue(twoDropped[8].contains("Esc back")) } func testBorderAndTitleStylesApply() { @@ -172,7 +253,7 @@ final class DialogTests: XCTestCase { let result = render(simple(), in: area, fill: "x") let lines = result.buffer.plainLines() XCTAssertEqual(lines[2], String(repeating: "x", count: 40)) - XCTAssertEqual(lines[4], String(repeating: "x", count: 15) + "│ Hello │" + String(repeating: "x", count: 15)) + XCTAssertEqual(lines[5], String(repeating: "x", count: 15) + "│ Hello │" + String(repeating: "x", count: 15)) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) XCTAssertTrue(result.buffer.lines(colors: true).allSatisfy { Term.displayWidth($0) == 40 }) } @@ -185,10 +266,11 @@ final class DialogTests: XCTestCase { XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) } - func testStatusDialogWithoutButtonsOrHintsHasNoBlankRow() { + func testStatusDialogWithoutButtonsOrHintsHasBlankRowAboveMessageOnly() { let dialog = Dialog(title: "Working", message: [Span("Removing 2 items…")]) XCTAssertEqual(render(dialog, in: area).rows, [ "╭─ Working ─────────╮", + "│ │", "│ Removing 2 items… │", "╰───────────────────╯" ]) @@ -198,7 +280,8 @@ final class DialogTests: XCTestCase { let shortMessage = Dialog(title: "Cleanup complete", message: [Span("1 KB removed")]) XCTAssertEqual(render(shortMessage, in: area).rows, [ "╭─ Cleanup complete ─╮", - "│ 1 KB removed │", + "│ │", + "│ 1 KB removed │", "╰────────────────────╯" ]) let titleOnly = Dialog(title: "Removing 2 items…") diff --git a/cli/Tests/TerminalUITests/TermTests.swift b/cli/Tests/TerminalUITests/TermTests.swift index cf0d666..66feb55 100644 --- a/cli/Tests/TerminalUITests/TermTests.swift +++ b/cli/Tests/TerminalUITests/TermTests.swift @@ -8,6 +8,12 @@ final class TermTests: XCTestCase { XCTAssertEqual(Term.displayWidth("a\u{301}"), 1) } + func testSpanWidthSumsSanitizedText() { + XCTAssertEqual(Term.displayWidth([Span("ab"), Span("界")]), 4) + XCTAssertEqual(Term.displayWidth([Span("a\u{1B}[2Jb")]), 6) + XCTAssertEqual(Term.displayWidth([Span]()), 0) + } + func testTerminalControlCharactersAreSanitized() { XCTAssertEqual(Term.sanitize("safe\u{1B}[2Jname\n"), "safe�[2Jname�") XCTAssertEqual(Term.sanitize("one\ttwo"), "one two") diff --git a/cli/Tests/puremacTests/CaptureSupport.swift b/cli/Tests/puremacTests/CaptureSupport.swift index ed23a9d..ce1a8c5 100644 --- a/cli/Tests/puremacTests/CaptureSupport.swift +++ b/cli/Tests/puremacTests/CaptureSupport.swift @@ -1,5 +1,4 @@ import Foundation -import XCTest @testable import puremac func capture(_ descriptor: Int32, _ body: () throws -> Void) throws -> String { @@ -25,7 +24,7 @@ func captureStdout(_ body: () throws -> Void) throws -> String { try capture(STD func captureStderr(_ body: () throws -> Void) throws -> String { try capture(STDERR_FILENO, body) } extension InteractiveReviewModel { - static func reviewing(_ categories: [CategoryScan], selecting indices: [Int], query: String = "") -> InteractiveReviewModel { + static func selected(_ categories: [CategoryScan], selecting indices: [Int], query: String = "") -> InteractiveReviewModel { var model = InteractiveReviewModel(categories: categories) if !query.isEmpty { model.updateQuery(query) } var position = 0 @@ -34,7 +33,6 @@ extension InteractiveReviewModel { position = index model.toggleFocused() } - XCTAssertTrue(model.beginReview()) return model } } diff --git a/cli/Tests/puremacTests/CleanupFlowTests.swift b/cli/Tests/puremacTests/CleanupFlowTests.swift index ceedc70..43a3f48 100644 --- a/cli/Tests/puremacTests/CleanupFlowTests.swift +++ b/cli/Tests/puremacTests/CleanupFlowTests.swift @@ -39,7 +39,7 @@ final class CleanupFlowTests: XCTestCase { XCTAssertFalse(CleanupFlow.closesInfoDialog(.up)) } - func testRemovingScreenShowsStatusDialogWithoutButtonsOverFadedFinalReview() { + func testRemovingScreenShowsStatusDialogWithoutButtonsOverFadedSelectionScreen() { let buffer = CleanupFlow.removingScreen(review: review(), labels: labels, width: 80, height: 24) let lines = buffer.plainLines() XCTAssertTrue(lines.contains { $0.contains("Removing 2 items…") }) @@ -47,9 +47,10 @@ final class CleanupFlowTests: XCTestCase { let dialog = CleanupFlow.removingDialog(count: 2, total: 3_000, noun: "item") XCTAssertTrue(dialog.buttons.isEmpty) XCTAssertNil(dialog.focusedButton) - XCTAssertTrue(lines.contains { $0.contains("╭─ Final review ") }) + XCTAssertTrue(lines.contains { $0.contains("╭─ Choose items to clean ") }) + XCTAssertFalse(lines.contains { $0.contains("Final review") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) - XCTAssertFalse(lines.contains { $0.contains("/tmp/third") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/third") }) XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) let frame = CleanupFlow.removingDialog(count: 2, total: 3_000, noun: "item").frame(in: buffer.area) XCTAssertEqual(buffer[frame.x, frame.y].style, TextStyle(color: .yellow)) @@ -187,8 +188,8 @@ final class CleanupFlowTests: XCTestCase { XCTAssertFalse(lines.contains { $0.contains("Esc") || $0.contains("cancel") }) } - func testBackgroundKeepsTheReviewFilter() { - let model = InteractiveReviewModel.reviewing(selection(), selecting: [0], query: "first") + func testBackgroundKeepsTheSelectionFilter() { + let model = InteractiveReviewModel.selected(selection(), selecting: [0], query: "first") let lines = CleanupFlow.resultScreen( outcome: CleanOutcome(removed: 1, freedBytes: 1_000), review: model, labels: labels, width: 80, height: 24 ).plainLines() @@ -196,7 +197,7 @@ final class CleanupFlowTests: XCTestCase { } private func review() -> InteractiveReviewModel { - .reviewing(selection(), selecting: [0, 1]) + .selected(selection(), selecting: [0, 1]) } private func selection() -> [CategoryScan] { diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index c5b0d06..07c2de2 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -28,17 +28,6 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(model.selectedResult()[0].selectedItems.map(\.path), ["/tmp/second"]) } - func testReviewRequiresSelectionBeforeFinalReview() { - var model = InteractiveReviewModel(categories: fixtureCategories()) - XCTAssertFalse(model.beginReview()) - XCTAssertFalse(model.isReviewing) - XCTAssertFalse(model.status.isEmpty) - - model.toggleFocused() - XCTAssertTrue(model.beginReview()) - XCTAssertTrue(model.isReviewing) - } - func testReviewRenderIsBoundedAndKeepsControlsVisible() { var model = InteractiveReviewModel(categories: fixtureCategories()) model.selectAllMatching() @@ -47,7 +36,7 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(lines.count, height) XCTAssertTrue(lines.contains { $0.contains("Space toggle") }) - XCTAssertTrue(lines.contains { $0.contains("Enter review") }) + XCTAssertTrue(lines.contains { $0.contains("Enter remove") }) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == width }) } } @@ -164,13 +153,6 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(buffer[7, 4].style, TextStyle(color: .green)) XCTAssertEqual(buffer[7, 5].style, TextStyle(color: .yellow)) XCTAssertEqual(buffer[7, 6].style, TextStyle(inverse: true)) - - XCTAssertTrue(model.beginReview()) - model.move(2) - let review = renderReview(model, width: 60, height: 24) - XCTAssertEqual(review[7, 4].style, TextStyle(color: .green)) - XCTAssertEqual(review[7, 5].style, TextStyle(color: .yellow)) - XCTAssertEqual(review[7, 6].style, TextStyle(inverse: true)) } func testReviewFocusedPathLineSitsBelowDividerAndHintsFollow() { @@ -178,7 +160,7 @@ final class InteractiveScreensTests: XCTestCase { let divider = lines.firstIndex { $0.hasPrefix("├") }! XCTAssertTrue(lines[divider].hasSuffix("┤")) XCTAssertTrue(lines[divider + 1].hasPrefix("│ Path /tmp/first")) - XCTAssertTrue(lines[divider + 2].hasPrefix("│ ↑↓ move ←→ path Space toggle A all N none / search Enter review")) + XCTAssertTrue(lines[divider + 2].hasPrefix("│ ↑↓ move ←→ path Space toggle A all N none / search Enter remove")) XCTAssertTrue(lines[divider + 3].hasPrefix("│ Esc/q cancel")) XCTAssertTrue(lines[23].hasPrefix("╰")) } @@ -244,33 +226,18 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertFalse(line.hasSuffix("…│")) } - func testFinalReviewControlsFitAtMinimumSupportedWidth() { - var model = InteractiveReviewModel(categories: fixtureCategories()) - model.selectAllMatching() - XCTAssertTrue(model.beginReview()) - let lines = renderReview(model, width: 40, height: 12).plainLines() - XCTAssertEqual(lines.count, 12) - XCTAssertTrue(lines.contains { $0.contains("Enter confirm") }) - XCTAssertTrue(lines.contains { $0.contains("q cancel") }) - XCTAssertFalse(lines.contains { $0.contains("Command confirmation follows") }) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) - } - - func testFinalReviewUsesYellowWindowAndListsOnlySelectedItems() { + func testSelectionScreenKeepsTheCyanWindowAndListsEveryItem() { var model = InteractiveReviewModel(categories: fixtureCategories()) model.toggleFocused() - XCTAssertTrue(model.beginReview()) let buffer = renderReview(model, width: 80, height: 24) let lines = buffer.plainLines() - XCTAssertTrue(lines[0].hasPrefix("╭─ Final review ")) - XCTAssertTrue(lines[0].hasSuffix(" 1 selected · 1 KB ─╮")) - XCTAssertEqual(buffer[0, 0].style, TextStyle(color: .yellow)) - XCTAssertEqual(buffer[3, 0].style, TextStyle(color: .yellow, bold: true)) - XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) - XCTAssertFalse(lines.contains { $0.contains("/tmp/second") }) - XCTAssertTrue(lines.contains { $0.contains("↑↓ scroll ←→ path Enter confirm Esc edit q cancel") }) - XCTAssertFalse(lines.contains { $0.contains("Command confirmation follows") }) - XCTAssertFalse(lines.contains { $0.contains("Space toggle") }) + XCTAssertTrue(lines[0].hasPrefix("╭─ Review removable files ")) + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + XCTAssertEqual(buffer[3, 0].style, TextStyle(color: .cyan, bold: true)) + XCTAssertTrue(lines.contains { $0.contains("/tmp/second") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/third") }) + XCTAssertTrue(lines.contains { $0.contains("Enter remove") }) + XCTAssertFalse(lines.contains { $0.contains("Enter review") || $0.contains("Final review") }) } func testReviewBelowMinimumUsesTooSmallScreen() { @@ -418,21 +385,22 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(Term.displayWidth(Render.sizeCol(1_024)), Render.sizeColumnWidth) } - func testConfirmationOpensOnlyFromFinalReviewWithCancelFocused() { - var selecting = InteractiveReviewModel(categories: fixtureCategories()) - selecting.selectAllMatching() - XCTAssertFalse(selecting.beginConfirmation()) - XCTAssertFalse(selecting.isConfirming) + func testConfirmationOpensOnlyWithASelectionAndCancelFocused() { + var empty = InteractiveReviewModel(categories: fixtureCategories()) + XCTAssertFalse(empty.beginConfirmation()) + XCTAssertFalse(empty.isConfirming) + XCTAssertEqual(empty.status, "Select at least one item to continue") - var model = reviewingModel() + var model = selectedModel() XCTAssertFalse(model.isConfirming) XCTAssertTrue(model.beginConfirmation()) XCTAssertTrue(model.isConfirming) XCTAssertEqual(model.confirmation, .cancel) + XCTAssertEqual(model.status, "") } func testConfirmationFocusMovesWithClamping() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) model.moveConfirmationFocus(-1) XCTAssertEqual(model.confirmation, .cancel) @@ -444,34 +412,32 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(model.confirmation, .cancel) } - func testCancelConfirmationReturnsToFinalReviewAndReopensOnCancel() { - var model = reviewingModel() + func testCancelConfirmationReturnsToSelectionAndReopensOnCancel() { + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) model.moveConfirmationFocus(1) model.cancelConfirmation() XCTAssertFalse(model.isConfirming) - XCTAssertTrue(model.isReviewing) XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.confirmation, .cancel) } func testEnterRightAfterOpeningOnlyClosesTheDialog() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(.enter), .handled) XCTAssertFalse(model.isConfirming) - XCTAssertTrue(model.isReviewing) } func testEnterOnRemoveConfirms() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(.right), .handled) XCTAssertEqual(model.handleConfirmationKey(.enter), .remove) } func testTabAndArrowsMoveConfirmationFocus() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(.tab), .handled) XCTAssertEqual(model.confirmation, .remove) @@ -483,7 +449,7 @@ final class InteractiveScreensTests: XCTestCase { func testYConfirmsInOpenDialog() { for key in [TerminalKey.character("y"), .character("Y")] { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(key), .remove) } @@ -491,22 +457,21 @@ final class InteractiveScreensTests: XCTestCase { func testNAndEscapeCloseTheDialogOnly() { for key in [TerminalKey.character("n"), .character("N"), .escape] { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(key), .handled) XCTAssertFalse(model.isConfirming) - XCTAssertTrue(model.isReviewing) } } func testQCancelsTheWholeFlowFromTheDialog() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(.character("q")), .quit) } func testOtherKeysDoNothingWhileDialogIsOpen() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) let before = model.selectedAddresses.count let keys: [TerminalKey] = [ @@ -519,18 +484,17 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(model.confirmation, .cancel) } XCTAssertEqual(model.selectedAddresses.count, before) - XCTAssertTrue(model.isReviewing) } func testConfirmationKeysAreIgnoredWhenDialogIsClosed() { - var model = reviewingModel() + var model = selectedModel() XCTAssertEqual(model.handleConfirmationKey(.character("y")), .passthrough) XCTAssertEqual(model.handleConfirmationKey(.enter), .passthrough) XCTAssertEqual(model.handleConfirmationKey(.character("q")), .passthrough) } func testTabCyclesBetweenButtons() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.handleConfirmationKey(.tab), .handled) XCTAssertEqual(model.confirmation, .remove) @@ -542,42 +506,44 @@ final class InteractiveScreensTests: XCTestCase { for (count, noun, title) in [(1, "item", "Remove 1 item?"), (1, "artifact", "Remove 1 artifact?"), (0, "item", "Remove 0 items?"), (2, "artifact", "Remove 2 artifacts?")] { XCTAssertEqual( - InteractiveReview.confirmationDialog(count: count, total: 1_000, noun: noun, focus: .cancel).title, + InteractiveReview.confirmationDialog(count: count, total: 1_000, hidden: 0, noun: noun, focus: .cancel).title, title ) } } - func testConfirmationDialogIsDrawnOverFadedFinalReview() { - var model = reviewingModel() + func testConfirmationDialogIsDrawnOverFadedSelectionScreen() { + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) let buffer = renderReview(model, width: 80, height: 24) let lines = buffer.plainLines() XCTAssertTrue(lines.contains { $0.contains("Remove 2 items?") }) - XCTAssertTrue(lines.contains { $0.contains("3 KB will be permanently deleted.") }) - XCTAssertTrue(lines.contains { $0.contains("This cannot be undone.") }) + XCTAssertTrue(lines.contains { $0.contains("3 KB will be deleted") }) + XCTAssertFalse(lines.contains { $0.contains("permanently") || $0.contains("cannot be undone") }) + XCTAssertFalse(lines.contains { $0.contains("hidden by search") }) XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Remove ]") }) - XCTAssertTrue(lines.contains { $0.contains("←→ choose Enter select Y remove Esc back") }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + XCTAssertFalse(lines.contains { $0.contains("Y remove") || $0.contains("choose") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/second") }) - XCTAssertFalse(lines.contains { $0.contains("/tmp/third") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/third") }) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 80 }) XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) XCTAssertEqual(buffer[3, 0].style, TextStyle(dim: true)) } func testConfirmationDialogUsesYellowTitleAndBorder() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) let buffer = renderReview(model, width: 80, height: 24) - let frame = InteractiveReview.confirmationDialog(count: 2, total: 3_000, noun: "item", focus: .cancel) + let frame = InteractiveReview.confirmationDialog(count: 2, total: 3_000, hidden: 0, noun: "item", focus: .cancel) .frame(in: buffer.area) XCTAssertEqual(buffer[frame.x, frame.y].style, TextStyle(color: .yellow)) XCTAssertEqual(buffer[frame.x + 3, frame.y].style, TextStyle(color: .yellow, bold: true)) } func testConfirmationDialogFocusStyles() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) let cancelFocused = renderReview(model, width: 80, height: 24).lines(colors: true).joined() XCTAssertTrue(cancelFocused.contains("\u{1B}[7m› Cancel ‹")) @@ -590,7 +556,7 @@ final class InteractiveScreensTests: XCTestCase { } func testConfirmationDialogUsesTheGivenNoun() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) let lines = InteractiveReview.render( model: model, title: "Choose project artifacts", noun: "artifact", width: 80, height: 24 @@ -599,18 +565,68 @@ final class InteractiveScreensTests: XCTestCase { } func testConfirmationDialogFitsMinimumSize() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) let lines = renderReview(model, width: 40, height: 12).plainLines() XCTAssertEqual(lines.count, 12) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Remove ]") }) - XCTAssertTrue(lines.contains { $0.contains("Y remove") }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + } + + func testHiddenSelectedCountIsTheSelectedItemsTheSearchFiltersOut() { + var model = selectedModel() + XCTAssertEqual(model.hiddenSelectedCount, 0) + model.updateQuery("second") + XCTAssertEqual(model.hiddenSelectedCount, 1) + XCTAssertEqual(model.selectedCount, 2) + model.updateQuery("zzz") + XCTAssertEqual(model.hiddenSelectedCount, 2) + model.updateQuery("/tmp") + XCTAssertEqual(model.hiddenSelectedCount, 0) } - func testFinalReviewWithoutDialogIsNotFaded() { - let buffer = renderReview(reviewingModel(), width: 80, height: 24) - XCTAssertEqual(buffer[0, 0].style, TextStyle(color: .yellow)) + func testSearchDoesNotNarrowWhatTheConfirmationCountsAndRemoves() { + var model = selectedModel() + model.updateQuery("second") + XCTAssertTrue(model.beginConfirmation()) + XCTAssertEqual(model.selectedResult().flatMap { $0.selectedItems }.map(\.path), ["/tmp/first", "/tmp/second"]) + let lines = renderReview(model, width: 80, height: 24).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Remove 2 items?") }) + XCTAssertTrue(lines.contains { $0.contains("3 KB will be deleted") }) + } + + func testHiddenBySearchRowAppearsDimOnlyWhenSelectedItemsAreFilteredOut() { + var model = selectedModel() + model.updateQuery("second") + XCTAssertTrue(model.beginConfirmation()) + let buffer = renderReview(model, width: 80, height: 24) + let lines = buffer.plainLines() + let row = lines.firstIndex { $0.contains("1 hidden by search") }! + let column = lines[row].distance(from: lines[row].startIndex, to: lines[row].range(of: "1 hidden")!.lowerBound) + XCTAssertEqual(buffer[column, row].style, TextStyle(dim: true)) + XCTAssertTrue(lines[row - 1].contains("3 KB will be deleted")) + + model.cancelConfirmation() + model.updateQuery("/tmp") + XCTAssertTrue(model.beginConfirmation()) + XCTAssertFalse(renderReview(model, width: 80, height: 24).plainLines().contains { $0.contains("hidden by search") }) + } + + func testConfirmationDialogFitsMinimumSizeWithHiddenRow() { + var model = selectedModel() + model.updateQuery("second") + XCTAssertTrue(model.beginConfirmation()) + let lines = renderReview(model, width: 40, height: 12).plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines.contains { $0.contains("1 hidden by search") }) + XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Remove ]") }) + } + + func testSelectionWithoutDialogIsNotFaded() { + let buffer = renderReview(selectedModel(), width: 80, height: 24) + XCTAssertEqual(buffer[3, 0].style, TextStyle(color: .cyan, bold: true)) XCTAssertFalse(buffer.plainLines().contains { $0.contains("Cancel") }) } @@ -622,8 +638,8 @@ final class InteractiveScreensTests: XCTestCase { } } - func testEnterInFinalReviewOpensDialogAndNeverReturnsTheSelection() { - var model = reviewingModel() + func testEnterOnTheSelectionOpensDialogAndNeverReturnsTheSelection() { + var model = selectedModel() XCTAssertEqual(model.routeKey(.enter), .handled) XCTAssertTrue(model.isConfirming) XCTAssertEqual(model.confirmation, .cancel) @@ -631,23 +647,31 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertFalse(model.isConfirming) } + func testEnterWithNothingSelectedIsHandledWithoutOpeningTheDialog() { + var model = InteractiveReviewModel(categories: fixtureCategories()) + XCTAssertEqual(model.routeKey(.enter), .handled) + XCTAssertFalse(model.isConfirming) + XCTAssertEqual(model.status, "Select at least one item to continue") + } + func testRouteKeyReturnsRemoveOnlyFromTheOpenDialog() { - var model = reviewingModel() + var model = selectedModel() XCTAssertEqual(model.routeKey(.character("y")), .passthrough) - _ = model.routeKey(.enter) + XCTAssertTrue(model.beginConfirmation()) XCTAssertEqual(model.routeKey(.character("y")), .remove) XCTAssertEqual(model.routeKey(.character("q")), .quit) XCTAssertEqual(model.routeKey(.space), .handled) } - func testRouteKeyPassesEnterThroughOutsideTheFinalReview() { - var model = InteractiveReviewModel(categories: fixtureCategories()) + func testEnterWhileSearchingPassesThroughAndOpensNoDialog() { + var model = selectedModel() + model.isSearching = true XCTAssertEqual(model.routeKey(.enter), .passthrough) XCTAssertFalse(model.isConfirming) } func testTooSmallScreenLetsOnlyCloseAndCancelKeysReachTheDialog() { - var model = reviewingModel() + var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) for key in [TerminalKey.escape, .character("n"), .character("N"), .character("q"), .enter] { XCTAssertTrue(model.acceptsKey(key, tooSmall: true), "\(key)") @@ -661,13 +685,13 @@ final class InteractiveScreensTests: XCTestCase { } func testTooSmallRuleDoesNotAffectOtherStates() { - let model = reviewingModel() + let model = selectedModel() XCTAssertTrue(model.acceptsKey(.enter, tooSmall: true)) XCTAssertTrue(model.acceptsKey(.down, tooSmall: true)) } - private func reviewingModel() -> InteractiveReviewModel { - .reviewing(fixtureCategories(), selecting: [0, 1]) + private func selectedModel() -> InteractiveReviewModel { + .selected(fixtureCategories(), selecting: [0, 1]) } private func menuOptions(_ count: Int) -> [(title: String, detail: String)] { From 281bf69cae4146347d30c58824bcef7020ba19f4 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 12:27:17 +0000 Subject: [PATCH 05/21] feat(cli): add background work with a spinner to TerminalUI --- cli/Sources/TerminalUI/BackgroundWork.swift | 88 ++++++++++++ cli/Sources/TerminalUI/Spinner.swift | 7 + cli/Sources/TerminalUI/TerminalSession.swift | 5 + .../TerminalUITests/BackgroundWorkTests.swift | 129 ++++++++++++++++++ cli/Tests/TerminalUITests/SpinnerTests.swift | 13 ++ 5 files changed, 242 insertions(+) create mode 100644 cli/Sources/TerminalUI/BackgroundWork.swift create mode 100644 cli/Sources/TerminalUI/Spinner.swift create mode 100644 cli/Tests/TerminalUITests/BackgroundWorkTests.swift create mode 100644 cli/Tests/TerminalUITests/SpinnerTests.swift diff --git a/cli/Sources/TerminalUI/BackgroundWork.swift b/cli/Sources/TerminalUI/BackgroundWork.swift new file mode 100644 index 0000000..f0d8a8e --- /dev/null +++ b/cli/Sources/TerminalUI/BackgroundWork.swift @@ -0,0 +1,88 @@ +import Foundation + +public final class WorkProgress: @unchecked Sendable { + private let lock = NSLock() + private var current: Value + + public init(_ initial: Value) { + current = initial + } + + public var value: Value { + lock.lock() + defer { lock.unlock() } + return current + } + + public func set(_ newValue: Value) { + lock.lock() + current = newValue + lock.unlock() + } +} + +public final class CancelFlag: @unchecked Sendable { + private let lock = NSLock() + private var cancelled = false + + public init() {} + + public var isCancelled: Bool { + lock.lock() + defer { lock.unlock() } + return cancelled + } + + public func cancel() { + lock.lock() + cancelled = true + lock.unlock() + } +} + +enum BackgroundWork { + static let redrawIntervalMilliseconds = 80 + + static func run( + progress initial: State, + draw: (_ tick: Int, _ progress: State) -> Void, + readKey: (_ timeoutMilliseconds: Int) -> TerminalKey?, + onKey: (TerminalKey, CancelFlag) -> Void, + work: @escaping (WorkProgress, CancelFlag) -> Output + ) -> Output { + let progress = WorkProgress(initial) + let cancel = CancelFlag() + let outcome = WorkProgress(nil) + + DispatchQueue.global().async { + outcome.set(work(progress, cancel)) + } + + var tick = 0 + while outcome.value == nil { + draw(tick, progress.value) + if let key = readKey(redrawIntervalMilliseconds) { + onKey(key, cancel) + } + tick += 1 + } + return outcome.value! + } +} + +extension TerminalSession { + public func runWithSpinner( + progress initial: State, + render: (_ tick: Int, _ progress: State) -> Buffer, + onKey: (TerminalKey, CancelFlag) -> Void = { _, _ in }, + work: @escaping (WorkProgress, CancelFlag) -> Output + ) -> Output { + BackgroundWork.run( + progress: initial, + draw: { tick, progress in draw(render(tick, progress)) }, + readKey: { readKey(timeoutMilliseconds: $0) }, + onKey: onKey, + work: work + ) + } +} diff --git a/cli/Sources/TerminalUI/Spinner.swift b/cli/Sources/TerminalUI/Spinner.swift new file mode 100644 index 0000000..525da53 --- /dev/null +++ b/cli/Sources/TerminalUI/Spinner.swift @@ -0,0 +1,7 @@ +public enum Spinner { + private static let frames = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏".map(String.init) + + public static func frame(tick: Int) -> String { + frames[tick % frames.count] + } +} diff --git a/cli/Sources/TerminalUI/TerminalSession.swift b/cli/Sources/TerminalUI/TerminalSession.swift index d84c374..5c73f28 100644 --- a/cli/Sources/TerminalUI/TerminalSession.swift +++ b/cli/Sources/TerminalUI/TerminalSession.swift @@ -157,6 +157,11 @@ public final class TerminalSession { return first == 0x1B ? readEscapeSequence() : decodeCharacter(firstByte: first) } + public func readKey(timeoutMilliseconds: Int) -> TerminalKey? { + guard !isClosed, inputAvailable(milliseconds: Int32(clamping: timeoutMilliseconds)) else { return nil } + return readKey() + } + static func key(forSimpleByte byte: UInt8) -> TerminalKey? { switch byte { case 0x0A, 0x0D: return .enter diff --git a/cli/Tests/TerminalUITests/BackgroundWorkTests.swift b/cli/Tests/TerminalUITests/BackgroundWorkTests.swift new file mode 100644 index 0000000..e99f5f3 --- /dev/null +++ b/cli/Tests/TerminalUITests/BackgroundWorkTests.swift @@ -0,0 +1,129 @@ +import XCTest +@testable import TerminalUI + +final class BackgroundWorkTests: XCTestCase { + private let wait: DispatchTimeInterval = .seconds(5) + + func testRedrawsUntilWorkFinishesAndTickIncreases() { + let release = DispatchSemaphore(value: 0) + var ticks: [Int] = [] + var reads = 0 + + let result = BackgroundWork.run( + progress: 0, + draw: { tick, _ in ticks.append(tick) }, + readKey: { _ in + reads += 1 + if reads == 5 { release.signal() } + return nil + }, + onKey: { _, _ in }, + work: { _, _ in + _ = release.wait(timeout: .now() + self.wait) + return "done" + } + ) + + XCTAssertEqual(result, "done") + XCTAssertGreaterThanOrEqual(ticks.count, 5) + XCTAssertEqual(ticks, Array(0.. Date: Mon, 19 Oct 2026 12:36:22 +0000 Subject: [PATCH 06/21] feat(cli): show a spinner and the current path while removing --- cli/Sources/TerminalUI/BackgroundWork.swift | 17 +++- cli/Sources/puremac/Core/Cleaner.swift | 10 ++- cli/Sources/puremac/Core/CleanupFlow.swift | 53 +++++++++-- .../TerminalUITests/BackgroundWorkTests.swift | 39 ++++++-- .../puremacTests/CleanerProgressTests.swift | 50 +++++++++++ cli/Tests/puremacTests/CleanupFlowTests.swift | 89 ++++++++++++++++--- 6 files changed, 225 insertions(+), 33 deletions(-) create mode 100644 cli/Tests/puremacTests/CleanerProgressTests.swift diff --git a/cli/Sources/TerminalUI/BackgroundWork.swift b/cli/Sources/TerminalUI/BackgroundWork.swift index f0d8a8e..d511052 100644 --- a/cli/Sources/TerminalUI/BackgroundWork.swift +++ b/cli/Sources/TerminalUI/BackgroundWork.swift @@ -61,8 +61,13 @@ enum BackgroundWork { var tick = 0 while outcome.value == nil { draw(tick, progress.value) - if let key = readKey(redrawIntervalMilliseconds) { - onKey(key, cancel) + let deadline = DispatchTime.now().uptimeNanoseconds + UInt64(redrawIntervalMilliseconds) * 1_000_000 + while outcome.value == nil { + let remaining = remainingMilliseconds(until: deadline) + guard remaining > 0 else { break } + if let key = readKey(remaining) { + onKey(key, cancel) + } } tick += 1 } @@ -70,6 +75,14 @@ enum BackgroundWork { } } +extension BackgroundWork { + private static func remainingMilliseconds(until deadline: UInt64) -> Int { + let now = DispatchTime.now().uptimeNanoseconds + guard deadline > now else { return 0 } + return Int((deadline - now + 999_999) / 1_000_000) + } +} + extension TerminalSession { public func runWithSpinner( progress initial: State, diff --git a/cli/Sources/puremac/Core/Cleaner.swift b/cli/Sources/puremac/Core/Cleaner.swift index 6c12604..70fd04a 100644 --- a/cli/Sources/puremac/Core/Cleaner.swift +++ b/cli/Sources/puremac/Core/Cleaner.swift @@ -9,10 +9,16 @@ struct CleanOutcome { } enum Cleaner { - static func remove(_ items: [ScanItem], ignore: IgnoreStore, dryRun: Bool) -> CleanOutcome { + static func remove( + _ items: [ScanItem], + ignore: IgnoreStore, + dryRun: Bool, + beforeItem: ((_ index: Int, _ count: Int, _ item: ScanItem) -> Void)? = nil + ) -> CleanOutcome { var out = CleanOutcome() let fm = FileManager.default - for item in items { + for (index, item) in items.enumerated() { + beforeItem?(index, items.count, item) if Safety.hasSymlinkComponent(item.path) { out.skipped.append((item.path, "symlink")) continue diff --git a/cli/Sources/puremac/Core/CleanupFlow.swift b/cli/Sources/puremac/Core/CleanupFlow.swift index 4a60f9c..4387d98 100644 --- a/cli/Sources/puremac/Core/CleanupFlow.swift +++ b/cli/Sources/puremac/Core/CleanupFlow.swift @@ -7,7 +7,21 @@ enum CleanupFlowResult { case finished(CleanOutcome) } +struct RemovalProgress { + let position: Int + let count: Int + let path: String + + init(index: Int, count: Int, path: String) { + position = index + 1 + self.count = count + self.path = path + } +} + enum CleanupFlow { + private static let removingMaxContentWidth = 60 + struct Labels { let scanning: String let empty: String @@ -36,8 +50,20 @@ enum CleanupFlow { ) else { return .cancelled } let items = review.selectedResult().flatMap { $0.selectedItems } - session.draw(removingScreen(review: review, labels: labels, width: session.width, height: session.height)) - let outcome = Cleaner.remove(items, ignore: ignore, dryRun: false) + let outcome = session.runWithSpinner( + progress: RemovalProgress(index: 0, count: items.count, path: items.first?.path ?? ""), + render: { tick, progress in + removingScreen( + review: review, labels: labels, progress: progress, tick: tick, + width: session.width, height: session.height + ) + }, + work: { progress, _ in + Cleaner.remove(items, ignore: ignore, dryRun: false) { index, count, item in + progress.set(RemovalProgress(index: index, count: count, path: item.path)) + } + } + ) session.draw(resultScreen(outcome: outcome, review: review, labels: labels, width: session.width, height: session.height)) while !closesInfoDialog(session.readKey()) {} return .finished(outcome) @@ -88,10 +114,12 @@ enum CleanupFlow { ) } - static func removingScreen(review: InteractiveReviewModel, labels: Labels, width: Int, height: Int) -> Buffer { - let dialog = removingDialog(count: review.selectedCount, total: review.selectedBytes, noun: labels.noun) + static func removingScreen( + review: InteractiveReviewModel, labels: Labels, progress: RemovalProgress, tick: Int, width: Int, height: Int + ) -> Buffer { + let area = Rect(x: 0, y: 0, width: width, height: height) return StatusScreen.overlay( - dialog, + removingDialog(noun: labels.noun, progress: progress, tick: tick, area: area), on: selectionScreen(review, labels: labels, width: width, height: height), tooSmallExitHint: "Removing…" ) @@ -109,12 +137,19 @@ enum CleanupFlow { "\(count) \(noun)\(count == 1 ? "" : "s")" } - static func removingDialog(count: Int, total: Int64, noun: String) -> Dialog { - Dialog( - title: "Removing \(counted(count, noun))…", + static func removingDialog(noun: String, progress: RemovalProgress, tick: Int, area: Rect) -> Dialog { + let rowWidth = min(removingMaxContentWidth, Dialog.maxContentWidth(in: area)) + let current = Term.truncate( + Spinner.frame(tick: tick) + " " + Render.shorten(progress.path), to: rowWidth, middle: true + ) + return Dialog( + title: "Removing \(counted(progress.count, noun))…", titleStyle: StatusScreen.warningTitle, borderStyle: StatusScreen.warningBorder, - message: [Span(ByteCount.human(total))] + message: [ + Span(Term.pad(current, to: rowWidth)), + Span("\(progress.position) of \(progress.count)", TextStyle(dim: true)) + ] ) } diff --git a/cli/Tests/TerminalUITests/BackgroundWorkTests.swift b/cli/Tests/TerminalUITests/BackgroundWorkTests.swift index e99f5f3..0f1520e 100644 --- a/cli/Tests/TerminalUITests/BackgroundWorkTests.swift +++ b/cli/Tests/TerminalUITests/BackgroundWorkTests.swift @@ -7,16 +7,14 @@ final class BackgroundWorkTests: XCTestCase { func testRedrawsUntilWorkFinishesAndTickIncreases() { let release = DispatchSemaphore(value: 0) var ticks: [Int] = [] - var reads = 0 let result = BackgroundWork.run( progress: 0, - draw: { tick, _ in ticks.append(tick) }, - readKey: { _ in - reads += 1 - if reads == 5 { release.signal() } - return nil + draw: { tick, _ in + ticks.append(tick) + if ticks.count == 5 { release.signal() } }, + readKey: { _ in nil }, onKey: { _, _ in }, work: { _, _ in _ = release.wait(timeout: .now() + self.wait) @@ -29,7 +27,7 @@ final class BackgroundWorkTests: XCTestCase { XCTAssertEqual(ticks, Array(0.. IgnoreStore { + try IgnoreStore(fileURL: directory.appendingPathComponent("ignore.json")) + } + + private func makeItem(_ name: String) throws -> ScanItem { + let path = directory.appendingPathComponent(name).path + try Data("x".utf8).write(to: URL(fileURLWithPath: path)) + return ScanItem(path: path, sizeBytes: 1, modified: nil, identity: Safety.fileIdentity(at: path)) + } + + func testCallbackRunsBeforeEachItemWithIndexCountAndItem() throws { + let items = try (0..<3).map { try makeItem("item\($0)") } + var calls: [(Int, Int, String, Bool)] = [] + + _ = Cleaner.remove(items, ignore: try ignoreStore(), dryRun: false) { index, count, item in + calls.append((index, count, item.path, FileManager.default.fileExists(atPath: item.path))) + } + + XCTAssertEqual(calls.map { $0.0 }, [0, 1, 2]) + XCTAssertEqual(calls.map { $0.1 }, [3, 3, 3]) + XCTAssertEqual(calls.map { $0.2 }, items.map { $0.path }) + XCTAssertEqual(calls.map { $0.3 }, [true, true, true]) + } + + func testOutcomeIsTheSameWithAndWithoutCallback() throws { + let items = [try makeItem("a"), try makeItem("b")] + let plain = Cleaner.remove(items, ignore: try ignoreStore(), dryRun: true) + let observed = Cleaner.remove(items, ignore: try ignoreStore(), dryRun: true) { _, _, _ in } + XCTAssertEqual(observed.removed, plain.removed) + XCTAssertEqual(observed.freedBytes, plain.freedBytes) + XCTAssertEqual(observed.skipped.map { $0.path }, plain.skipped.map { $0.path }) + XCTAssertEqual(observed.failed.map { $0.path }, plain.failed.map { $0.path }) + } +} diff --git a/cli/Tests/puremacTests/CleanupFlowTests.swift b/cli/Tests/puremacTests/CleanupFlowTests.swift index 43a3f48..7be546e 100644 --- a/cli/Tests/puremacTests/CleanupFlowTests.swift +++ b/cli/Tests/puremacTests/CleanupFlowTests.swift @@ -40,36 +40,97 @@ final class CleanupFlowTests: XCTestCase { } func testRemovingScreenShowsStatusDialogWithoutButtonsOverFadedSelectionScreen() { - let buffer = CleanupFlow.removingScreen(review: review(), labels: labels, width: 80, height: 24) + let buffer = CleanupFlow.removingScreen( + review: review(), labels: labels, progress: progress(), tick: 0, width: 80, height: 24 + ) let lines = buffer.plainLines() XCTAssertTrue(lines.contains { $0.contains("Removing 2 items…") }) - XCTAssertTrue(lines.contains { $0.contains("3 KB") }) - let dialog = CleanupFlow.removingDialog(count: 2, total: 3_000, noun: "item") + XCTAssertTrue(lines.contains { $0.contains("⠋ /tmp/second") }) + XCTAssertTrue(lines.contains { $0.contains("2 of 2") }) + let dialog = CleanupFlow.removingDialog(noun: "item", progress: progress(), tick: 0, area: buffer.area) XCTAssertTrue(dialog.buttons.isEmpty) XCTAssertNil(dialog.focusedButton) + XCTAssertNil(dialog.hints) XCTAssertTrue(lines.contains { $0.contains("╭─ Choose items to clean ") }) XCTAssertFalse(lines.contains { $0.contains("Final review") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/third") }) XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) - let frame = CleanupFlow.removingDialog(count: 2, total: 3_000, noun: "item").frame(in: buffer.area) + let frame = dialog.frame(in: buffer.area) XCTAssertEqual(buffer[frame.x, frame.y].style, TextStyle(color: .yellow)) XCTAssertEqual(buffer[frame.x + 3, frame.y].style, TextStyle(color: .yellow, bold: true)) } + func testRemovingDialogShowsSpinnerFrameForTheTick() { + let area = Rect(x: 0, y: 0, width: 80, height: 24) + let first = CleanupFlow.removingDialog(noun: "item", progress: progress(), tick: 0, area: area) + let second = CleanupFlow.removingDialog(noun: "item", progress: progress(), tick: 1, area: area) + XCTAssertTrue(first.message[0].text.hasPrefix("\(Spinner.frame(tick: 0)) ")) + XCTAssertTrue(second.message[0].text.hasPrefix("\(Spinner.frame(tick: 1)) ")) + } + + func testRemovingDialogCountRowIsDim() { + let dialog = CleanupFlow.removingDialog( + noun: "item", progress: RemovalProgress(index: 2, count: 5, path: "/tmp/a"), tick: 0, + area: Rect(x: 0, y: 0, width: 80, height: 24) + ) + XCTAssertEqual(dialog.message[1], Span("3 of 5", TextStyle(dim: true))) + XCTAssertEqual(dialog.message.count, 2) + } + + func testRemovingDialogKeepsFixedWidthAcrossItems() { + let wide = Rect(x: 0, y: 0, width: 120, height: 24) + let short = RemovalProgress(index: 0, count: 2, path: "/tmp/a") + let long = RemovalProgress(index: 1, count: 2, path: "/tmp/" + String(repeating: "deep-name/", count: 20)) + let shortDialog = CleanupFlow.removingDialog(noun: "item", progress: short, tick: 0, area: wide) + let longDialog = CleanupFlow.removingDialog(noun: "item", progress: long, tick: 5, area: wide) + XCTAssertEqual(shortDialog.frame(in: wide), longDialog.frame(in: wide)) + XCTAssertEqual(shortDialog.frame(in: wide).width, 60 + 4) + let narrow = Rect(x: 0, y: 0, width: 40, height: 12) + XCTAssertEqual( + CleanupFlow.removingDialog(noun: "item", progress: short, tick: 0, area: narrow).frame(in: narrow).width, + Dialog.maxContentWidth(in: narrow) + 4 + ) + } + + func testRemovingDialogShortensAndMiddleTruncatesThePath() { + let area = Rect(x: 0, y: 0, width: 80, height: 24) + let home = FileManager.default.homeDirectoryForCurrentUser.path + let path = home + "/Library/Caches/" + String(repeating: "very-long-name/", count: 8) + "end" + let row = CleanupFlow.removingDialog( + noun: "item", progress: RemovalProgress(index: 0, count: 1, path: path), tick: 0, area: area + ).message[0].text + XCTAssertEqual(Term.displayWidth(row), 60) + XCTAssertTrue(row.contains("~/Library")) + XCTAssertTrue(row.contains("…")) + XCTAssertTrue(row.hasSuffix("end")) + } + + func testRemovalProgressIsOneBasedAndSizedFromTheCleanerCallback() { + let progress = RemovalProgress(index: 0, count: 3, path: "/tmp/x") + XCTAssertEqual(progress.position, 1) + XCTAssertEqual(progress.count, 3) + XCTAssertEqual(RemovalProgress(index: 2, count: 3, path: "/tmp/y").position, 3) + } + func testRemovingTitleUsesSingularForOneItem() { - XCTAssertEqual(CleanupFlow.removingDialog(count: 1, total: 1_000, noun: "item").title, "Removing 1 item…") - XCTAssertEqual(CleanupFlow.removingDialog(count: 1, total: 1_000, noun: "artifact").title, "Removing 1 artifact…") - XCTAssertEqual(CleanupFlow.removingDialog(count: 0, total: 0, noun: "item").title, "Removing 0 items…") - XCTAssertEqual(CleanupFlow.removingDialog(count: 2, total: 1_000, noun: "artifact").title, "Removing 2 artifacts…") + let area = Rect(x: 0, y: 0, width: 80, height: 24) + func title(_ count: Int, _ noun: String) -> String { + CleanupFlow.removingDialog( + noun: noun, progress: RemovalProgress(index: 0, count: count, path: "/tmp/a"), tick: 0, area: area + ).title + } + XCTAssertEqual(title(1, "item"), "Removing 1 item…") + XCTAssertEqual(title(1, "artifact"), "Removing 1 artifact…") + XCTAssertEqual(title(0, "item"), "Removing 0 items…") + XCTAssertEqual(title(2, "artifact"), "Removing 2 artifacts…") } func testRemovingDialogUsesTheNoun() { let lines = CleanupFlow.removingScreen( review: review(), labels: CleanupFlow.Labels(scanning: "s", empty: "e", reviewTitle: "t", noun: "artifact"), - width: 80, - height: 24 + progress: progress(), tick: 0, width: 80, height: 24 ).plainLines() XCTAssertTrue(lines.contains { $0.contains("Removing 2 artifacts…") }) } @@ -183,7 +244,9 @@ final class CleanupFlowTests: XCTestCase { } func testTooSmallRemovingScreenMakesNoCancelPromise() { - let lines = CleanupFlow.removingScreen(review: review(), labels: labels, width: 30, height: 8).plainLines() + let lines = CleanupFlow.removingScreen( + review: review(), labels: labels, progress: progress(), tick: 0, width: 30, height: 8 + ).plainLines() XCTAssertTrue(lines.contains { $0.contains("Removing") }) XCTAssertFalse(lines.contains { $0.contains("Esc") || $0.contains("cancel") }) } @@ -196,6 +259,10 @@ final class CleanupFlowTests: XCTestCase { XCTAssertTrue(lines.contains { $0.contains("Filter first") }) } + private func progress() -> RemovalProgress { + RemovalProgress(index: 1, count: 2, path: "/tmp/second") + } + private func review() -> InteractiveReviewModel { .selected(selection(), selecting: [0, 1]) } From 2a191f74e138c103af7625ecaf7b7f2c51592e58 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 12:43:22 +0000 Subject: [PATCH 07/21] feat(cli): balance dialog spacing and keep the removal spinner in place --- cli/Sources/TerminalUI/Dialog.swift | 32 ++- cli/Sources/puremac/Core/CleanupFlow.swift | 3 +- cli/Tests/TerminalUITests/DialogTests.swift | 205 +++++++++++------- cli/Tests/puremacTests/CleanupFlowTests.swift | 19 +- .../InteractiveScreensTests.swift | 2 +- 5 files changed, 172 insertions(+), 89 deletions(-) diff --git a/cli/Sources/TerminalUI/Dialog.swift b/cli/Sources/TerminalUI/Dialog.swift index e221dfd..85cc411 100644 --- a/cli/Sources/TerminalUI/Dialog.swift +++ b/cli/Sources/TerminalUI/Dialog.swift @@ -11,6 +11,8 @@ public struct DialogButton: Equatable { } public struct Dialog { + public enum MessageAlignment: Equatable { case center, leading } + public var title: String public var titleStyle: TextStyle public var borderStyle: TextStyle @@ -18,6 +20,7 @@ public struct Dialog { public var buttons: [DialogButton] public var focusedButton: Int? public var hints: KeyHints? + public var messageAlignment: MessageAlignment public init( title: String, @@ -26,7 +29,8 @@ public struct Dialog { message: [Span] = [], buttons: [DialogButton] = [], focusedButton: Int? = nil, - hints: KeyHints? = nil + hints: KeyHints? = nil, + messageAlignment: MessageAlignment = .center ) { self.title = title self.titleStyle = titleStyle @@ -35,10 +39,13 @@ public struct Dialog { self.buttons = buttons self.focusedButton = focusedButton self.hints = hints + self.messageAlignment = messageAlignment } + private static let sidePadding = 1 + public static func maxContentWidth(in area: Rect) -> Int { - max(1, area.width - 8) + max(1, area.width - 8 - 2 * Dialog.sidePadding) } public func frame(in area: Rect) -> Rect { @@ -48,11 +55,12 @@ public struct Dialog { public func render(in area: Rect, buffer: inout Buffer) { let (frame, layout) = placement(in: area) buffer.clear(frame) - let content = Window(title: title, borderStyle: borderStyle, titleStyle: titleStyle) + let inner = Window(title: title, borderStyle: borderStyle, titleStyle: titleStyle) .render(in: frame, buffer: &buffer) + let content = Rect(x: inner.x + Dialog.sidePadding, y: inner.y, width: max(0, inner.width - 2 * Dialog.sidePadding), height: inner.height) var row = content.y + layout.blankAboveMessage for message in layout.messageRows { - renderCentered([message], in: content, row: row, buffer: &buffer) + renderMessage(message, in: content, row: row, buffer: &buffer) row += 1 } row += layout.blankBelowMessage @@ -72,17 +80,18 @@ public struct Dialog { var blankAboveMessage = 0 var blankBelowMessage = 0 var blankBelowButtons = 0 + var blankBelowLast = 0 var hintRows: Int var buttonRows: Int var height: Int { - messageRows.count + blankAboveMessage + blankBelowMessage + blankBelowButtons + buttonRows + hintRows + messageRows.count + blankAboveMessage + blankBelowMessage + blankBelowButtons + blankBelowLast + buttonRows + hintRows } } private func placement(in area: Rect) -> (frame: Rect, layout: Layout) { let contentWidth = self.contentWidth(maxWidth: Dialog.maxContentWidth(in: area)) let layout = layout(contentWidth: contentWidth, maxRows: area.height - 4) - let width = contentWidth + 4 + let width = contentWidth + 4 + 2 * Dialog.sidePadding let height = layout.height + 2 let frame = Rect( x: area.x + (area.width - width) / 2, @@ -126,6 +135,8 @@ public struct Dialog { layout.blankBelowMessage = tailRows > 0 ? 1 : 0 } layout.blankBelowButtons = buttonRows > 0 && hintRows > 0 ? 1 : 0 + layout.blankBelowLast = wrapped.isEmpty && tailRows == 0 ? 0 : 1 + if layout.height > maxRows { layout.blankBelowLast = 0 } if layout.height > maxRows { layout.blankBelowButtons = 0 } if layout.height > maxRows { layout.blankBelowMessage = 0 } if layout.height > maxRows { layout.blankAboveMessage = 0 } @@ -139,6 +150,15 @@ public struct Dialog { buffer.write(spans, x: column, y: row, maxWidth: content.x + content.width - column) } + private func renderMessage(_ span: Span, in content: Rect, row: Int, buffer: inout Buffer) { + switch messageAlignment { + case .center: + renderCentered([span], in: content, row: row, buffer: &buffer) + case .leading: + buffer.write([span], x: content.x, y: row, maxWidth: content.width) + } + } + private func renderButtons(in content: Rect, row: Int, buffer: inout Buffer) { renderCentered(buttonSpans, in: content, row: row, buffer: &buffer) } diff --git a/cli/Sources/puremac/Core/CleanupFlow.swift b/cli/Sources/puremac/Core/CleanupFlow.swift index 4387d98..6529aed 100644 --- a/cli/Sources/puremac/Core/CleanupFlow.swift +++ b/cli/Sources/puremac/Core/CleanupFlow.swift @@ -149,7 +149,8 @@ enum CleanupFlow { message: [ Span(Term.pad(current, to: rowWidth)), Span("\(progress.position) of \(progress.count)", TextStyle(dim: true)) - ] + ], + messageAlignment: .leading ) } diff --git a/cli/Tests/TerminalUITests/DialogTests.swift b/cli/Tests/TerminalUITests/DialogTests.swift index f00bc48..b0428c5 100644 --- a/cli/Tests/TerminalUITests/DialogTests.swift +++ b/cli/Tests/TerminalUITests/DialogTests.swift @@ -22,34 +22,35 @@ final class DialogTests: XCTestCase { } func testMaxContentWidthLeavesTheMarginAroundTheFrame() { - XCTAssertEqual(Dialog.maxContentWidth(in: Rect(x: 0, y: 0, width: 80, height: 24)), 72) + XCTAssertEqual(Dialog.maxContentWidth(in: Rect(x: 0, y: 0, width: 80, height: 24)), 70) XCTAssertEqual(Dialog.maxContentWidth(in: Rect(x: 0, y: 0, width: 4, height: 24)), 1) } func testFrameIsCenteredAndSizedToContent() { let dialog = simple() - XCTAssertEqual(dialog.frame(in: area), Rect(x: 15, y: 3, width: 10, height: 6)) + XCTAssertEqual(dialog.frame(in: area), Rect(x: 14, y: 2, width: 12, height: 7)) XCTAssertEqual(render(dialog, in: area).rows, [ - "╭─ Hi ───╮", - "│ │", - "│ Hello │", - "│ │", - "│ [ OK ] │", - "╰────────╯" + "╭─ Hi ─────╮", + "│ │", + "│ Hello │", + "│ │", + "│ [ OK ] │", + "│ │", + "╰──────────╯" ]) } func testFrameIsCenteredInOffsetArea() { let frame = simple().frame(in: Rect(x: 10, y: 2, width: 40, height: 12)) - XCTAssertEqual(frame, Rect(x: 25, y: 5, width: 10, height: 6)) + XCTAssertEqual(frame, Rect(x: 24, y: 4, width: 12, height: 7)) } func testContentWidthIsWidestOfMessageButtonsAndHints() { let wideButtons = simple(buttons: [DialogButton("Cancel"), DialogButton("Remove")]) - XCTAssertEqual(wideButtons.frame(in: area).width, 22 + 4) + XCTAssertEqual(wideButtons.frame(in: area).width, 22 + 6) var withHints = simple() withHints.hints = KeyHints([KeyHint("Esc", "back"), KeyHint("Enter", "select")]) - XCTAssertEqual(withHints.frame(in: area).width, Term.displayWidth("Esc back Enter select") + 4) + XCTAssertEqual(withHints.frame(in: area).width, Term.displayWidth("Esc back Enter select") + 6) } func testWidthIsCappedToMarginsAndMessageWraps() { @@ -67,16 +68,16 @@ final class DialogTests: XCTestCase { message: [Span("aaa bbb ccc ddd"), Span("ee")], buttons: [] ) - let result = render(dialog, in: Rect(x: 0, y: 0, width: 16, height: 12)) - XCTAssertEqual(result.frame.width, 12) - XCTAssertEqual(Array(result.rows[2...4]), ["│ aaa bbb │", "│ ccc ddd │", "│ ee │"]) + let result = render(dialog, in: Rect(x: 0, y: 0, width: 20, height: 12)) + XCTAssertEqual(result.frame.width, 16) + XCTAssertEqual(Array(result.rows[2...4]), ["│ aaa bbb │", "│ ccc ddd │", "│ ee │"]) } func testLongWordIsHardBrokenByDisplayWidth() { let dialog = Dialog(title: "T", message: [Span("abcdefghij 界界界")], buttons: []) - let result = render(dialog, in: Rect(x: 0, y: 0, width: 13, height: 12)) + let result = render(dialog, in: Rect(x: 0, y: 0, width: 15, height: 12)) let rows = result.buffer.plainLines().dropFirst(result.frame.y + 2).prefix(4).map { String($0.dropFirst(2).dropLast(2)) } - XCTAssertEqual(rows, ["│ abcde │", "│ fghij │", "│ 界界 │", "│ 界 │"]) + XCTAssertEqual(rows, ["│ abcde │", "│ fghij │", "│ 界界 │", "│ 界 │"]) } func testDropsBlankRowFirstWhenHeightIsShort() { @@ -115,15 +116,15 @@ final class DialogTests: XCTestCase { func testButtonsAreTwoSpacesApart() { let result = render(simple(buttons: both), in: area) - XCTAssertEqual(result.rows[4], "│ [ Cancel ] [ Remove ] │") + XCTAssertEqual(result.rows[4], "│ [ Cancel ] [ Remove ] │") } func testFocusedButtonIsWrittenWithPointersAtTheSameWidth() { var dialog = simple(buttons: both) dialog.focusedButton = 0 - XCTAssertEqual(render(dialog, in: area).rows[4], "│ › Cancel ‹ [ Remove ] │") + XCTAssertEqual(render(dialog, in: area).rows[4], "│ › Cancel ‹ [ Remove ] │") dialog.focusedButton = 1 - XCTAssertEqual(render(dialog, in: area).rows[4], "│ [ Cancel ] › Remove ‹ │") + XCTAssertEqual(render(dialog, in: area).rows[4], "│ [ Cancel ] › Remove ‹ │") } func testFocusedNormalButtonIsInverse() { @@ -153,14 +154,15 @@ final class DialogTests: XCTestCase { var dialog = simple() dialog.hints = KeyHints([KeyHint("Esc", "back")]) XCTAssertEqual(render(dialog, in: area).rows, [ - "╭─ Hi ─────╮", - "│ │", - "│ Hello │", - "│ │", - "│ [ OK ] │", - "│ │", - "│ Esc back │", - "╰──────────╯" + "╭─ Hi ───────╮", + "│ │", + "│ Hello │", + "│ │", + "│ [ OK ] │", + "│ │", + "│ Esc back │", + "│ │", + "╰────────────╯" ]) } @@ -168,12 +170,13 @@ final class DialogTests: XCTestCase { var dialog = Dialog(title: "Hi", message: [Span("Hello, world!")]) dialog.hints = KeyHints([KeyHint("Esc", "back")]) XCTAssertEqual(render(dialog, in: area).rows, [ - "╭─ Hi ──────────╮", - "│ │", - "│ Hello, world! │", - "│ │", - "│ Esc back │", - "╰───────────────╯" + "╭─ Hi ────────────╮", + "│ │", + "│ Hello, world! │", + "│ │", + "│ Esc back │", + "│ │", + "╰─────────────────╯" ]) } @@ -182,11 +185,12 @@ final class DialogTests: XCTestCase { dialog.hints = KeyHints([ KeyHint("Enter", "select"), KeyHint("Esc", "back"), KeyHint("Tab", "next"), KeyHint("Space", "toggle") ]) - let rows = render(dialog, in: Rect(x: 0, y: 0, width: 40, height: 14)).rows - XCTAssertEqual(Array(rows.suffix(3)), [ - "│ Enter select Esc back Tab next │", - "│ Space toggle │", - "╰──────────────────────────────────╯" + let rows = render(dialog, in: Rect(x: 0, y: 0, width: 42, height: 14)).rows + XCTAssertEqual(Array(rows.suffix(4)), [ + "│ Enter select Esc back Tab next │", + "│ Space toggle │", + "│" + String(repeating: " ", count: 36) + "│", + "╰" + String(repeating: "─", count: 36) + "╯" ]) } @@ -194,48 +198,89 @@ final class DialogTests: XCTestCase { var messageAndHints = Dialog(title: "T", message: [Span("Hello")]) messageAndHints.hints = KeyHints([KeyHint("Esc", "back")]) XCTAssertEqual(render(messageAndHints, in: area).rows, [ - "╭─ T ──────╮", - "│ │", - "│ Hello │", - "│ │", - "│ Esc back │", - "╰──────────╯" + "╭─ T ────────╮", + "│ │", + "│ Hello │", + "│ │", + "│ Esc back │", + "│ │", + "╰────────────╯" ]) XCTAssertEqual(render(Dialog(title: "Title", buttons: [DialogButton("OK")]), in: area).rows, [ - "╭─ Title ─╮", - "│ [ OK ] │", - "╰─────────╯" + "╭─ Title ───╮", + "│ [ OK ] │", + "│ │", + "╰───────────╯" ]) var buttonsAndHints = Dialog(title: "T", buttons: [DialogButton("OK")]) buttonsAndHints.hints = KeyHints([KeyHint("Esc", "back")]) XCTAssertEqual(render(buttonsAndHints, in: area).rows, [ - "╭─ T ──────╮", - "│ [ OK ] │", - "│ │", - "│ Esc back │", - "╰──────────╯" + "╭─ T ────────╮", + "│ [ OK ] │", + "│ │", + "│ Esc back │", + "│ │", + "╰────────────╯" ]) } func testDropsBlankRowsBottomUpBeforeAnyMessageRow() { var dialog = Dialog(title: "T", message: (1...4).map { Span("line \($0)") }, buttons: [DialogButton("OK")]) dialog.hints = KeyHints([KeyHint("Esc", "back")]) - let oneDropped = render(dialog, in: area).rows - XCTAssertEqual(oneDropped.count, 10) - XCTAssertTrue(oneDropped[1].allSatisfy { $0 == " " || $0 == "│" }) - XCTAssertTrue(oneDropped[2].contains("line 1")) - XCTAssertTrue(oneDropped[5].contains("line 4")) - XCTAssertTrue(oneDropped[6].allSatisfy { $0 == " " || $0 == "│" }) - XCTAssertTrue(oneDropped[7].contains("[ OK ]")) - XCTAssertTrue(oneDropped[8].contains("Esc back")) + let droppedTwoBlankRows = render(dialog, in: area).rows + XCTAssertEqual(droppedTwoBlankRows.count, 10) + XCTAssertTrue(droppedTwoBlankRows[1].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(droppedTwoBlankRows[2].contains("line 1")) + XCTAssertTrue(droppedTwoBlankRows[5].contains("line 4")) + XCTAssertTrue(droppedTwoBlankRows[6].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(droppedTwoBlankRows[7].contains("[ OK ]")) + XCTAssertTrue(droppedTwoBlankRows[8].contains("Esc back")) dialog.message = (1...5).map { Span("line \($0)") } - let twoDropped = render(dialog, in: area).rows - XCTAssertEqual(twoDropped.count, 10) - XCTAssertTrue(twoDropped[1].allSatisfy { $0 == " " || $0 == "│" }) - XCTAssertTrue(twoDropped[6].contains("line 5")) - XCTAssertTrue(twoDropped[7].contains("[ OK ]")) - XCTAssertTrue(twoDropped[8].contains("Esc back")) + let droppedThreeBlankRows = render(dialog, in: area).rows + XCTAssertEqual(droppedThreeBlankRows.count, 10) + XCTAssertTrue(droppedThreeBlankRows[1].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(droppedThreeBlankRows[6].contains("line 5")) + XCTAssertTrue(droppedThreeBlankRows[7].contains("[ OK ]")) + XCTAssertTrue(droppedThreeBlankRows[8].contains("Esc back")) + } + + func testBottomBlankRowIsDroppedBeforeTheOtherBlankRows() { + var dialog = Dialog(title: "T", message: [Span("a"), Span("b")], buttons: [DialogButton("OK")]) + dialog.hints = KeyHints([KeyHint("Esc", "back")]) + let fits = render(dialog, in: Rect(x: 0, y: 0, width: 40, height: 12)) + XCTAssertEqual(fits.rows.count, 10) + XCTAssertTrue(fits.rows[8].allSatisfy { $0 == " " || $0 == "│" }) + let tight = render(dialog, in: Rect(x: 0, y: 0, width: 40, height: 11)).rows + XCTAssertEqual(tight.count, 9) + XCTAssertTrue(tight[1].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(tight[4].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(tight[6].allSatisfy { $0 == " " || $0 == "│" }) + XCTAssertTrue(tight[7].contains("Esc back")) + } + + func testLeadingMessageAlignmentKeepsRowsInTheFirstContentColumn() { + var dialog = Dialog( + title: "T", + message: [Span("a"), Span("longer text")], + buttons: [DialogButton("OK")] + ) + dialog.messageAlignment = .leading + XCTAssertEqual(render(dialog, in: area).rows, [ + "╭─ T ───────────╮", + "│ │", + "│ a │", + "│ longer text │", + "│ │", + "│ [ OK ] │", + "│ │", + "╰───────────────╯" + ]) + } + + func testCenterMessageAlignmentIsTheDefault() { + let dialog = Dialog(title: "T", message: [Span("a"), Span("longer text")]) + XCTAssertEqual(render(dialog, in: area).rows[2], "│ a │") } func testBorderAndTitleStylesApply() { @@ -252,8 +297,8 @@ final class DialogTests: XCTestCase { func testRenderClearsBackgroundInsideFrameOnly() { let result = render(simple(), in: area, fill: "x") let lines = result.buffer.plainLines() - XCTAssertEqual(lines[2], String(repeating: "x", count: 40)) - XCTAssertEqual(lines[5], String(repeating: "x", count: 15) + "│ Hello │" + String(repeating: "x", count: 15)) + XCTAssertEqual(lines[1], String(repeating: "x", count: 40)) + XCTAssertEqual(lines[4], String(repeating: "x", count: 14) + "│ Hello │" + String(repeating: "x", count: 14)) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) XCTAssertTrue(result.buffer.lines(colors: true).allSatisfy { Term.displayWidth($0) == 40 }) } @@ -266,28 +311,30 @@ final class DialogTests: XCTestCase { XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) } - func testStatusDialogWithoutButtonsOrHintsHasBlankRowAboveMessageOnly() { + func testStatusDialogWithoutButtonsOrHintsHasBlankRowsAroundMessage() { let dialog = Dialog(title: "Working", message: [Span("Removing 2 items…")]) XCTAssertEqual(render(dialog, in: area).rows, [ - "╭─ Working ─────────╮", - "│ │", - "│ Removing 2 items… │", - "╰───────────────────╯" + "╭─ Working ───────────╮", + "│ │", + "│ Removing 2 items… │", + "│ │", + "╰─────────────────────╯" ]) } func testContentWidthFitsTitle() { let shortMessage = Dialog(title: "Cleanup complete", message: [Span("1 KB removed")]) XCTAssertEqual(render(shortMessage, in: area).rows, [ - "╭─ Cleanup complete ─╮", - "│ │", - "│ 1 KB removed │", - "╰────────────────────╯" + "╭─ Cleanup complete ───╮", + "│ │", + "│ 1 KB removed │", + "│ │", + "╰──────────────────────╯" ]) let titleOnly = Dialog(title: "Removing 2 items…") XCTAssertEqual(render(titleOnly, in: area).rows, [ - "╭─ Removing 2 items… ─╮", - "╰─────────────────────╯" + "╭─ Removing 2 items… ───╮", + "╰───────────────────────╯" ]) } } diff --git a/cli/Tests/puremacTests/CleanupFlowTests.swift b/cli/Tests/puremacTests/CleanupFlowTests.swift index 7be546e..866b620 100644 --- a/cli/Tests/puremacTests/CleanupFlowTests.swift +++ b/cli/Tests/puremacTests/CleanupFlowTests.swift @@ -78,6 +78,21 @@ final class CleanupFlowTests: XCTestCase { XCTAssertEqual(dialog.message.count, 2) } + func testRemovingDialogKeepsRowsInTheFirstContentColumn() { + let area = Rect(x: 0, y: 0, width: 80, height: 24) + let dialog = CleanupFlow.removingDialog(noun: "item", progress: progress(), tick: 0, area: area) + var buffer = Buffer(width: 80, height: 24) + dialog.render(in: area, buffer: &buffer) + let frame = dialog.frame(in: area) + let lines = buffer.plainLines() + let spinnerRow = lines.first { $0.contains("⠋ /tmp/second") }! + let countRow = lines.first { $0.contains("2 of 2") }! + let spinnerColumn = spinnerRow.distance(from: spinnerRow.startIndex, to: spinnerRow.range(of: "⠋")!.lowerBound) + let countColumn = countRow.distance(from: countRow.startIndex, to: countRow.range(of: "2 of 2")!.lowerBound) + XCTAssertEqual(spinnerColumn, frame.x + 3) + XCTAssertEqual(countColumn, frame.x + 3) + } + func testRemovingDialogKeepsFixedWidthAcrossItems() { let wide = Rect(x: 0, y: 0, width: 120, height: 24) let short = RemovalProgress(index: 0, count: 2, path: "/tmp/a") @@ -85,11 +100,11 @@ final class CleanupFlowTests: XCTestCase { let shortDialog = CleanupFlow.removingDialog(noun: "item", progress: short, tick: 0, area: wide) let longDialog = CleanupFlow.removingDialog(noun: "item", progress: long, tick: 5, area: wide) XCTAssertEqual(shortDialog.frame(in: wide), longDialog.frame(in: wide)) - XCTAssertEqual(shortDialog.frame(in: wide).width, 60 + 4) + XCTAssertEqual(shortDialog.frame(in: wide).width, 60 + 6) let narrow = Rect(x: 0, y: 0, width: 40, height: 12) XCTAssertEqual( CleanupFlow.removingDialog(noun: "item", progress: short, tick: 0, area: narrow).frame(in: narrow).width, - Dialog.maxContentWidth(in: narrow) + 4 + Dialog.maxContentWidth(in: narrow) + 6 ) } diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index 07c2de2..ea384fa 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -526,7 +526,7 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertFalse(lines.contains { $0.contains("Y remove") || $0.contains("choose") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/first") }) XCTAssertTrue(lines.contains { $0.contains("/tmp/second") }) - XCTAssertTrue(lines.contains { $0.contains("/tmp/third") }) + XCTAssertTrue(lines.contains { $0.contains("/tmp/thir") }) XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 80 }) XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) XCTAssertEqual(buffer[3, 0].style, TextStyle(dim: true)) From 1e8dc7f4ee1269656060552ada5a8b6eef09052f Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 12:56:48 +0000 Subject: [PATCH 08/21] feat(cli): show measuring progress in the storage explorer --- cli/Sources/TerminalUI/BackgroundWork.swift | 6 + cli/Sources/puremac/Commands/Analyze.swift | 222 ++++++++++++++---- .../TerminalUITests/BackgroundWorkTests.swift | 6 + cli/Tests/puremacTests/AnalyzeTests.swift | 176 +++++++++++++- 4 files changed, 355 insertions(+), 55 deletions(-) diff --git a/cli/Sources/TerminalUI/BackgroundWork.swift b/cli/Sources/TerminalUI/BackgroundWork.swift index d511052..8347562 100644 --- a/cli/Sources/TerminalUI/BackgroundWork.swift +++ b/cli/Sources/TerminalUI/BackgroundWork.swift @@ -19,6 +19,12 @@ public final class WorkProgress: @unchecked Sendable { current = newValue lock.unlock() } + + public func update(_ change: (inout Value) -> Void) { + lock.lock() + change(¤t) + lock.unlock() + } } public final class CancelFlag: @unchecked Sendable { diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index cd997c0..6e9aa88 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -72,6 +72,12 @@ struct Analyze: ParsableCommand { let skippedCount: Int var isPartial: Bool { inaccessibleCount > 0 || skippedCount > 0 } + + static func suffix(isDirectory: Bool, isPackage: Bool) -> String { + isDirectory && !isPackage ? "/" : (isPackage ? " [package]" : "") + } + + var suffix: String { Self.suffix(isDirectory: isDir, isPackage: isPackage) } } struct FolderSnapshot: Equatable { @@ -91,13 +97,43 @@ struct Analyze: ParsableCommand { var errors: [String] = [] } + enum ScanEvent: Equatable { + case measuring(position: Int, count: Int, name: String, isDirectory: Bool, isPackage: Bool) + case measured(Child) + } + + struct ScanProgress { + let path: String + var position = 0 + var count = 0 + var name = "" + var nameIsDirectory = false + var nameIsPackage = false + var measured: [Child] = [] + + mutating func apply(_ event: ScanEvent) { + switch event { + case .measuring(let position, let count, let name, let isDirectory, let isPackage): + (self.position, self.count, self.name) = (position, count, name) + (nameIsDirectory, nameIsPackage) = (isDirectory, isPackage) + case .measured(let child): + measured.append(child) + } + } + } + struct BrowserLevel { let snapshot: FolderSnapshot var selected = 0 var offset = 0 } - func scanFolder(_ directory: String, ignore: IgnoreStore = IgnoreStore()) -> FolderSnapshot { + func scanFolder( + _ directory: String, + ignore: IgnoreStore = IgnoreStore(), + progress: ((ScanEvent) -> Void)? = nil, + isCancelled: () -> Bool = { false } + ) -> FolderSnapshot { let standardized = (directory as NSString).standardizingPath let directoryURL = URL(fileURLWithPath: standardized, isDirectory: true) let names: [String] @@ -117,20 +153,23 @@ struct Analyze: ParsableCommand { var context = MeasureContext() var children: [Child] = [] let orderedNames = names.sorted { $0.localizedStandardCompare($1) == .orderedAscending } - for name in orderedNames { + for (index, name) in orderedNames.enumerated() { + if isCancelled() { break } let url = directoryURL.appendingPathComponent(name) + if let progress { + let kind = Self.kind(of: url) + progress(.measuring( + position: index + 1, count: orderedNames.count, name: name, + isDirectory: kind.isDirectory, isPackage: kind.isPackage + )) + } if let child = measureChild(url, ignore: ignore, context: &context) { children.append(child) + progress?(.measured(child)) } } - children.sort { - if $0.size == $1.size { - return URL(fileURLWithPath: $0.path).lastPathComponent - .localizedStandardCompare(URL(fileURLWithPath: $1.path).lastPathComponent) == .orderedAscending - } - return $0.size > $1.size - } + children = Self.ranked(children) return FolderSnapshot( path: standardized, children: children, @@ -141,10 +180,26 @@ struct Analyze: ParsableCommand { ) } + static func ranked(_ children: [Child]) -> [Child] { + children.sorted { + if $0.size == $1.size { + return URL(fileURLWithPath: $0.path).lastPathComponent + .localizedStandardCompare(URL(fileURLWithPath: $1.path).lastPathComponent) == .orderedAscending + } + return $0.size > $1.size + } + } + func sizedChildren(of directory: String) -> [Child] { scanFolder(directory).children } + private static func kind(of url: URL) -> (isDirectory: Bool, isPackage: Bool) { + let values = try? url.resourceValues(forKeys: [.isDirectoryKey, .isPackageKey]) + let isDirectory = values?.isDirectory == true + return (isDirectory, isDirectory && values?.isPackage == true) + } + private func measureChild(_ topURL: URL, ignore: IgnoreStore, context: inout MeasureContext) -> Child? { let path = topURL.path if Safety.ignoredPathProtectsCandidate(path, ignore: ignore) { @@ -167,13 +222,12 @@ struct Analyze: ParsableCommand { break } - let values = try? topURL.resourceValues(forKeys: [.isDirectoryKey, .isPackageKey]) - let isDirectory = values?.isDirectory == true + let kind = Self.kind(of: topURL) return Child( path: path, size: measurement.bytes, - isDir: isDirectory, - isPackage: isDirectory && values?.isPackage == true, + isDir: kind.isDirectory, + isPackage: kind.isPackage, inaccessibleCount: 0, skippedCount: measurement.status == .partial ? max(1, measurement.skippedEntries) : 0 ) @@ -217,9 +271,8 @@ struct Analyze: ParsableCommand { let fraction = total > 0 ? Double(child.size) / Double(total) : 0 let percentage = String(format: "%5.1f%%", fraction * 100) let size = ByteCount.human(child.size).padding(toLength: 10, withPad: " ", startingAt: 0) - let suffix = child.isDir && !child.isPackage ? "/" : (child.isPackage ? " [package]" : "") let partial = child.isPartial ? Term.yellow(" !") : "" - let name = URL(fileURLWithPath: child.path).lastPathComponent + suffix + let name = URL(fileURLWithPath: child.path).lastPathComponent + child.suffix print("\(indent)\(size) \(Term.dim(percentage)) \(Term.bar(fraction: fraction, width: 20)) \(name)\(partial)") if depthLeft > 0 && child.isDir && !child.isPackage { let snapshot = scanFolder(child.path, ignore: ignore) @@ -242,8 +295,8 @@ struct Analyze: ParsableCommand { private func browse(_ target: String, ignore: IgnoreStore) throws { let session = try TerminalSession() defer { session.close() } - session.draw(Self.renderMeasuring(target, width: session.width, height: session.height)) - var levels = [BrowserLevel(snapshot: scanFolder(target, ignore: ignore))] + guard let first = measure(target, ignore: ignore, session: session, drillingDown: false) else { return } + var levels = [BrowserLevel(snapshot: first)] var running = true while running { @@ -272,8 +325,9 @@ struct Analyze: ParsableCommand { levels[index].selected = max(0, levels[index].snapshot.children.count - 1) case .enter, .right: guard let child = Self.focusedChild(levels[index]), child.isDir, !child.isPackage else { continue } - session.draw(Self.renderMeasuring(child.path, width: session.width, height: session.height)) - levels.append(BrowserLevel(snapshot: scanFolder(child.path, ignore: ignore))) + if let snapshot = measure(child.path, ignore: ignore, session: session, drillingDown: true) { + levels.append(BrowserLevel(snapshot: snapshot)) + } case .left, .backspace: if levels.count > 1 { levels.removeLast() } case .escape: @@ -291,17 +345,36 @@ struct Analyze: ParsableCommand { } } - static func renderMeasuring(_ path: String, width: Int, height: Int) -> Buffer { - StatusScreen.render( - title: windowTitle, - message: "Measuring allocated space...", - detail: path, - hint: StatusScreen.cancelHint, - width: width, - height: height + private func measure(_ path: String, ignore: IgnoreStore, session: TerminalSession, drillingDown: Bool) -> FolderSnapshot? { + session.runWithSpinner( + progress: ScanProgress(path: (path as NSString).standardizingPath), + render: { tick, progress in + Self.renderMeasuringBrowser( + progress: progress, tick: tick, drillingDown: drillingDown, + width: session.width, height: session.height + ) + }, + onKey: { key, cancel in + if Self.cancelsMeasuring(key, drillingDown: drillingDown) { cancel.cancel() } + }, + work: { progress, cancel in + let snapshot = scanFolder(path, ignore: ignore, progress: { event in + progress.update { $0.apply(event) } + }, isCancelled: { cancel.isCancelled }) + return cancel.isCancelled ? nil : snapshot + } ) } + static func cancelsMeasuring(_ key: TerminalKey, drillingDown: Bool) -> Bool { + switch key { + case .escape: return true + case .left, .backspace: return drillingDown + case .character(let character): return !drillingDown && character.lowercased() == "q" + default: return false + } + } + private static let windowTitle = "PureMac Space Explorer" private static let focusedLabel = "Focused: " private static let window = Window(title: windowTitle) @@ -312,13 +385,17 @@ struct Analyze: ParsableCommand { private static let headerRows = 2 private static let dividerRows = 1 private static let minimumListRows = 3 + private static let exitKeyHint = KeyHint("q/Esc", "exit") + private static let exitText = "Esc/q exit" private static let browserHints = KeyHints([ KeyHint("↑↓", "move"), KeyHint("Enter/→", "open"), KeyHint("O", "reveal"), KeyHint("←/⌫", "back"), - KeyHint("q/Esc", "exit") + exitKeyHint ]) + private static let firstScanHints = KeyHints([exitKeyHint]) + private static let drillDownHints = KeyHints([KeyHint("←/⌫/Esc", "back")]) private struct BrowserLayout { let header: Rect @@ -332,15 +409,17 @@ struct Analyze: ParsableCommand { var visibleRows: Int { max(1, list.height) } } - private static func layout(snapshot: FolderSnapshot, selected: Int, width: Int, height: Int) -> BrowserLayout { + private static func layout( + snapshot: FolderSnapshot, selected: Int, hints: KeyHints = browserHints, showsPath: Bool = true, width: Int, height: Int + ) -> BrowserLayout { let content = window.contentRect(in: Rect(x: 0, y: 0, width: width, height: height)) let focusedPath = snapshot.children.indices.contains(selected) ? snapshot.children[selected].path : snapshot.path let pathWidth = max(1, content.width - focusedLabel.count) - let hintRows = browserHints.rows(width: content.width).count + let hintRows = hints.rows(width: content.width).count let errorRows = snapshot.errors.isEmpty ? 0 : 1 let spareRows = content.height - headerRows - dividerRows - errorRows - hintRows - minimumListRows var pathLines = Term.wrap(focusedPath, width: pathWidth) - let pathRows = min(pathLines.count, max(1, spareRows)) + let pathRows = showsPath ? min(pathLines.count, max(1, spareRows)) : 0 var budget = pathRows * pathWidth while pathLines.count > pathRows && budget > 1 { pathLines = Term.wrap(Term.truncate(focusedPath, to: budget, middle: true), width: pathWidth) @@ -360,14 +439,65 @@ struct Analyze: ParsableCommand { ) } + private struct Measuring { + let tick: Int + let progress: ScanProgress + let drillingDown: Bool + + var hints: KeyHints { drillingDown ? drillDownHints : firstScanHints } + var exitHint: String { drillingDown ? "Esc back" : exitText } + + var statusSpans: [Span] { + let status = progress.position == 0 ? "Measuring…" : "Measuring \(progress.position) of \(progress.count)" + return [Span(Spinner.frame(tick: tick) + " " + status, TextStyle(dim: true))] + } + + func currentRow(width: Int) -> String? { + guard !progress.name.isEmpty else { return nil } + let suffix = Child.suffix(isDirectory: progress.nameIsDirectory, isPackage: progress.nameIsPackage) + let spinner = Spinner.frame(tick: tick) + " " + return spinner + Term.truncate(progress.name + suffix, to: max(1, width - spinner.count), middle: true) + } + } + + static func renderMeasuringBrowser( + progress: ScanProgress, tick: Int, drillingDown: Bool, width: Int, height: Int + ) -> Buffer { + let children = ranked(progress.measured) + let snapshot = FolderSnapshot( + path: progress.path, + children: children, + total: children.reduce(Int64(0)) { $0 + $1.size }, + inaccessibleCount: 0, + skippedCount: 0, + errors: [] + ) + return render( + level: BrowserLevel(snapshot: snapshot, selected: -1), + measuring: Measuring(tick: tick, progress: progress, drillingDown: drillingDown), + width: width, + height: height + ) + } + static func renderBrowser(level: BrowserLevel, width: Int, height: Int) -> Buffer { + render(level: level, measuring: nil, width: width, height: height) + } + + private static func render(level: BrowserLevel, measuring: Measuring?, width: Int, height: Int) -> Buffer { guard TooSmallScreen.fits(width: width, height: height) else { - return TooSmallScreen.render(title: windowTitle, exitHint: "Esc/q exit", width: width, height: height) + return TooSmallScreen.render( + title: windowTitle, exitHint: measuring?.exitHint ?? exitText, width: width, height: height + ) } var buffer = Buffer(width: width, height: height) let snapshot = level.snapshot + let hints = measuring?.hints ?? browserHints window.render(in: buffer.area, buffer: &buffer) - let layout = layout(snapshot: snapshot, selected: level.selected, width: width, height: height) + let layout = layout( + snapshot: snapshot, selected: level.selected, hints: hints, showsPath: measuring == nil, + width: width, height: height + ) buffer.write( Term.truncate(snapshot.path, to: layout.header.width, middle: true), @@ -376,14 +506,16 @@ struct Analyze: ParsableCommand { style: TextStyle(bold: true) ) buffer.write( - statusLine(snapshot, width: layout.header.width), + measuring?.statusSpans ?? [Span(statusLine(snapshot, width: layout.header.width), TextStyle(dim: true))], x: layout.header.x, y: layout.header.y + 1, - style: TextStyle(dim: true) + maxWidth: layout.header.width ) window.renderDivider(atRow: layout.divider.y, in: buffer.area, buffer: &buffer) - renderRows(level: level, in: layout.list, buffer: &buffer) - Scrollbar(total: snapshot.children.count, visible: layout.visibleRows, offset: level.offset) + let currentRow = measuring?.currentRow(width: layout.list.width) + let capacity = max(0, layout.list.height - (currentRow == nil ? 0 : 1)) + renderRows(level: level, isMeasuring: measuring != nil, currentRow: currentRow, capacity: capacity, in: layout.list, buffer: &buffer) + Scrollbar(total: snapshot.children.count, visible: capacity, offset: level.offset) .render(column: width - 1, rows: layout.list.y..<(layout.list.y + layout.list.height), buffer: &buffer) for (index, line) in layout.pathLines.prefix(layout.path.height).enumerated() { @@ -404,14 +536,21 @@ struct Analyze: ParsableCommand { maxWidth: area.width ) } - browserHints.render(in: layout.footer, buffer: &buffer) + hints.render(in: layout.footer, buffer: &buffer) return buffer } - private static func renderRows(level: BrowserLevel, in list: Rect, buffer: inout Buffer) { + private static func renderRows( + level: BrowserLevel, isMeasuring: Bool, currentRow: String?, capacity: Int, in list: Rect, buffer: inout Buffer + ) { let snapshot = level.snapshot - let upperBound = min(snapshot.children.count, level.offset + list.height) + let upperBound = min(snapshot.children.count, level.offset + capacity) + if let currentRow { + let shown = max(0, upperBound - level.offset) + buffer.write(currentRow, x: list.x, y: list.y + shown, style: TextStyle(dim: true), maxWidth: list.width) + } guard level.offset < upperBound else { + guard !isMeasuring else { return } let inaccessible = snapshot.inaccessibleCount > 0 buffer.write( inaccessible ? "Folder contents are inaccessible." : "No measurable items.", @@ -449,11 +588,10 @@ struct Analyze: ParsableCommand { private static func renderRow(_ child: Child, focused: Bool, total: Int64, in rect: Rect, buffer: inout Buffer) { let fraction = total > 0 ? Double(child.size) / Double(total) : 0 let barWidth = min(maximumGaugeWidth, max(minimumGaugeWidth, (rect.width - gaugeReservedWidth) / 3)) - let suffix = child.isDir && !child.isPackage ? "/" : (child.isPackage ? " [package]" : "") let partial = child.isPartial ? " !" : "" let nameColumn = rect.width - rowPrefixWidth - barWidth let nameWidth = max(1, nameColumn - partial.count) - let name = Term.truncate(URL(fileURLWithPath: child.path).lastPathComponent + suffix, to: nameWidth, middle: true) + let name = Term.truncate(URL(fileURLWithPath: child.path).lastPathComponent + child.suffix, to: nameWidth, middle: true) let rowStyle = TextStyle(inverse: focused) let sizeStyle = SizeLevel.style(bytes: child.size, focused: focused) let gauge = Gauge(fraction: fraction).spans(width: barWidth, filled: sizeStyle).map { diff --git a/cli/Tests/TerminalUITests/BackgroundWorkTests.swift b/cli/Tests/TerminalUITests/BackgroundWorkTests.swift index 0f1520e..928bcb5 100644 --- a/cli/Tests/TerminalUITests/BackgroundWorkTests.swift +++ b/cli/Tests/TerminalUITests/BackgroundWorkTests.swift @@ -4,6 +4,12 @@ import XCTest final class BackgroundWorkTests: XCTestCase { private let wait: DispatchTimeInterval = .seconds(5) + func testUpdateMutatesTheStoredValueInPlace() { + let progress = WorkProgress([1, 2]) + progress.update { $0.append(3) } + XCTAssertEqual(progress.value, [1, 2, 3]) + } + func testRedrawsUntilWorkFinishesAndTickIncreases() { let release = DispatchSemaphore(value: 0) var ticks: [Int] = [] diff --git a/cli/Tests/puremacTests/AnalyzeTests.swift b/cli/Tests/puremacTests/AnalyzeTests.swift index 1a07754..acb9956 100644 --- a/cli/Tests/puremacTests/AnalyzeTests.swift +++ b/cli/Tests/puremacTests/AnalyzeTests.swift @@ -232,13 +232,12 @@ final class AnalyzeTests: XCTestCase { XCTAssertFalse(fitting.contains { $0.contains("┃") }) } - func testHeaderAndMeasuringStyles() { + func testHeaderStyles() { let buffer = Analyze.renderBrowser( level: Analyze.BrowserLevel(snapshot: snapshot(children: manyChildren(3))), width: 60, height: 14 ) XCTAssertTrue(buffer[2, 1].style.bold) XCTAssertTrue(buffer[2, 2].style.dim) - XCTAssertTrue(Analyze.renderMeasuring("/tmp", width: 40, height: 12)[2, 1].style.dim) } func testVisibleRowCountKeepsAtLeastOneRowWhenTooSmall() { @@ -339,21 +338,172 @@ final class AnalyzeTests: XCTestCase { ) } - func testMeasuringScreenShowsWindowWithTruncatedPath() { - let lines = Analyze.renderMeasuring("/Users/example/" + String(repeating: "a", count: 60), width: 40, height: 12).plainLines() + private func measuringProgress( + position: Int = 3, count: Int = 5, name: String = "Library", isPackage: Bool = false, + measured: [Analyze.Child]? = nil + ) -> Analyze.ScanProgress { + Analyze.ScanProgress( + path: "/tmp", position: position, count: count, name: name, nameIsDirectory: true, + nameIsPackage: isPackage, + measured: measured ?? [child("/tmp/small", size: 1_000), child("/tmp/big", size: 5_000)] + ) + } - XCTAssertEqual(lines.count, 12) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) - XCTAssertTrue(lines[0].hasPrefix("╭─ PureMac Space Explorer ")) - XCTAssertTrue(lines[1].contains("Measuring allocated space...")) - XCTAssertTrue(lines[2].contains("…")) - XCTAssertTrue(lines.joined().contains("Ctrl+C cancel")) + private func measuringLines( + _ progress: Analyze.ScanProgress, drillingDown: Bool = false, width: Int = 60, height: Int = 14 + ) -> [String] { + Analyze.renderMeasuringBrowser( + progress: progress, tick: 2, drillingDown: drillingDown, width: width, height: height + ).plainLines() } - func testMeasuringScreenBelowMinimumUsesTooSmallScreen() { + func testScanReportsEachChildBeforeAndAfterMeasuring() throws { + try Data(repeating: 0x41, count: 4_096).write(to: root.appendingPathComponent("a.bin")) + try FileManager.default.createDirectory(at: root.appendingPathComponent("b-dir"), withIntermediateDirectories: true) + try Data(repeating: 0x42, count: 8_192).write(to: root.appendingPathComponent("b-dir/x.bin")) + + var events: [Analyze.ScanEvent] = [] + let snapshot = Analyze().scanFolder(root.path, progress: { events.append($0) }) + + XCTAssertEqual(events.count, 4) + XCTAssertEqual(events[0], .measuring(position: 1, count: 2, name: "a.bin", isDirectory: false, isPackage: false)) + guard case .measured(let first) = events[1] else { return XCTFail("expected measured") } + XCTAssertEqual(URL(fileURLWithPath: first.path).lastPathComponent, "a.bin") + XCTAssertEqual(events[2], .measuring(position: 2, count: 2, name: "b-dir", isDirectory: true, isPackage: false)) + XCTAssertEqual(snapshot, Analyze().scanFolder(root.path)) + } + + func testScanStopsBetweenChildrenWhenCancelled() throws { + for name in ["a.bin", "b.bin", "c.bin"] { + try Data(repeating: 0x41, count: 4_096).write(to: root.appendingPathComponent(name)) + } + var measured = 0 + let snapshot = Analyze().scanFolder( + root.path, + progress: { if case .measured = $0 { measured += 1 } }, + isCancelled: { measured >= 1 } + ) + + XCTAssertEqual(measured, 1) + XCTAssertEqual(snapshot.children.count, 1) + } + + func testScanProgressCollectsEvents() { + var progress = Analyze.ScanProgress(path: "/tmp") + progress.apply(.measuring(position: 2, count: 4, name: "Docs", isDirectory: true, isPackage: true)) + XCTAssertEqual(progress.position, 2) + XCTAssertEqual(progress.count, 4) + XCTAssertEqual(progress.name, "Docs") + XCTAssertTrue(progress.nameIsDirectory) + XCTAssertTrue(progress.nameIsPackage) + progress.apply(.measured(child("/tmp/Docs", size: 10))) + XCTAssertEqual(progress.measured.map(\.path), ["/tmp/Docs"]) + } + + func testMeasuringBrowserShowsSpinnerStatusSortedChildrenAndCurrentName() { + let buffer = Analyze.renderMeasuringBrowser(progress: measuringProgress(), tick: 2, drillingDown: false, width: 60, height: 14) + let lines = buffer.plainLines() + + XCTAssertEqual(lines[0], "╭─ PureMac Space Explorer ─────────────────────────────────╮") + XCTAssertEqual(lines[1], "│ /tmp │") + XCTAssertEqual(lines[2], "│ ⠹ Measuring 3 of 5 │") + XCTAssertTrue(lines[3].contains("big/")) + XCTAssertTrue(lines[4].contains("small/")) + XCTAssertEqual(lines[5], "│ ⠹ Library/ │") + XCTAssertTrue(buffer[2, 2].style.dim) + XCTAssertTrue(buffer[2, 5].style.dim) + XCTAssertFalse(lines.joined().contains("No measurable items.")) + XCTAssertFalse(buffer[2, 3].style.inverse) + } + + func testMeasuringBrowserBeforeFirstChildAndForFiles() { + let start = Analyze.renderMeasuringBrowser( + progress: Analyze.ScanProgress(path: "/tmp"), tick: 0, drillingDown: false, width: 60, height: 14 + ).plainLines() + XCTAssertEqual(start[2], "│ ⠋ Measuring… │") + XCTAssertEqual(start[3], "│ │") + + var file = measuringProgress(name: "notes.txt", measured: []) + file.nameIsDirectory = false XCTAssertEqual( - Analyze.renderMeasuring("/tmp", width: 39, height: 11), - TooSmallScreen.render(title: "PureMac Space Explorer", exitHint: "Ctrl+C cancel", width: 39, height: 11) + Analyze.renderMeasuringBrowser(progress: file, tick: 0, drillingDown: false, width: 60, height: 14).plainLines()[3], + "│ ⠋ notes.txt │" ) } + + func testMeasuringBrowserBelowMinimumUsesTooSmallScreen() { + XCTAssertEqual( + Analyze.renderMeasuringBrowser(progress: measuringProgress(), tick: 0, drillingDown: false, width: 39, height: 11), + TooSmallScreen.render(title: "PureMac Space Explorer", exitHint: "Esc/q exit", width: 39, height: 11) + ) + XCTAssertEqual( + Analyze.renderMeasuringBrowser(progress: measuringProgress(), tick: 0, drillingDown: true, width: 39, height: 11), + TooSmallScreen.render(title: "PureMac Space Explorer", exitHint: "Esc back", width: 39, height: 11) + ) + } + + func testMeasuringBrowserKeepsCurrentRowWhenMoreChildrenThanRows() { + let many = (0..<40).map { child("/tmp/item-\($0)", size: Int64(1_000 - $0)) } + let lines = measuringLines(measuringProgress(measured: many)) + let currentIndex = lines.firstIndex { $0.contains("⠹ Library/") } + + XCTAssertNotNil(currentIndex) + XCTAssertTrue(lines[currentIndex! - 1].contains("item-")) + XCTAssertTrue(lines[currentIndex! + 1].hasPrefix("├")) + XCTAssertTrue(lines.joined().contains("item-0/")) + XCTAssertFalse(lines.joined().contains("item-39/")) + } + + func testMeasuringBrowserScrollbarMatchesDrawnRowsAndPathRowIsHidden() { + let lines0 = measuringLines(measuringProgress(measured: []), width: 40, height: 12) + XCTAssertFalse(lines0.joined().contains("Focused:")) + let divider = lines0.firstIndex { $0.hasPrefix("├") }! + let listRows = divider - 3 + for count in [listRows - 1, listRows, listRows + 4] { + let many = (0.. Date: Mon, 19 Oct 2026 13:07:31 +0000 Subject: [PATCH 09/21] feat(cli): ask before measuring the home folder from the menu --- cli/Sources/puremac/Commands/Analyze.swift | 41 +++++++--- cli/Sources/puremac/Core/ButtonFocus.swift | 24 ++++++ .../puremac/Core/ExploreConfirmation.swift | 62 +++++++++++++++ .../puremac/Core/InteractiveReview.swift | 31 ++------ cli/Sources/puremac/Core/StatusScreen.swift | 1 + cli/Sources/puremac/PureMac.swift | 30 +++---- cli/Tests/puremacTests/AnalyzeTests.swift | 21 +++-- cli/Tests/puremacTests/ButtonFocusTests.swift | 39 +++++++++ .../ExploreConfirmationTests.swift | 79 +++++++++++++++++++ .../InteractiveScreensTests.swift | 12 +-- 10 files changed, 276 insertions(+), 64 deletions(-) create mode 100644 cli/Sources/puremac/Core/ButtonFocus.swift create mode 100644 cli/Sources/puremac/Core/ExploreConfirmation.swift create mode 100644 cli/Tests/puremacTests/ButtonFocusTests.swift create mode 100644 cli/Tests/puremacTests/ExploreConfirmationTests.swift diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index 6e9aa88..a55c14e 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -295,7 +295,7 @@ struct Analyze: ParsableCommand { private func browse(_ target: String, ignore: IgnoreStore) throws { let session = try TerminalSession() defer { session.close() } - guard let first = measure(target, ignore: ignore, session: session, drillingDown: false) else { return } + guard case .snapshot(let first) = measure(target, ignore: ignore, session: session, drillingDown: false) else { return } var levels = [BrowserLevel(snapshot: first)] var running = true @@ -325,8 +325,10 @@ struct Analyze: ParsableCommand { levels[index].selected = max(0, levels[index].snapshot.children.count - 1) case .enter, .right: guard let child = Self.focusedChild(levels[index]), child.isDir, !child.isPackage else { continue } - if let snapshot = measure(child.path, ignore: ignore, session: session, drillingDown: true) { - levels.append(BrowserLevel(snapshot: snapshot)) + switch measure(child.path, ignore: ignore, session: session, drillingDown: true) { + case .snapshot(let snapshot): levels.append(BrowserLevel(snapshot: snapshot)) + case .cancelled: break + case .exit: running = false } case .left, .backspace: if levels.count > 1 { levels.removeLast() } @@ -345,8 +347,13 @@ struct Analyze: ParsableCommand { } } - private func measure(_ path: String, ignore: IgnoreStore, session: TerminalSession, drillingDown: Bool) -> FolderSnapshot? { - session.runWithSpinner( + private enum MeasureResult { + case snapshot(FolderSnapshot), cancelled, exit + } + + private func measure(_ path: String, ignore: IgnoreStore, session: TerminalSession, drillingDown: Bool) -> MeasureResult { + var exitRequested = false + let snapshot = session.runWithSpinner( progress: ScanProgress(path: (path as NSString).standardizingPath), render: { tick, progress in Self.renderMeasuringBrowser( @@ -355,7 +362,9 @@ struct Analyze: ParsableCommand { ) }, onKey: { key, cancel in - if Self.cancelsMeasuring(key, drillingDown: drillingDown) { cancel.cancel() } + guard let action = Self.measuringKeyAction(key, drillingDown: drillingDown) else { return } + if action == .exit { exitRequested = true } + cancel.cancel() }, work: { progress, cancel in let snapshot = scanFolder(path, ignore: ignore, progress: { event in @@ -364,14 +373,20 @@ struct Analyze: ParsableCommand { return cancel.isCancelled ? nil : snapshot } ) + if exitRequested { return .exit } + return snapshot.map(MeasureResult.snapshot) ?? .cancelled + } + + enum MeasureKeyAction: Equatable { + case back, exit } - static func cancelsMeasuring(_ key: TerminalKey, drillingDown: Bool) -> Bool { + static func measuringKeyAction(_ key: TerminalKey, drillingDown: Bool) -> MeasureKeyAction? { switch key { - case .escape: return true - case .left, .backspace: return drillingDown - case .character(let character): return !drillingDown && character.lowercased() == "q" - default: return false + case .escape: return drillingDown ? .back : .exit + case .left, .backspace: return drillingDown ? .back : nil + case .character(let character): return character.lowercased() == "q" ? .exit : nil + default: return nil } } @@ -395,7 +410,7 @@ struct Analyze: ParsableCommand { exitKeyHint ]) private static let firstScanHints = KeyHints([exitKeyHint]) - private static let drillDownHints = KeyHints([KeyHint("←/⌫/Esc", "back")]) + private static let drillDownHints = KeyHints([KeyHint("←/⌫/Esc", "back"), KeyHint("q", "exit")]) private struct BrowserLayout { let header: Rect @@ -445,7 +460,7 @@ struct Analyze: ParsableCommand { let drillingDown: Bool var hints: KeyHints { drillingDown ? drillDownHints : firstScanHints } - var exitHint: String { drillingDown ? "Esc back" : exitText } + var exitHint: String { drillingDown ? "Esc back q exit" : exitText } var statusSpans: [Span] { let status = progress.position == 0 ? "Measuring…" : "Measuring \(progress.position) of \(progress.count)" diff --git a/cli/Sources/puremac/Core/ButtonFocus.swift b/cli/Sources/puremac/Core/ButtonFocus.swift new file mode 100644 index 0000000..7da8e59 --- /dev/null +++ b/cli/Sources/puremac/Core/ButtonFocus.swift @@ -0,0 +1,24 @@ +import TerminalUI + +struct ButtonFocus { + let count: Int + private(set) var index: Int + + mutating func move(_ delta: Int) { + index = min(count - 1, max(0, index + delta)) + } + + mutating func cycle() { + index = (index + 1) % count + } + + mutating func navigate(_ key: TerminalKey) -> Bool { + switch key { + case .left: move(-1) + case .right: move(1) + case .tab: cycle() + default: return false + } + return true + } +} diff --git a/cli/Sources/puremac/Core/ExploreConfirmation.swift b/cli/Sources/puremac/Core/ExploreConfirmation.swift new file mode 100644 index 0000000..1bf681e --- /dev/null +++ b/cli/Sources/puremac/Core/ExploreConfirmation.swift @@ -0,0 +1,62 @@ +import TerminalUI + +enum ExploreChoice: Equatable { + case start, back +} + +struct ExploreConfirmation { + private static let buttons = [DialogButton("Cancel"), DialogButton("Start")] + static let startIndex = buttons.count - 1 + + private(set) var focus = ButtonFocus(count: buttons.count, index: startIndex) + + mutating func handle(_ key: TerminalKey) -> ExploreChoice? { + if focus.navigate(key) { return nil } + switch key { + case .enter: + return focus.index == Self.startIndex ? .start : .back + case .escape: + return .back + case .character(let character): + switch String(character).lowercased() { + case "s": return .start + case "q", "n": return .back + default: return nil + } + default: + return nil + } + } + + func render(width: Int, height: Int) -> Buffer { + let menu = TerminalMenu.render( + title: HomeMenu.title, + subtitle: HomeMenu.subtitle, + options: HomeMenu.options, + selection: HomeMenu.exploreIndex, + width: width, + height: height + ) + return StatusScreen.overlay(dialog, on: menu, tooSmallExitHint: "Esc back") + } + + static func ask() throws -> Bool { + let session = try TerminalSession() + defer { session.close() } + var model = ExploreConfirmation() + while true { + session.draw(model.render(width: session.width, height: session.height)) + if let choice = model.handle(session.readKey()) { return choice == .start } + } + } + + private var dialog: Dialog { + Dialog( + title: "Explore your home folder?", + message: [Span("Measuring every folder can take a few minutes.")], + buttons: Self.buttons, + focusedButton: focus.index, + hints: StatusScreen.choiceHints + ) + } +} diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index 12b5a0c..beed0fb 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -13,7 +13,7 @@ enum ReviewDisplayRow { case item(ReviewAddress) } -enum ConfirmationButton: Int { +enum ConfirmationButton: Int, CaseIterable { case cancel, remove } @@ -157,26 +157,14 @@ struct InteractiveReviewModel { confirmation = nil } - mutating func moveConfirmationFocus(_ delta: Int) { - guard let current = confirmation else { return } - let moved = min(ConfirmationButton.remove.rawValue, max(ConfirmationButton.cancel.rawValue, current.rawValue + delta)) - confirmation = ConfirmationButton(rawValue: moved) - } - - mutating func cycleConfirmationFocus() { - guard let current = confirmation else { return } - confirmation = current == .cancel ? .remove : .cancel - } - mutating func handleConfirmationKey(_ key: TerminalKey) -> ReviewKeyRoute { guard let focused = confirmation else { return .passthrough } + var buttons = ButtonFocus(count: ConfirmationButton.allCases.count, index: focused.rawValue) + if buttons.navigate(key) { + confirmation = ConfirmationButton(rawValue: buttons.index) + return .handled + } switch key { - case .left: - moveConfirmationFocus(-1) - case .right: - moveConfirmationFocus(1) - case .tab: - cycleConfirmationFocus() case .enter: if focused == .remove { return .remove } cancelConfirmation() @@ -418,15 +406,10 @@ enum InteractiveReview { message: message, buttons: [DialogButton("Cancel"), DialogButton("Remove", role: .destructive)], focusedButton: focus.rawValue, - hints: KeyHints(confirmationHints) + hints: StatusScreen.choiceHints ) } - private static let confirmationHints = [ - KeyHint("Enter", "select"), - KeyHint("Esc", "back") - ] - private static let selectHints = [ KeyHint("↑↓", "move"), KeyHint("←→", "path"), diff --git a/cli/Sources/puremac/Core/StatusScreen.swift b/cli/Sources/puremac/Core/StatusScreen.swift index 27819ee..af341d4 100644 --- a/cli/Sources/puremac/Core/StatusScreen.swift +++ b/cli/Sources/puremac/Core/StatusScreen.swift @@ -4,6 +4,7 @@ enum StatusScreen { static let warningTitle = TextStyle(color: .yellow, bold: true) static let cancelHint = KeyHint("Ctrl+C", "cancel") static let warningBorder = TextStyle(color: .yellow) + static let choiceHints = KeyHints([KeyHint("Enter", "select"), KeyHint("Esc", "back")]) static func render( title: String, diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index c85ea08..18e38bf 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -28,20 +28,20 @@ struct PureMac: ParsableCommand { } enum HomeMenu { + static let title = "PureMac" + static let subtitle = "Your Mac, with room to work. / \(puremacVersion)" + static let exploreIndex = 2 + static let options: [(title: String, detail: String)] = [ + ("Clean caches", "Choose tools and individual paths to remove"), + ("Project cleanup", "Review dependencies and generated build artifacts"), + ("Explore storage", "Browse folders and find what takes up space"), + ("System status", "Inspect memory and available disk space"), + ("Preferences", "View cleanup settings and configuration paths"), + ("Protected paths", "View folders excluded from cleanup") + ] + static func run() throws { - let options: [(title: String, detail: String)] = [ - ("Clean caches", "Choose tools and individual paths to remove"), - ("Project cleanup", "Review dependencies and generated build artifacts"), - ("Explore storage", "Browse folders and find what takes up space"), - ("System status", "Inspect memory and available disk space"), - ("Preferences", "View cleanup settings and configuration paths"), - ("Protected paths", "View folders excluded from cleanup") - ] - while let choice = try TerminalMenu.choose( - title: "PureMac", - subtitle: "Your Mac, with room to work. / \(puremacVersion)", - options: options - ) { + while let choice = try TerminalMenu.choose(title: title, subtitle: subtitle, options: options) { switch choice { case 0: guard let category = try TerminalMenu.choose( @@ -58,7 +58,9 @@ enum HomeMenu { let arguments = [[], ["dev"], ["junk"], ["ai"], ["trash"]] try Clean.parse(arguments[category]).run() case 1: try Purge.parse([]).run() - case 2: try Analyze.parse([]).run() + case exploreIndex: + guard try ExploreConfirmation.ask() else { continue } + try Analyze.parse([]).run() case 3: try Optimize.parse([]).run() case 4: try Config.parse([]).run() case 5: try Ignore.List.parse([]).run() diff --git a/cli/Tests/puremacTests/AnalyzeTests.swift b/cli/Tests/puremacTests/AnalyzeTests.swift index acb9956..e352588 100644 --- a/cli/Tests/puremacTests/AnalyzeTests.swift +++ b/cli/Tests/puremacTests/AnalyzeTests.swift @@ -438,7 +438,7 @@ final class AnalyzeTests: XCTestCase { ) XCTAssertEqual( Analyze.renderMeasuringBrowser(progress: measuringProgress(), tick: 0, drillingDown: true, width: 39, height: 11), - TooSmallScreen.render(title: "PureMac Space Explorer", exitHint: "Esc back", width: 39, height: 11) + TooSmallScreen.render(title: "PureMac Space Explorer", exitHint: "Esc back q exit", width: 39, height: 11) ) } @@ -478,6 +478,7 @@ final class AnalyzeTests: XCTestCase { let drill = measuringLines(measuringProgress(), drillingDown: true).joined(separator: "\n") XCTAssertTrue(drill.contains("←/⌫/Esc back")) + XCTAssertTrue(drill.contains("q exit")) XCTAssertFalse(drill.contains("q/Esc")) XCTAssertFalse(drill.contains("reveal")) } @@ -492,18 +493,24 @@ final class AnalyzeTests: XCTestCase { XCTAssertTrue(row.contains("aaa")) } - func testWhichKeysCancelAMeasurement() { + func testMeasuringKeyActionInTheFirstScan() { for key in [TerminalKey.escape, .character("q"), .character("Q")] { - XCTAssertTrue(Analyze.cancelsMeasuring(key, drillingDown: false)) + XCTAssertEqual(Analyze.measuringKeyAction(key, drillingDown: false), .exit) } for key in [TerminalKey.left, .up, .enter, .backspace, .character("o")] { - XCTAssertFalse(Analyze.cancelsMeasuring(key, drillingDown: false)) + XCTAssertNil(Analyze.measuringKeyAction(key, drillingDown: false)) } + } + + func testMeasuringKeyActionInADrillDown() { for key in [TerminalKey.escape, .left, .backspace] { - XCTAssertTrue(Analyze.cancelsMeasuring(key, drillingDown: true)) + XCTAssertEqual(Analyze.measuringKeyAction(key, drillingDown: true), .back) + } + for key in [TerminalKey.character("q"), .character("Q")] { + XCTAssertEqual(Analyze.measuringKeyAction(key, drillingDown: true), .exit) } - for key in [TerminalKey.character("q"), .right, .enter, .down] { - XCTAssertFalse(Analyze.cancelsMeasuring(key, drillingDown: true)) + for key in [TerminalKey.right, .enter, .down, .character("o")] { + XCTAssertNil(Analyze.measuringKeyAction(key, drillingDown: true)) } } } diff --git a/cli/Tests/puremacTests/ButtonFocusTests.swift b/cli/Tests/puremacTests/ButtonFocusTests.swift new file mode 100644 index 0000000..804ba9e --- /dev/null +++ b/cli/Tests/puremacTests/ButtonFocusTests.swift @@ -0,0 +1,39 @@ +import XCTest +import TerminalUI +@testable import puremac + +final class ButtonFocusTests: XCTestCase { + func testMovesWithClamping() { + var focus = ButtonFocus(count: 2, index: 0) + focus.move(-1) + XCTAssertEqual(focus.index, 0) + focus.move(1) + XCTAssertEqual(focus.index, 1) + focus.move(1) + XCTAssertEqual(focus.index, 1) + focus.move(-1) + XCTAssertEqual(focus.index, 0) + } + + func testCycleWraps() { + var focus = ButtonFocus(count: 2, index: 0) + focus.cycle() + XCTAssertEqual(focus.index, 1) + focus.cycle() + XCTAssertEqual(focus.index, 0) + } + + func testNavigateHandlesOnlyLeftRightAndTab() { + var focus = ButtonFocus(count: 2, index: 0) + XCTAssertTrue(focus.navigate(.right)) + XCTAssertEqual(focus.index, 1) + XCTAssertTrue(focus.navigate(.left)) + XCTAssertEqual(focus.index, 0) + XCTAssertTrue(focus.navigate(.tab)) + XCTAssertEqual(focus.index, 1) + for key in [TerminalKey.enter, .escape, .up, .character("q")] { + XCTAssertFalse(focus.navigate(key)) + XCTAssertEqual(focus.index, 1) + } + } +} diff --git a/cli/Tests/puremacTests/ExploreConfirmationTests.swift b/cli/Tests/puremacTests/ExploreConfirmationTests.swift new file mode 100644 index 0000000..f9a2a0d --- /dev/null +++ b/cli/Tests/puremacTests/ExploreConfirmationTests.swift @@ -0,0 +1,79 @@ +import XCTest +import TerminalUI +@testable import puremac + +final class ExploreConfirmationTests: XCTestCase { + func testEnterActivatesTheFocusedButton() { + var model = ExploreConfirmation() + XCTAssertEqual(model.handle(.enter), .start) + XCTAssertNil(model.handle(.left)) + XCTAssertEqual(model.handle(.enter), .back) + } + + func testLeftRightClampAndTabCycles() { + var model = ExploreConfirmation() + XCTAssertNil(model.handle(.right)) + XCTAssertEqual(model.handle(.enter), .start) + XCTAssertNil(model.handle(.left)) + XCTAssertNil(model.handle(.left)) + XCTAssertEqual(model.handle(.enter), .back) + XCTAssertNil(model.handle(.tab)) + XCTAssertEqual(model.handle(.enter), .start) + XCTAssertNil(model.handle(.tab)) + XCTAssertEqual(model.handle(.enter), .back) + } + + func testEscapeQAndNGoBackFromAnyFocus() { + for key in [TerminalKey.escape, .character("q"), .character("Q"), .character("n"), .character("N")] { + var model = ExploreConfirmation() + XCTAssertEqual(model.handle(key), .back) + } + } + + func testSStartsFromAnyFocus() { + var model = ExploreConfirmation() + _ = model.handle(.left) + XCTAssertEqual(model.handle(.character("s")), .start) + XCTAssertEqual(model.handle(.character("S")), .start) + } + + func testOtherKeysDoNothing() { + var model = ExploreConfirmation() + for key in [TerminalKey.up, .down, .space, .character("x"), .character("y")] { + XCTAssertNil(model.handle(key)) + } + XCTAssertEqual(model.handle(.enter), .start) + } + + func testRendersTheDialogOverTheFadedMenu() { + let buffer = ExploreConfirmation().render(width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertEqual(lines.count, 24) + XCTAssertTrue(lines.contains { $0.contains("Explore your home folder?") }) + XCTAssertTrue(lines.contains { $0.contains("Measuring every folder can take a few minutes.") }) + XCTAssertTrue(lines.contains { $0.contains("[ Cancel ] › Start ‹") }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + let menuRow = lines.firstIndex { $0.contains("Clean caches") } + XCTAssertNotNil(menuRow) + XCTAssertEqual(buffer[2, menuRow ?? 0].style, TextStyle(dim: true)) + } + + func testFocusFollowsTheModel() { + var model = ExploreConfirmation() + _ = model.handle(.left) + let lines = model.render(width: 80, height: 24).plainLines() + XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Start ]") }) + } + + func testFitsTheMinimumSize() { + let lines = ExploreConfirmation().render(width: 40, height: 12).plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + } + + func testBelowTheMinimumSizeShowsWhatEscDoes() { + let lines = ExploreConfirmation().render(width: 39, height: 11).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Esc back") }) + } +} diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index ea384fa..4cdc57c 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -402,20 +402,20 @@ final class InteractiveScreensTests: XCTestCase { func testConfirmationFocusMovesWithClamping() { var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) - model.moveConfirmationFocus(-1) + _ = model.handleConfirmationKey(.left) XCTAssertEqual(model.confirmation, .cancel) - model.moveConfirmationFocus(1) + _ = model.handleConfirmationKey(.right) XCTAssertEqual(model.confirmation, .remove) - model.moveConfirmationFocus(1) + _ = model.handleConfirmationKey(.right) XCTAssertEqual(model.confirmation, .remove) - model.moveConfirmationFocus(-1) + _ = model.handleConfirmationKey(.left) XCTAssertEqual(model.confirmation, .cancel) } func testCancelConfirmationReturnsToSelectionAndReopensOnCancel() { var model = selectedModel() XCTAssertTrue(model.beginConfirmation()) - model.moveConfirmationFocus(1) + _ = model.handleConfirmationKey(.right) model.cancelConfirmation() XCTAssertFalse(model.isConfirming) XCTAssertTrue(model.beginConfirmation()) @@ -549,7 +549,7 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertTrue(cancelFocused.contains("\u{1B}[7m› Cancel ‹")) XCTAssertTrue(cancelFocused.contains("\u{1B}[31m[ Remove ]")) - model.moveConfirmationFocus(1) + _ = model.handleConfirmationKey(.right) let removeFocused = renderReview(model, width: 80, height: 24).lines(colors: true).joined() XCTAssertTrue(removeFocused.contains("\u{1B}[7;31m› Remove ‹")) XCTAssertFalse(removeFocused.contains("\u{1B}[7m› Cancel ‹")) From c8f99daa63a73d0dd557b3c0393ade0352d37fbb Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 13:24:47 +0000 Subject: [PATCH 10/21] feat(cli): show memory pressure and storage gauges in system status --- cli/Sources/TerminalUI/Term.swift | 2 +- cli/Sources/puremac/Commands/Optimize.swift | 136 +++++++++---- cli/Sources/puremac/Core/InfoSheet.swift | 112 +++++++++++ cli/Sources/puremac/Core/SystemInfo.swift | 55 ++++++ cli/Tests/puremacTests/InfoSheetTests.swift | 141 +++++++++++++ .../puremacTests/OptimizeConfigTests.swift | 186 ++++++++++++++++++ 6 files changed, 589 insertions(+), 43 deletions(-) create mode 100644 cli/Sources/puremac/Core/InfoSheet.swift create mode 100644 cli/Tests/puremacTests/InfoSheetTests.swift diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 0bd9156..046ef48 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -164,7 +164,7 @@ extension Term { return lines.isEmpty ? [""] : lines } - static func wordWrap(_ string: String, width: Int) -> [String] { + public static func wordWrap(_ string: String, width: Int) -> [String] { var lines: [String] = [] var current = "" var gap = "" diff --git a/cli/Sources/puremac/Commands/Optimize.swift b/cli/Sources/puremac/Commands/Optimize.swift index 0a0497d..69827b9 100644 --- a/cli/Sources/puremac/Commands/Optimize.swift +++ b/cli/Sources/puremac/Commands/Optimize.swift @@ -30,29 +30,107 @@ struct Optimize: ParsableCommand { func run() throws { switch task ?? "status" { case "ram": - try showMemory(includeHeading: true) - print("") - print(Term.dim("No memory was purged. macOS reclaims inactive memory when applications need it.")) + Self.printPlain(Self.memorySheet(try SystemInfo.memoryStatus(), pressure: SystemInfo.memoryPressure()), withHeader: false) case "purgeable": - try showStorage(includeHeading: true) - print("") - print(Term.dim("No storage was changed. APFS managed capacity is an estimate controlled by macOS.")) + Self.printPlain(Self.storageSheet(try SystemInfo.volumeStatus("/")), withHeader: false) case "snapshots": try showSnapshots() default: - print(Term.bold("Mac status")) - print(Term.dim("Read-only measurements from macOS")) - print("") - try showMemory(includeHeading: true) - print("") - try showStorage(includeHeading: true) - print("") - print(" " + Term.dim("Uptime") + " " + Self.formatUptime(ProcessInfo.processInfo.systemUptime)) - print("") - print(Term.dim("No maintenance ran. Use `puremac clean --dry-run` to review removable files.")) + let memory = try SystemInfo.memoryStatus() + let volume = try SystemInfo.volumeStatus("/") + Self.printPlain(Self.statusSheet( + memory: memory, + pressure: SystemInfo.memoryPressure(), + volume: volume, + uptime: ProcessInfo.processInfo.systemUptime + )) } } + static func statusSheet( + memory: MemoryStatus, + pressure: MemoryPressure?, + volume: VolumeStatus, + uptime: TimeInterval + ) -> InfoSheet { + InfoSheet( + title: "Mac status", + subtitle: "Read-only measurements from macOS", + sections: [ + memorySection(memory, pressure: pressure), + storageSection(volume), + InfoSection(title: nil, rows: [.message([Span("Uptime", TextStyle(dim: true)), Span(" " + formatUptime(uptime))])]), + ], + footnote: "No maintenance ran. Use `puremac clean --dry-run` to review removable files." + ) + } + + static func memorySheet(_ status: MemoryStatus, pressure: MemoryPressure?) -> InfoSheet { + InfoSheet( + title: "Memory", + sections: [memorySection(status, pressure: pressure)], + footnote: "No memory was purged. macOS reclaims inactive memory when applications need it." + ) + } + + static func storageSheet(_ status: VolumeStatus) -> InfoSheet { + InfoSheet( + title: "Storage", + sections: [storageSection(status)], + footnote: "No storage was changed. APFS managed capacity is an estimate controlled by macOS." + ) + } + + static func memorySection(_ status: MemoryStatus, pressure: MemoryPressure?) -> InfoSection { + let used = ByteCount.human(status.total - status.free) + var rows: [InfoRow] = [ + .gauge( + fraction: status.usedFraction, + color: pressure?.color, + text: "\(used) in use of \(ByteCount.human(status.total))" + ) + ] + if let pressure { + rows.append(.metric(label: "Pressure", value: [Span(pressure.label, TextStyle(color: pressure.color))], note: nil)) + } + rows += [ + metric("Installed", ByteCount.human(status.total)), + metric("Free now", ByteCount.human(status.free)), + metric("Active", ByteCount.human(status.active)), + metric("Inactive", ByteCount.human(status.inactive)), + metric("Compressed", ByteCount.human(status.compressed)), + metric("Wired", ByteCount.human(status.wired)), + ] + return InfoSection(title: "Memory", rows: rows) + } + + static func storageSection(_ status: VolumeStatus) -> InfoSection { + let color = status.freeColor + var rows: [InfoRow] = [ + .gauge( + fraction: status.usedFraction, + color: color, + text: "\(ByteCount.human(status.availableNow)) free of \(ByteCount.human(status.total))" + ), + .metric(label: "Free now", value: [Span(ByteCount.human(status.availableNow), TextStyle(color: color))], note: nil), + metric("Total", ByteCount.human(status.total)), + metric("Managed by macOS", ByteCount.human(status.systemManagedCapacity)), + ] + if status.systemManagedCapacity > 0 { + let note = "Managed capacity may include purgeable files and is not guaranteed free space." + rows.append(.message([Span(note, TextStyle(dim: true))])) + } + return InfoSection(title: "Storage", rows: rows) + } + + private static func metric(_ label: String, _ value: String) -> InfoRow { + .metric(label: label, value: [Span(value)], note: nil) + } + + private static func printPlain(_ sheet: InfoSheet, withHeader: Bool = true) { + for line in sheet.plainLines(withHeader: withHeader) { print(line) } + } + static func parseLocalSnapshots(_ output: String) -> [String] { let snapshots = output.split(whereSeparator: \Character.isNewline) .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } @@ -89,28 +167,6 @@ struct Optimize: ParsableCommand { return "\(minutes)m" } - private func showMemory(includeHeading: Bool) throws { - let status = try SystemInfo.memoryStatus() - if includeHeading { print(Term.bold("Memory")) } - printMetric("Installed", ByteCount.human(status.total)) - printMetric("Free now", ByteCount.human(status.free)) - printMetric("Active", ByteCount.human(status.active)) - printMetric("Inactive", ByteCount.human(status.inactive)) - printMetric("Compressed", ByteCount.human(status.compressed)) - printMetric("Wired", ByteCount.human(status.wired)) - } - - private func showStorage(includeHeading: Bool) throws { - let status = try SystemInfo.volumeStatus("/") - if includeHeading { print(Term.bold("Storage")) } - printMetric("Free now", ByteCount.human(status.availableNow)) - printMetric("Total", ByteCount.human(status.total)) - printMetric("Managed by macOS", ByteCount.human(status.systemManagedCapacity)) - if status.systemManagedCapacity > 0 { - print(Term.dim(" Managed capacity may include purgeable files and is not guaranteed free space.")) - } - } - private func showSnapshots() throws { let result = Shell.run("/usr/bin/tmutil", ["listlocalsnapshots", "/"]) guard result.status == 0 else { @@ -129,8 +185,4 @@ struct Optimize: ParsableCommand { print("") print(Term.dim("Read-only list. Snapshot storage is managed by Time Machine and macOS.")) } - - private func printMetric(_ label: String, _ value: String) { - print(" \(label.padding(toLength: 17, withPad: " ", startingAt: 0)) \(value)") - } } diff --git a/cli/Sources/puremac/Core/InfoSheet.swift b/cli/Sources/puremac/Core/InfoSheet.swift new file mode 100644 index 0000000..515a3be --- /dev/null +++ b/cli/Sources/puremac/Core/InfoSheet.swift @@ -0,0 +1,112 @@ +import TerminalUI + +struct InfoSheet { + var title: String + var subtitle: String? + var sections: [InfoSection] + var footnote: String? + + private static let backHint = KeyHint("Esc", "back") + private static let hints = KeyHints([KeyHint("↑↓", "scroll"), backHint]) + private static let labelWidth = 17 + private static let gaugeWidth = 20 + + func plainLines(withHeader: Bool = true, colors: Bool = Term.colorEnabled) -> [String] { + var lines: [[Span]] = [] + if withHeader { + lines.append([Span(title, TextStyle(bold: true))]) + if let subtitle { lines.append([Span(subtitle, TextStyle(dim: true))]) } + lines.append([]) + } + return (lines + bodyLines()).map { Self.line($0, colors: colors) } + } + + func render(width: Int, height: Int, offset: Int) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: title, exitHint: "\(Self.backHint.key) \(Self.backHint.action)", width: width, height: height) + } + var buffer = Buffer(width: width, height: height) + let window = Window(title: title) + let content = window.render(in: buffer.area, buffer: &buffer) + let areas = content.splitRows([.fill, .length(1), .length(Self.hints.rows(width: content.width).count)]) + let (list, divider, footer) = (areas[0], areas[1], areas[2]) + + var lines = bodyLines(wrappingTo: list.width) + if let subtitle { lines = Self.wrapped(subtitle, style: TextStyle(dim: true), indent: "", width: list.width) + [[]] + lines } + let start = max(0, min(offset, lines.count - list.height)) + for (index, spans) in lines.dropFirst(start).prefix(list.height).enumerated() { + Self.write(spans, in: Rect(x: list.x, y: list.y + index, width: list.width, height: 1), buffer: &buffer) + } + Scrollbar(total: lines.count, visible: list.height, offset: start) + .render(column: width - 1, rows: list.y..<(list.y + list.height), buffer: &buffer) + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + Self.hints.render(in: footer, buffer: &buffer) + return buffer + } + + private func bodyLines(wrappingTo width: Int? = nil) -> [[Span]] { + var lines: [[Span]] = [] + for section in sections { + if !lines.isEmpty { lines.append([]) } + if let title = section.title { lines.append([Span(title, TextStyle(bold: true))]) } + lines += section.rows.flatMap { Self.lines($0, wrappingTo: width) } + } + if let footnote { + lines.append([]) + lines += width.map { Self.wrapped(footnote, style: TextStyle(dim: true), indent: "", width: $0) } + ?? [[Span(footnote, TextStyle(dim: true))]] + } + return lines + } + + private static func lines(_ row: InfoRow, wrappingTo width: Int?) -> [[Span]] { + if let width, case .message(let spans) = row, spans.count == 1 { + return wrapped(spans[0].text, style: spans[0].style, indent: " ", width: width) + } + return [spans(row)] + } + + private static func wrapped(_ text: String, style: TextStyle, indent: String, width: Int) -> [[Span]] { + Term.wordWrap(text, width: max(1, width - indent.count)).map { [Span(indent), Span($0, style)] } + } + + private static func spans(_ row: InfoRow) -> [Span] { + switch row { + case .metric(let label, let value, let note): + let labelSpan = Span(Term.pad(label, to: labelWidth), TextStyle(dim: true)) + let noteSpans = note.map { [Span(" "), Span($0, TextStyle(dim: true))] } ?? [] + return [Span(" "), labelSpan, Span(" ")] + value + noteSpans + case .gauge(let fraction, let color, let text): + let filled = color.map { TextStyle(color: $0) } ?? .plain + return [Span(" ")] + Gauge(fraction: fraction).spans(width: gaugeWidth, filled: filled) + [Span(" " + text)] + case .message(let spans): + return [Span(" ")] + spans + } + } + + private static func line(_ spans: [Span], colors: Bool) -> String { + var buffer = Buffer(width: Term.displayWidth(spans), height: 1) + buffer.write(spans, x: 0, y: 0) + return buffer.lines(colors: colors)[0] + } + + private static func write(_ spans: [Span], in rect: Rect, buffer: inout Buffer) { + guard Term.displayWidth(spans) > rect.width else { + buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width) + return + } + let used = buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width - 1) + buffer.write("…", x: rect.x + used, y: rect.y) + } +} + +struct InfoSection { + var title: String? + var rows: [InfoRow] +} + +enum InfoRow { + case metric(label: String, value: [Span], note: String?) + case gauge(fraction: Double, color: TerminalColor?, text: String) + case message([Span]) +} diff --git a/cli/Sources/puremac/Core/SystemInfo.swift b/cli/Sources/puremac/Core/SystemInfo.swift index 6487350..a90f9bd 100644 --- a/cli/Sources/puremac/Core/SystemInfo.swift +++ b/cli/Sources/puremac/Core/SystemInfo.swift @@ -1,5 +1,6 @@ import Darwin import Foundation +import TerminalUI struct MemoryStatus: Equatable { let total: Int64 @@ -8,6 +9,39 @@ struct MemoryStatus: Equatable { let active: Int64 let wired: Int64 let compressed: Int64 + + var usedFraction: Double { + total > 0 ? Double(total - free) / Double(total) : 0 + } +} + +enum MemoryPressure: Equatable { + case normal, warning, critical + + init?(level: Int) { + switch level { + case 1: self = .normal + case 2: self = .warning + case 4: self = .critical + default: return nil + } + } + + var label: String { + switch self { + case .normal: return "Normal" + case .warning: return "Warning" + case .critical: return "Critical" + } + } + + var color: TerminalColor { + switch self { + case .normal: return .green + case .warning: return .yellow + case .critical: return .red + } + } } struct VolumeStatus: Equatable { @@ -18,6 +52,20 @@ struct VolumeStatus: Equatable { var systemManagedCapacity: Int64 { max(0, availableForImportantUsage - availableNow) } + + var freeFraction: Double { + total > 0 ? Double(availableNow) / Double(total) : 1 + } + + var usedFraction: Double { 1 - freeFraction } + + var freeColor: TerminalColor { + switch freeFraction { + case ..<0.1: return .red + case ..<0.2: return .yellow + default: return .green + } + } } enum SystemInfoError: LocalizedError { @@ -62,6 +110,13 @@ enum SystemInfo { ) } + static func memoryPressure() -> MemoryPressure? { + var level: Int32 = 0 + var size = MemoryLayout.size + guard sysctlbyname("kern.memorystatus_vm_pressure_level", &level, &size, nil, 0) == 0 else { return nil } + return MemoryPressure(level: Int(level)) + } + static func volumeStatus(_ path: String) throws -> VolumeStatus { let url = URL(fileURLWithPath: path) let values = try url.resourceValues(forKeys: [ diff --git a/cli/Tests/puremacTests/InfoSheetTests.swift b/cli/Tests/puremacTests/InfoSheetTests.swift new file mode 100644 index 0000000..18ad641 --- /dev/null +++ b/cli/Tests/puremacTests/InfoSheetTests.swift @@ -0,0 +1,141 @@ +import XCTest +@testable import puremac +import TerminalUI + +final class InfoSheetTests: XCTestCase { + private let dim = TextStyle(dim: true) + + private func sample(extraRows: Int = 0) -> InfoSheet { + InfoSheet( + title: "Mac status", + subtitle: "Read-only measurements", + sections: [ + InfoSection(title: "Memory", rows: [ + .gauge(fraction: 0.5, color: .green, text: "8 GB in use of 16 GB"), + .metric(label: "Pressure", value: [Span("Normal", TextStyle(color: .green))], note: nil), + .metric(label: "Installed", value: [Span("16 GB")], note: "saved"), + ] + (0.. TerminalColor { + VolumeStatus(availableNow: free, availableForImportantUsage: free, total: 100).freeColor + } + XCTAssertEqual(color(free: 9), .red) + XCTAssertEqual(color(free: 10), .yellow) + XCTAssertEqual(color(free: 19), .yellow) + XCTAssertEqual(color(free: 20), .green) + let empty = VolumeStatus(availableNow: 0, availableForImportantUsage: 0, total: 0) + XCTAssertEqual(empty.usedFraction, 0) + XCTAssertEqual(empty.freeFraction, 1) + XCTAssertEqual(empty.freeColor, .green) + XCTAssertEqual(VolumeStatus(availableNow: 25, availableForImportantUsage: 25, total: 100).freeFraction, 0.25, accuracy: 0.0001) + XCTAssertEqual(VolumeStatus(availableNow: 25, availableForImportantUsage: 25, total: 100).usedFraction, 0.75, accuracy: 0.0001) + } + + func testMemorySectionHasGaugeColoredByPressureThenPressureAndTodaysRows() { + let rows = Optimize.memorySection(memory, pressure: .warning).rows + guard case .gauge(let fraction, let color, let text) = rows[0] else { return XCTFail("gauge first") } + XCTAssertEqual(fraction, 0.75, accuracy: 0.0001) + XCTAssertEqual(color, .yellow) + XCTAssertEqual(text, "\(ByteCount.human(12_000_000_000)) in use of \(ByteCount.human(16_000_000_000))") + guard case .metric("Pressure", let value, nil) = rows[1] else { return XCTFail("pressure second") } + XCTAssertEqual(value, [Span("Warning", TextStyle(color: .yellow))]) + XCTAssertEqual(rows.dropFirst(2).compactMap { row -> String? in + if case .metric(let label, _, _) = row { return label } + return nil + }, ["Installed", "Free now", "Active", "Inactive", "Compressed", "Wired"]) + } + + func testMemorySectionWithoutPressureHasPlainGaugeAndNoPressureRow() { + let rows = Optimize.memorySection(memory, pressure: nil).rows + guard case .gauge(_, let color, _) = rows[0] else { return XCTFail("gauge first") } + XCTAssertNil(color) + XCTAssertEqual(rows.count, 7) + } + + func testStorageSectionColorsGaugeAndFreeValueByFreeShare() { + let volume = VolumeStatus(availableNow: 5, availableForImportantUsage: 25, total: 100) + let rows = Optimize.storageSection(volume).rows + guard case .gauge(let fraction, let color, let text) = rows[0] else { return XCTFail("gauge first") } + XCTAssertEqual(fraction, 0.95, accuracy: 0.0001) + XCTAssertEqual(color, .red) + XCTAssertEqual(text, "\(ByteCount.human(5)) free of \(ByteCount.human(100))") + guard case .metric("Free now", let value, nil) = rows[1] else { return XCTFail("free second") } + XCTAssertEqual(value, [Span(ByteCount.human(5), TextStyle(color: .red))]) + XCTAssertEqual(rows.dropFirst(2).count, 3) + guard case .message(let note) = rows[4] else { return XCTFail("note last") } + XCTAssertEqual(note, [Span("Managed capacity may include purgeable files and is not guaranteed free space.", TextStyle(dim: true))]) + } + + func testStorageSectionOmitsTheNoteWithoutManagedCapacity() { + let rows = Optimize.storageSection(VolumeStatus(availableNow: 50, availableForImportantUsage: 50, total: 100)).rows + XCTAssertEqual(rows.count, 4) + } + + func testStatusSheetHasTitleSubtitleSectionsUptimeAndFootnote() { + let volume = VolumeStatus(availableNow: 50, availableForImportantUsage: 50, total: 100) + let sheet = Optimize.statusSheet(memory: memory, pressure: .normal, volume: volume, uptime: 3_661) + XCTAssertEqual(sheet.title, "Mac status") + XCTAssertEqual(sheet.subtitle, "Read-only measurements from macOS") + XCTAssertEqual(sheet.sections.map(\.title), ["Memory", "Storage", nil]) + XCTAssertEqual(sheet.sections[2].rows.count, 1) + guard case .message(let uptime) = sheet.sections[2].rows[0] else { return XCTFail("uptime message") } + XCTAssertEqual(uptime, [Span("Uptime", TextStyle(dim: true)), Span(" 1h 1m")]) + XCTAssertEqual(sheet.footnote, "No maintenance ran. Use `puremac clean --dry-run` to review removable files.") + } +} + +private let goldenStatus: [String] = [ + "Mac status", + "Read-only measurements from macOS", + "", + "Memory", + " ███████████████░░░░░ 12.9 GB in use of 17.2 GB", + " Pressure Normal", + " Installed 17.2 GB", + " Free now 4.3 GB", + " Active 2.1 GB", + " Inactive 1.1 GB", + " Compressed 536.9 MB", + " Wired 3.2 GB", + "", + "Storage", + " ████████████████░░░░ 107.4 GB free of 536.9 GB", + " Free now 107.4 GB", + " Total 536.9 GB", + " Managed by macOS 53.7 GB", + " Managed capacity may include purgeable files and is not guaranteed free space.", + "", + " Uptime 2d 1h 1m", + "", + "No maintenance ran. Use `puremac clean --dry-run` to review removable files.", +] + +private let goldenRam: [String] = [ + "Memory", + " ███████████████░░░░░ 12.9 GB in use of 17.2 GB", + " Pressure Normal", + " Installed 17.2 GB", + " Free now 4.3 GB", + " Active 2.1 GB", + " Inactive 1.1 GB", + " Compressed 536.9 MB", + " Wired 3.2 GB", + "", + "No memory was purged. macOS reclaims inactive memory when applications need it.", +] + +private let goldenPurgeable: [String] = [ + "Storage", + " ████████████████░░░░ 107.4 GB free of 536.9 GB", + " Free now 107.4 GB", + " Total 536.9 GB", + " Managed by macOS 53.7 GB", + " Managed capacity may include purgeable files and is not guaranteed free space.", + "", + "No storage was changed. APFS managed capacity is an estimate controlled by macOS.", +] From 4d1d3d0345288a7aa2cc516f2919874de068ccf2 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 13:50:44 +0000 Subject: [PATCH 11/21] feat(cli): open preferences and protected paths inside the UI from the menu --- cli/Sources/TerminalUI/Buffer.swift | 4 +- cli/Sources/TerminalUI/Style.swift | 5 + cli/Sources/TerminalUI/Term.swift | 108 ++++++---- cli/Sources/puremac/Commands/Config.swift | 39 ++-- cli/Sources/puremac/Commands/Ignore.swift | 28 ++- cli/Sources/puremac/Commands/Optimize.swift | 24 ++- cli/Sources/puremac/Core/InfoSheet.swift | 132 ++++++++---- cli/Sources/puremac/Core/TerminalMenu.swift | 17 +- cli/Sources/puremac/PureMac.swift | 25 ++- cli/Tests/TerminalUITests/TermTests.swift | 51 +++++ cli/Tests/puremacTests/InfoSheetTests.swift | 188 +++++++++++++++++- .../InteractiveScreensTests.swift | 28 ++- .../puremacTests/PreferencesSheetTests.swift | 145 ++++++++++++++ 13 files changed, 671 insertions(+), 123 deletions(-) create mode 100644 cli/Tests/puremacTests/PreferencesSheetTests.swift diff --git a/cli/Sources/TerminalUI/Buffer.swift b/cli/Sources/TerminalUI/Buffer.swift index 37f79da..29e094d 100644 --- a/cli/Sources/TerminalUI/Buffer.swift +++ b/cli/Sources/TerminalUI/Buffer.swift @@ -112,8 +112,8 @@ public struct Buffer: Equatable { var current = TextStyle.plain for column in 0.. String { + guard self != current else { return "" } + return self == .plain ? "\u{1B}[0m" : "\u{1B}[0m\u{1B}[\(sgrParameters)m" + } } public struct Span: Equatable { diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 046ef48..4019205 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -145,35 +145,25 @@ public enum Term { extension Term { public static func wrap(_ string: String, width: Int) -> [String] { - let safe = sanitize(string) - guard !safe.isEmpty else { return [""] } - var lines: [String] = [] - var current = "" - var used = 0 - for character in safe { - let characterWidth = max(0, displayWidth(String(character))) - if used + characterWidth > width && !current.isEmpty { - lines.append(current) - current = "" - used = 0 - } - current.append(character) - used += characterWidth - } - if !current.isEmpty { lines.append(current) } - return lines.isEmpty ? [""] : lines + let characters = sanitize(string).map { (character: $0, style: TextStyle.plain) } + let (lines, last) = hardBreak(characters, width: width) + return (lines + [last]).map { String($0.map(\.character)) } } public static func wordWrap(_ string: String, width: Int) -> [String] { - var lines: [String] = [] - var current = "" - var gap = "" - for token in wordTokens(sanitize(string)) { + wordWrap([Span(string)], width: width).map { $0.map(\.text).joined() } + } + + public static func wordWrap(_ spans: [Span], width: Int) -> [[Span]] { + var lines: [[StyledCharacter]] = [] + var current: [StyledCharacter] = [] + var gap: [StyledCharacter] = [] + for token in wordTokens(spans) { guard !token.isSpaces else { - gap = token.text + gap = token.characters continue } - let word = token.text + let word = token.characters if displayWidth(word) <= width { if current.isEmpty { current = word @@ -186,22 +176,72 @@ extension Term { continue } if !current.isEmpty { lines.append(current) } - let pieces = wrap(word, width: width) - lines += pieces.dropLast() - current = pieces[pieces.count - 1] + let (broken, last) = hardBreak(word, width: width) + lines += broken + current = last } lines.append(current) - return lines + return lines.map(merged) } - private static func wordTokens(_ string: String) -> [(text: String, isSpaces: Bool)] { - var tokens: [(text: String, isSpaces: Bool)] = [] - for character in string { - let isSpace = character == " " - if let last = tokens.last, last.isSpaces == isSpace { - tokens[tokens.count - 1].text.append(character) + private typealias StyledCharacter = (character: Character, style: TextStyle) + + private static func hardBreak(_ characters: [StyledCharacter], width: Int) -> (lines: [[StyledCharacter]], last: [StyledCharacter]) { + var lines: [[StyledCharacter]] = [] + var current: [StyledCharacter] = [] + var used = 0 + for character in characters { + let characterWidth = displayWidth([character]) + if used + characterWidth > width && !current.isEmpty { + lines.append(current) + current = [] + used = 0 + } + current.append(character) + used += characterWidth + } + return (lines, current) + } + + public static func styled(_ spans: [Span], colors: Bool = colorEnabled) -> String { + var output = "" + var current = TextStyle.plain + for span in spans { + let text = sanitize(span.text) + guard !text.isEmpty else { continue } + if colors { output += span.style.transition(from: current) } + current = span.style + output += text + } + return colors && current != .plain ? output + "\u{1B}[0m" : output + } + + private static func displayWidth(_ characters: [StyledCharacter]) -> Int { + characters.reduce(0) { $0 + max(0, displayWidth(String($1.character))) } + } + + private static func merged(_ characters: [StyledCharacter]) -> [Span] { + var spans: [Span] = [] + for (character, style) in characters { + if let last = spans.last, last.style == style { + spans[spans.count - 1].text.append(character) } else { - tokens.append((String(character), isSpace)) + spans.append(Span(String(character), style)) + } + } + return spans + } + + private static func wordTokens(_ spans: [Span]) -> [(characters: [StyledCharacter], isSpaces: Bool)] { + var tokens: [(characters: [StyledCharacter], isSpaces: Bool)] = [] + for span in spans { + for character in sanitize(span.text) { + let isSpace = character == " " + if let last = tokens.last, last.isSpaces == isSpace { + tokens[tokens.count - 1].characters.append((character, span.style)) + } else { + tokens.append(([(character, span.style)], isSpace)) + } } } return tokens diff --git a/cli/Sources/puremac/Commands/Config.swift b/cli/Sources/puremac/Commands/Config.swift index 57b1571..b2e2115 100644 --- a/cli/Sources/puremac/Commands/Config.swift +++ b/cli/Sources/puremac/Commands/Config.swift @@ -50,18 +50,33 @@ struct Config: ParsableCommand { return } - print(Term.bold("PureMac CLI settings")) - print(Term.dim("Values used when a command-line option is omitted")) - print("") - for key in ConfigStore.knownKeys { - let isSaved = store.values[key] != nil - let value = store.values[key] ?? ConfigStore.defaultValues[key] ?? "" - let source = isSaved ? "saved" : "default" - print(" \(key.padding(toLength: 26, withPad: " ", startingAt: 0)) \(value) days " + Term.dim(source)) + for line in Self.sheet(store: store).plainLines() { print(line) } + } + + static let sheetTitle = "PureMac CLI settings" + + static func sheet(store: ConfigStore) -> InfoSheet { + let keys = ConfigStore.knownKeys.map { key -> InfoRow in + let saved = store.values[key] + let value = saved ?? ConfigStore.defaultValues[key] ?? "" + let note = saved == nil ? Span("default", TextStyle(dim: true)) : Span("saved", TextStyle(color: .cyan)) + return .metric(label: key, value: [Span("\(value) days")], note: note) } - print("") - print(Term.bold("Files")) - print(" \("Settings".padding(toLength: 12, withPad: " ", startingAt: 0)) \(Render.shorten(AppPaths.configFile.path))") - print(" \("Protected".padding(toLength: 12, withPad: " ", startingAt: 0)) \(Render.shorten(AppPaths.ignoreFile.path))") + let files = [("Settings", AppPaths.configFile), ("Protected", AppPaths.ignoreFile)].map { label, url in + InfoRow.metric(label: label, value: [Span(Render.shorten(url.path))], note: nil) + } + return InfoSheet( + title: sheetTitle, + subtitle: "Values used when a command-line option is omitted", + sections: [ + InfoSection(title: nil, labelWidth: 26, rows: keys), + InfoSection(title: "Files", labelWidth: 12, rows: files), + ], + footnote: nil + ) + } + + static func currentSheet() throws -> InfoSheet { + sheet(store: try ConfigStore(fileURL: AppPaths.configFile)) } } diff --git a/cli/Sources/puremac/Commands/Ignore.swift b/cli/Sources/puremac/Commands/Ignore.swift index 4a78825..5d6a7ce 100644 --- a/cli/Sources/puremac/Commands/Ignore.swift +++ b/cli/Sources/puremac/Commands/Ignore.swift @@ -33,14 +33,36 @@ struct Ignore: ParsableCommand { struct List: ParsableCommand { static let configuration = CommandConfiguration(abstract: "Show protected paths.") + static let sheetTitle = "Protected paths" + func run() throws { let store = try IgnoreStore(fileURL: AppPaths.ignoreFile) - if store.roots.isEmpty { - print(Term.dim("No protected paths. Add one with `puremac ignore add `.")) + guard !store.roots.isEmpty else { + print(Term.styled(Self.emptyHint(quoted: true))) return } print(Term.bold("Protected paths:")) - for root in store.roots.sorted() { print(" " + Render.shorten(root)) } + for line in Self.sheet(roots: store.roots).plainLines(withHeader: false) { print(line) } + } + + static func emptyHint(quoted: Bool) -> [Span] { + let quote = quoted ? "`" : "" + return [ + Span("No protected paths. Add one with " + quote, TextStyle(dim: true)), + Span("puremac ignore add ", TextStyle(color: .cyan)), + Span(quote + ".", TextStyle(dim: true)), + ] + } + + static func sheet(roots: [String]) -> InfoSheet { + let rows: [InfoRow] = roots.isEmpty + ? [.message(emptyHint(quoted: false))] + : roots.sorted().map { .path(Render.shorten($0)) } + return InfoSheet(title: sheetTitle, subtitle: nil, sections: [InfoSection(title: nil, rows: rows)], footnote: nil) + } + + static func currentSheet() throws -> InfoSheet { + sheet(roots: try IgnoreStore(fileURL: AppPaths.ignoreFile).roots) } } } diff --git a/cli/Sources/puremac/Commands/Optimize.swift b/cli/Sources/puremac/Commands/Optimize.swift index 69827b9..32a2db4 100644 --- a/cli/Sources/puremac/Commands/Optimize.swift +++ b/cli/Sources/puremac/Commands/Optimize.swift @@ -36,17 +36,23 @@ struct Optimize: ParsableCommand { case "snapshots": try showSnapshots() default: - let memory = try SystemInfo.memoryStatus() - let volume = try SystemInfo.volumeStatus("/") - Self.printPlain(Self.statusSheet( - memory: memory, - pressure: SystemInfo.memoryPressure(), - volume: volume, - uptime: ProcessInfo.processInfo.systemUptime - )) + Self.printPlain(try Self.currentStatusSheet()) } } + static let statusTitle = "Mac status" + + static func currentStatusSheet() throws -> InfoSheet { + let memory = try SystemInfo.memoryStatus() + let volume = try SystemInfo.volumeStatus("/") + return statusSheet( + memory: memory, + pressure: SystemInfo.memoryPressure(), + volume: volume, + uptime: ProcessInfo.processInfo.systemUptime + ) + } + static func statusSheet( memory: MemoryStatus, pressure: MemoryPressure?, @@ -54,7 +60,7 @@ struct Optimize: ParsableCommand { uptime: TimeInterval ) -> InfoSheet { InfoSheet( - title: "Mac status", + title: statusTitle, subtitle: "Read-only measurements from macOS", sections: [ memorySection(memory, pressure: pressure), diff --git a/cli/Sources/puremac/Core/InfoSheet.swift b/cli/Sources/puremac/Core/InfoSheet.swift index 515a3be..59d580a 100644 --- a/cli/Sources/puremac/Core/InfoSheet.swift +++ b/cli/Sources/puremac/Core/InfoSheet.swift @@ -8,9 +8,19 @@ struct InfoSheet { private static let backHint = KeyHint("Esc", "back") private static let hints = KeyHints([KeyHint("↑↓", "scroll"), backHint]) - private static let labelWidth = 17 private static let gaugeWidth = 20 + private var window: Window { Window(title: title) } + + static func loading(title: String, _ build: () throws -> InfoSheet) -> InfoSheet { + do { + return try build() + } catch { + let message = Span(error.localizedDescription, TextStyle(color: .red)) + return InfoSheet(title: title, subtitle: nil, sections: [InfoSection(title: nil, rows: [.message([message])])], footnote: nil) + } + } + func plainLines(withHeader: Bool = true, colors: Bool = Term.colorEnabled) -> [String] { var lines: [[Span]] = [] if withHeader { @@ -18,7 +28,7 @@ struct InfoSheet { if let subtitle { lines.append([Span(subtitle, TextStyle(dim: true))]) } lines.append([]) } - return (lines + bodyLines()).map { Self.line($0, colors: colors) } + return (lines + bodyLines()).map { Term.styled($0, colors: colors) } } func render(width: Int, height: Int, offset: Int) -> Buffer { @@ -26,68 +36,95 @@ struct InfoSheet { return TooSmallScreen.render(title: title, exitHint: "\(Self.backHint.key) \(Self.backHint.action)", width: width, height: height) } var buffer = Buffer(width: width, height: height) - let window = Window(title: title) - let content = window.render(in: buffer.area, buffer: &buffer) - let areas = content.splitRows([.fill, .length(1), .length(Self.hints.rows(width: content.width).count)]) - let (list, divider, footer) = (areas[0], areas[1], areas[2]) - - var lines = bodyLines(wrappingTo: list.width) - if let subtitle { lines = Self.wrapped(subtitle, style: TextStyle(dim: true), indent: "", width: list.width) + [[]] + lines } - let start = max(0, min(offset, lines.count - list.height)) - for (index, spans) in lines.dropFirst(start).prefix(list.height).enumerated() { + window.render(in: buffer.area, buffer: &buffer) + let layout = layout(width: width, height: height) + let list = layout.list + let start = max(0, min(offset, layout.maxOffset)) + for (index, spans) in layout.lines.dropFirst(start).prefix(list.height).enumerated() { Self.write(spans, in: Rect(x: list.x, y: list.y + index, width: list.width, height: 1), buffer: &buffer) } - Scrollbar(total: lines.count, visible: list.height, offset: start) + Scrollbar(total: layout.lines.count, visible: list.height, offset: start) .render(column: width - 1, rows: list.y..<(list.y + list.height), buffer: &buffer) - window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) - Self.hints.render(in: footer, buffer: &buffer) + window.renderDivider(atRow: layout.divider.y, in: buffer.area, buffer: &buffer) + Self.hints.render(in: layout.footer, buffer: &buffer) return buffer } + func maxOffset(width: Int, height: Int) -> Int { + guard TooSmallScreen.fits(width: width, height: height) else { return 0 } + return layout(width: width, height: height).maxOffset + } + + func show(in session: TerminalSession) { + var scroll = InfoSheetScroll() + while true { + session.draw(render(width: session.width, height: session.height, offset: scroll.offset)) + if scroll.handle(session.readKey(), maxOffset: maxOffset(width: session.width, height: session.height)) { return } + } + } + + private struct Layout { + var list: Rect + var divider: Rect + var footer: Rect + var lines: [[Span]] + var maxOffset: Int { max(0, lines.count - list.height) } + } + + private func layout(width: Int, height: Int) -> Layout { + let content = window.contentRect(in: Rect(x: 0, y: 0, width: width, height: height)) + let areas = content.splitRows([.fill, .length(1), .length(Self.hints.rows(width: content.width).count)]) + let list = areas[0] + var lines = bodyLines(wrappingTo: list.width) + if let subtitle { + lines = Self.wrapped([Span(subtitle, TextStyle(dim: true))], indent: "", width: list.width) + [[]] + lines + } + return Layout(list: list, divider: areas[1], footer: areas[2], lines: lines) + } + private func bodyLines(wrappingTo width: Int? = nil) -> [[Span]] { var lines: [[Span]] = [] for section in sections { if !lines.isEmpty { lines.append([]) } if let title = section.title { lines.append([Span(title, TextStyle(bold: true))]) } - lines += section.rows.flatMap { Self.lines($0, wrappingTo: width) } + lines += section.rows.flatMap { Self.lines($0, labelWidth: section.labelWidth, wrappingTo: width) } } if let footnote { lines.append([]) - lines += width.map { Self.wrapped(footnote, style: TextStyle(dim: true), indent: "", width: $0) } - ?? [[Span(footnote, TextStyle(dim: true))]] + let note = [Span(footnote, TextStyle(dim: true))] + lines += width.map { Self.wrapped(note, indent: "", width: $0) } ?? [note] } return lines } - private static func lines(_ row: InfoRow, wrappingTo width: Int?) -> [[Span]] { - if let width, case .message(let spans) = row, spans.count == 1 { - return wrapped(spans[0].text, style: spans[0].style, indent: " ", width: width) - } - return [spans(row)] - } - - private static func wrapped(_ text: String, style: TextStyle, indent: String, width: Int) -> [[Span]] { - Term.wordWrap(text, width: max(1, width - indent.count)).map { [Span(indent), Span($0, style)] } - } - - private static func spans(_ row: InfoRow) -> [Span] { + private static func lines(_ row: InfoRow, labelWidth: Int, wrappingTo width: Int?) -> [[Span]] { switch row { case .metric(let label, let value, let note): let labelSpan = Span(Term.pad(label, to: labelWidth), TextStyle(dim: true)) - let noteSpans = note.map { [Span(" "), Span($0, TextStyle(dim: true))] } ?? [] - return [Span(" "), labelSpan, Span(" ")] + value + noteSpans + let noteSpans = note.map { [Span(" "), $0] } ?? [] + let row = [Span(" "), labelSpan, Span(" ")] + value + noteSpans + guard let width, Term.displayWidth(row) > width else { return [row] } + return [[Span(" "), Span(label, TextStyle(dim: true))], [Span(" ")] + fitted(value, to: width - 4 - Term.displayWidth(noteSpans)) + noteSpans] case .gauge(let fraction, let color, let text): - let filled = color.map { TextStyle(color: $0) } ?? .plain - return [Span(" ")] + Gauge(fraction: fraction).spans(width: gaugeWidth, filled: filled) + [Span(" " + text)] + let barWidth = width.map { min(gaugeWidth, $0 - 3 - Term.displayWidth(text)) } ?? gaugeWidth + let bar = Gauge(fraction: fraction).spans(width: barWidth, filled: color.map { TextStyle(color: $0) } ?? .plain) + return [[Span(" ")] + bar + [Span(bar.isEmpty ? text : " " + text)]] + case .path(let path): + let shown = width.map { Term.truncate(path, to: max(1, $0 - 2), middle: true) } ?? path + return [[Span(" " + shown)]] case .message(let spans): - return [Span(" ")] + spans + guard let width else { return [[Span(" ")] + spans] } + return wrapped(spans, indent: " ", width: width) } } - private static func line(_ spans: [Span], colors: Bool) -> String { - var buffer = Buffer(width: Term.displayWidth(spans), height: 1) - buffer.write(spans, x: 0, y: 0) - return buffer.lines(colors: colors)[0] + private static func fitted(_ spans: [Span], to width: Int) -> [Span] { + guard spans.count == 1, let span = spans.first else { return spans } + return [Span(Term.truncate(span.text, to: max(1, width), middle: true), span.style)] + } + + private static func wrapped(_ spans: [Span], indent: String, width: Int) -> [[Span]] { + Term.wordWrap(spans, width: max(1, width - indent.count)).map { [Span(indent)] + $0 } } private static func write(_ spans: [Span], in rect: Rect, buffer: inout Buffer) { @@ -102,11 +139,28 @@ struct InfoSheet { struct InfoSection { var title: String? + var labelWidth = 17 var rows: [InfoRow] } enum InfoRow { - case metric(label: String, value: [Span], note: String?) + case metric(label: String, value: [Span], note: Span?) case gauge(fraction: Double, color: TerminalColor?, text: String) case message([Span]) + case path(String) +} + +struct InfoSheetScroll { + private(set) var offset = 0 + + mutating func handle(_ key: TerminalKey, maxOffset: Int) -> Bool { + switch key { + case .up: offset = max(0, min(offset, maxOffset) - 1) + case .down: offset = min(maxOffset, offset + 1) + case .escape, .enter, .left, .backspace: return true + case .character(let character): return character.lowercased() == "q" + default: break + } + return false + } } diff --git a/cli/Sources/puremac/Core/TerminalMenu.swift b/cli/Sources/puremac/Core/TerminalMenu.swift index 9255757..d849f71 100644 --- a/cli/Sources/puremac/Core/TerminalMenu.swift +++ b/cli/Sources/puremac/Core/TerminalMenu.swift @@ -3,7 +3,12 @@ import TerminalUI struct TerminalMenuModel { let optionCount: Int - private(set) var selection = 0 + private(set) var selection: Int + + init(optionCount: Int, selection: Int = 0) { + self.optionCount = optionCount + self.selection = min(max(0, optionCount - 1), max(0, selection)) + } mutating func move(_ delta: Int) { guard optionCount > 0 else { return } @@ -30,13 +35,14 @@ enum TerminalMenu { static func choose( title: String, subtitle: String, - options: [(title: String, detail: String)] + options: [(title: String, detail: String)], + initialSelection: Int = 0 ) throws -> Int? { guard !options.isEmpty else { return nil } let session = try TerminalSession() defer { session.close() } - var model = TerminalMenuModel(optionCount: options.count) + var model = TerminalMenuModel(optionCount: options.count, selection: initialSelection) while true { session.draw( render( @@ -131,10 +137,13 @@ enum TerminalMenu { let indent = 6 let textWidth = max(1, rect.width - indent) let rowStyle = TextStyle(inverse: focused) + let numberText = "\(number)." buffer.write( [ FocusPointer.span(focused: focused), - Span(" " + Term.pad("\(number).", to: 4) + Term.pad(Term.truncate(option.title, to: textWidth), to: textWidth), rowStyle) + Span(" ", rowStyle), + Span(Term.pad(numberText, to: 4), focused ? rowStyle : TextStyle(color: .cyan)), + Span(Term.pad(Term.truncate(option.title, to: textWidth), to: textWidth), rowStyle) ], x: rect.x, y: rect.y, diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index 18e38bf..fc55a01 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -41,7 +41,15 @@ enum HomeMenu { ] static func run() throws { - while let choice = try TerminalMenu.choose(title: title, subtitle: subtitle, options: options) { + var focus = 0 + while let choice = try TerminalMenu.choose(title: title, subtitle: subtitle, options: options, initialSelection: focus) { + focus = choice + if let sheet = sheet(forChoice: choice) { + let session = try TerminalSession() + defer { session.close() } + sheet.show(in: session) + continue + } switch choice { case 0: guard let category = try TerminalMenu.choose( @@ -61,18 +69,17 @@ enum HomeMenu { case exploreIndex: guard try ExploreConfirmation.ask() else { continue } try Analyze.parse([]).run() - case 3: try Optimize.parse([]).run() - case 4: try Config.parse([]).run() - case 5: try Ignore.List.parse([]).run() default: return } - guard waitsForReturn(afterChoice: choice) else { continue } - print(Term.dim("\nPress Return to return to PureMac."), terminator: " ") - guard readLine() != nil else { return } } } - static func waitsForReturn(afterChoice choice: Int) -> Bool { - choice != 0 && choice != 1 + static func sheet(forChoice choice: Int) -> InfoSheet? { + switch choice { + case 3: return InfoSheet.loading(title: Optimize.statusTitle, Optimize.currentStatusSheet) + case 4: return InfoSheet.loading(title: Config.sheetTitle, Config.currentSheet) + case 5: return InfoSheet.loading(title: Ignore.List.sheetTitle, Ignore.List.currentSheet) + default: return nil + } } } diff --git a/cli/Tests/TerminalUITests/TermTests.swift b/cli/Tests/TerminalUITests/TermTests.swift index 66feb55..c61c008 100644 --- a/cli/Tests/TerminalUITests/TermTests.swift +++ b/cli/Tests/TerminalUITests/TermTests.swift @@ -59,4 +59,55 @@ final class TermTests: XCTestCase { func testWordWrapHardBreaksLongWord() { XCTAssertEqual(Term.wordWrap("ab abcdefg", width: 3), ["ab", "abc", "def", "g"]) } + + func testSpanWordWrapKeepsStylesAcrossLines() { + let dim = TextStyle(dim: true) + let cyan = TextStyle(color: .cyan) + let spans = [Span("Add one with ", dim), Span("`puremac ignore add `", cyan), Span(".", dim)] + XCTAssertEqual(Term.wordWrap(spans, width: 24), [ + [Span("Add one with ", dim), Span("`puremac", cyan)], + [Span("ignore add `", cyan), Span(".", dim)], + ]) + } + + func testSpanWordWrapDropsTheSpaceAtALineBreakWhateverItsStyle() { + let dim = TextStyle(dim: true) + XCTAssertEqual( + Term.wordWrap([Span("one ", dim), Span("two", .plain)], width: 3), + [[Span("one", dim)], [Span("two")]] + ) + } + + func testSpanWordWrapJoinsAWordSplitAcrossSpans() { + let bold = TextStyle(bold: true) + XCTAssertEqual( + Term.wordWrap([Span("ab", bold), Span("cd ef")], width: 5), + [[Span("ab", bold), Span("cd")], [Span("ef")]] + ) + } + + func testSpanWordWrapHardBreaksALongWordKeepingItsStyle() { + let cyan = TextStyle(color: .cyan) + XCTAssertEqual( + Term.wordWrap([Span("ab ", .plain), Span("abcdefg", cyan)], width: 3), + [[Span("ab")], [Span("abc", cyan)], [Span("def", cyan)], [Span("g", cyan)]] + ) + } + + func testSpanWordWrapOfNothingIsOneEmptyRow() { + XCTAssertEqual(Term.wordWrap([Span("")], width: 10), [[]]) + XCTAssertEqual(Term.wordWrap([], width: 10), [[]]) + } + + func testStyledJoinsSpanTextAndAddsCodesOnlyWithColors() { + let dim = TextStyle(dim: true) + let spans = [Span("a", dim), Span("b", dim), Span("c")] + XCTAssertEqual(Term.styled(spans, colors: false), "abc") + XCTAssertEqual(Term.styled(spans, colors: true), "\u{1B}[0m\u{1B}[2mab\u{1B}[0mc") + XCTAssertEqual(Term.styled([], colors: true), "") + } + + func testStyledKeepsZeroWidthCharactersAndSanitizesControls() { + XCTAssertEqual(Term.styled([Span("a\u{200B}b\u{07}")], colors: false), "a\u{200B}b\u{FFFD}") + } } diff --git a/cli/Tests/puremacTests/InfoSheetTests.swift b/cli/Tests/puremacTests/InfoSheetTests.swift index 18ad641..7ef1bd9 100644 --- a/cli/Tests/puremacTests/InfoSheetTests.swift +++ b/cli/Tests/puremacTests/InfoSheetTests.swift @@ -13,7 +13,7 @@ final class InfoSheetTests: XCTestCase { InfoSection(title: "Memory", rows: [ .gauge(fraction: 0.5, color: .green, text: "8 GB in use of 16 GB"), .metric(label: "Pressure", value: [Span("Normal", TextStyle(color: .green))], note: nil), - .metric(label: "Installed", value: [Span("16 GB")], note: "saved"), + .metric(label: "Installed", value: [Span("16 GB")], note: Span("saved", dim)), ] + (0..`", cyan), Span(".", dim)]) + ])], + footnote: nil + ) + let buffer = sheet.render(width: 40, height: 12, offset: 0) + let lines = buffer.plainLines() + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertFalse(lines.contains { $0.contains("…") }) + let text = lines.joined(separator: " ") + for word in ["protected", "puremac", "ignore", "add", "`."] { XCTAssertTrue(text.contains(word), word) } + let intro = lines.firstIndex { $0.contains("Add one with") } + let command = lines.firstIndex { $0.contains("puremac") } + XCTAssertNotNil(intro) + XCTAssertNotEqual(intro, command, "the hint wraps onto a second row") + let row = command ?? 0 + let styled = (0..<40).filter { buffer[$0, row].style == cyan }.map { buffer[$0, row].symbol }.joined() + XCTAssertEqual(styled, "`puremac ignore add `") + XCTAssertEqual(buffer[4, intro ?? 0].style, dim) + XCTAssertTrue(lines[row].hasPrefix("│ `"), lines[row]) + } + + func testWindowGaugeShrinksItsBarSoTheWholeTextFitsAt40Columns() { + let text = "107.4 GB free of 536.9 GB" + let sheet = InfoSheet( + title: "T", subtitle: nil, + sections: [InfoSection(title: nil, rows: [.gauge(fraction: 0.8, color: .green, text: text)])], + footnote: nil + ) + let narrow = sheet.render(width: 40, height: 12, offset: 0).plainLines() + let row = narrow.first { $0.contains("█") } + XCTAssertNotNil(row) + XCTAssertTrue(row?.contains(text) == true, row ?? "") + XCTAssertFalse(narrow.contains { $0.contains("…") }) + let wide = sheet.render(width: 80, height: 12, offset: 0).plainLines() + let bar = wide.first { $0.contains("█") }?.filter { "█░".contains($0) }.count + XCTAssertEqual(bar, 20) + } + + func testWindowGaugeWithoutRoomForABarShowsOnlyItsText() { + let text = String(repeating: "y", count: 33) + let sheet = InfoSheet( + title: "T", subtitle: nil, + sections: [InfoSection(title: nil, rows: [.gauge(fraction: 0.5, color: .green, text: text)])], + footnote: nil + ) + let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() + let row = lines.first { $0.contains(text) } + XCTAssertNotNil(row) + XCTAssertTrue(row?.hasPrefix("│ " + text) == true, row ?? "") + XCTAssertFalse(lines.contains { $0.contains("█") || $0.contains("░") || $0.contains("…") }) + } + + func testWindowShowsALongPathRowAsOneMiddleTruncatedRow() { + let path = "/Users/x/Projects/some/deep/folder/name-0" + let sheet = InfoSheet( + title: "T", subtitle: nil, + sections: [InfoSection(title: nil, rows: [.path(path), .path("/tmp/short")])], + footnote: nil + ) + let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() + let rows = lines.filter { $0.contains("/Users") || $0.contains("name-0") } + XCTAssertEqual(rows.count, 1, "\(rows)") + XCTAssertTrue(rows[0].contains("…") && rows[0].contains("name-0"), rows[0]) + XCTAssertTrue(rows[0].hasPrefix("│ /Users"), rows[0]) + XCTAssertTrue(lines.contains { $0.hasPrefix("│ /tmp/short ") }) + } + + func testPlainLinesShowAPathRowWithTwoSpacesAndNoTruncation() { + let path = "/Users/x/Projects/some/deep/folder/name-0" + let sheet = InfoSheet(title: "T", subtitle: nil, sections: [InfoSection(title: nil, rows: [.path(path)])], footnote: nil) + XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" " + path]) + } + + func testPlainLinesKeepZeroWidthCharactersInPaths() { + let sheet = InfoSheet(title: "T", subtitle: nil, sections: [InfoSection(title: nil, rows: [.path("/tmp/a\u{200B}b")])], footnote: nil) + XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" /tmp/a\u{200B}b"]) + } + + func testMaxOffsetIsZeroWhenEverythingFitsOrTheScreenIsTooSmall() { + XCTAssertEqual(sample().maxOffset(width: 60, height: 30), 0) + XCTAssertEqual(sample(extraRows: 30).maxOffset(width: 39, height: 11), 0) + } + + func testMaxOffsetIsTheLargestOffsetThatStillMovesTheWindow() { + let sheet = sample(extraRows: 30) + let most = sheet.maxOffset(width: 60, height: 14) + XCTAssertGreaterThan(most, 0) + XCTAssertEqual(sheet.render(width: 60, height: 14, offset: most), sheet.render(width: 60, height: 14, offset: most + 5)) + XCTAssertNotEqual(sheet.render(width: 60, height: 14, offset: most - 1), sheet.render(width: 60, height: 14, offset: most)) + } + + func testMaxOffsetCountsWrappedRows() { + let long = InfoSheet(title: "T", subtitle: nil, sections: [InfoSection(title: nil, rows: [.message([Span(Array(repeating: "word", count: 80).joined(separator: " "))])])], footnote: nil) + XCTAssertGreaterThan(long.maxOffset(width: 40, height: 12), long.maxOffset(width: 100, height: 12)) + } + + func testSectionLabelWidthPadsPlainLabels() { + let sheet = InfoSheet( + title: "T", subtitle: nil, + sections: [InfoSection(title: nil, labelWidth: 8, rows: [.metric(label: "Name", value: [Span("x")], note: nil)])], + footnote: nil + ) + XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" Name x"]) + } + + func testWindowMovesAMetricValueAndNoteToASecondRowWhenTheRowIsTooWide() { + let sheet = InfoSheet( + title: "T", subtitle: nil, + sections: [InfoSection(title: nil, labelWidth: 26, rows: [ + .metric(label: "purge.older_than_days", value: [Span("7 days")], note: Span("default", dim)), + .metric(label: "Short", value: [Span("x")], note: nil), + ])], + footnote: nil + ) + let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() + let label = lines.firstIndex { $0.contains("purge.older_than_days") } + XCTAssertNotNil(label) + XCTAssertFalse(lines[label ?? 0].contains("…")) + XCTAssertTrue(lines[(label ?? 0) + 1].hasPrefix("│ 7 days default"), lines[(label ?? 0) + 1]) + XCTAssertTrue(lines.contains { $0.hasPrefix("│ Short") && $0.contains(" x") }, "a row that fits stays on one line") + let wide = sheet.render(width: 80, height: 12, offset: 0).plainLines() + XCTAssertTrue(wide.contains { $0.contains("purge.older_than_days") && $0.contains("7 days default") }) + } + + func testWindowMiddleTruncatesALongMetricValueOnItsSecondRow() { + let path = "/Users/someone/.config/puremac/deep/config.json" + let sheet = InfoSheet( + title: "T", subtitle: nil, + sections: [InfoSection(title: nil, labelWidth: 12, rows: [.metric(label: "Settings", value: [Span(path)], note: nil)])], + footnote: nil + ) + let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() + let row = lines.first { $0.contains("config.json") } + XCTAssertNotNil(row) + XCTAssertTrue(row?.hasPrefix("│ /Users") == true && row?.contains("…") == true, row ?? "") + XCTAssertTrue(lines.contains { $0.contains("Settings") }) + XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" Settings " + path]) + } + + func testLoadingReturnsTheSheetOrARedErrorRow() { + struct Failure: LocalizedError { var errorDescription: String? { "disk unavailable" } } + let ok = InfoSheet(title: "T", subtitle: nil, sections: [], footnote: nil) + XCTAssertEqual(InfoSheet.loading(title: "Fallback") { ok }.title, "T") + let failed = InfoSheet.loading(title: "Mac status") { throw Failure() } + XCTAssertEqual(failed.title, "Mac status") + XCTAssertEqual(failed.sections.count, 1) + guard case .message(let spans) = failed.sections[0].rows[0] else { return XCTFail("message row") } + XCTAssertEqual(spans, [Span("disk unavailable", TextStyle(color: .red))]) + } + func testWindowWrapsLongMessagesAndFootnoteInsteadOfCutting() { let note = "Managed capacity may include purgeable files and is not guaranteed free space." let footnote = "No maintenance ran. Use `puremac clean --dry-run` to review removable files." @@ -138,4 +293,31 @@ final class InfoSheetTests: XCTestCase { TooSmallScreen.render(title: "Mac status", exitHint: "Esc back", width: 39, height: 11) ) } + + func testScrollMovesByOneAndStaysInRange() { + var scroll = InfoSheetScroll() + XCTAssertFalse(scroll.handle(.up, maxOffset: 3)) + XCTAssertEqual(scroll.offset, 0) + for _ in 0..<5 { XCTAssertFalse(scroll.handle(.down, maxOffset: 3)) } + XCTAssertEqual(scroll.offset, 3) + XCTAssertFalse(scroll.handle(.up, maxOffset: 3)) + XCTAssertEqual(scroll.offset, 2) + XCTAssertFalse(scroll.handle(.down, maxOffset: 0)) + XCTAssertEqual(scroll.offset, 0) + } + + func testScrollClosesOnEscQEnterLeftAndBackspace() { + for key in [TerminalKey.escape, .enter, .left, .backspace, .character("q"), .character("Q")] { + var scroll = InfoSheetScroll() + XCTAssertTrue(scroll.handle(key, maxOffset: 3), "\(key)") + } + } + + func testScrollIgnoresOtherKeys() { + for key in [TerminalKey.right, .tab, .space, .pageDown, .character("x"), .unknown] { + var scroll = InfoSheetScroll() + XCTAssertFalse(scroll.handle(key, maxOffset: 3), "\(key)") + XCTAssertEqual(scroll.offset, 0) + } + } } diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index 4cdc57c..364ffd4 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -346,6 +346,26 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(buffer[2, 1].style, TextStyle(dim: true)) } + func testMenuNumbersAreCyanExceptOnTheFocusedRow() { + let buffer = renderMenu(options: menuOptions(2), selection: 0, width: 40, height: 12) + XCTAssertEqual(buffer[4, 3].symbol, "1") + XCTAssertEqual(buffer[4, 3].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[4, 5].symbol, "2") + XCTAssertEqual(buffer[5, 5].symbol, ".") + XCTAssertEqual(buffer[4, 5].style, TextStyle(color: .cyan)) + XCTAssertEqual(buffer[5, 5].style, TextStyle(color: .cyan)) + XCTAssertEqual(buffer[8, 5].style, .plain) + XCTAssertEqual(buffer.plainLines()[5], renderMenu(options: menuOptions(2), selection: 1, width: 40, height: 12).plainLines()[5].replacingOccurrences(of: "›", with: " ")) + } + + func testMenuModelStartsAtTheInitialSelectionClamped() { + XCTAssertEqual(TerminalMenuModel(optionCount: 6, selection: 4).selection, 4) + XCTAssertEqual(TerminalMenuModel(optionCount: 6, selection: 99).selection, 5) + XCTAssertEqual(TerminalMenuModel(optionCount: 6, selection: -3).selection, 0) + XCTAssertEqual(TerminalMenuModel(optionCount: 0, selection: 2).selection, 0) + XCTAssertEqual(TerminalMenuModel(optionCount: 6).selection, 0) + } + func testMenuRenderBelowMinimumUsesTooSmallScreen() { let buffer = renderMenu(options: menuOptions(2), selection: 0, width: 30, height: 8) XCTAssertEqual(buffer, TooSmallScreen.render(title: "PureMac", exitHint: "Esc/q cancel", width: 30, height: 8)) @@ -630,14 +650,6 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertFalse(buffer.plainLines().contains { $0.contains("Cancel") }) } - func testHomeMenuWaitsForReturnOnlyAfterEntriesOutsideCleanup() { - XCTAssertFalse(HomeMenu.waitsForReturn(afterChoice: 0)) - XCTAssertFalse(HomeMenu.waitsForReturn(afterChoice: 1)) - for choice in 2...5 { - XCTAssertTrue(HomeMenu.waitsForReturn(afterChoice: choice)) - } - } - func testEnterOnTheSelectionOpensDialogAndNeverReturnsTheSelection() { var model = selectedModel() XCTAssertEqual(model.routeKey(.enter), .handled) diff --git a/cli/Tests/puremacTests/PreferencesSheetTests.swift b/cli/Tests/puremacTests/PreferencesSheetTests.swift new file mode 100644 index 0000000..476d5a8 --- /dev/null +++ b/cli/Tests/puremacTests/PreferencesSheetTests.swift @@ -0,0 +1,145 @@ +import Foundation +import XCTest +@testable import puremac +import TerminalUI + +private func withConfigHome(_ body: (URL) throws -> T) throws -> T { + let directory = FileManager.default.temporaryDirectory + .appendingPathComponent("puremac-sheet-tests-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + let saved = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"] + setenv("XDG_CONFIG_HOME", directory.path, 1) + defer { + if let saved { setenv("XDG_CONFIG_HOME", saved, 1) } else { unsetenv("XDG_CONFIG_HOME") } + try? FileManager.default.removeItem(at: directory) + } + return try body(directory.appendingPathComponent("puremac", isDirectory: true)) +} + +final class PlainCommandOutputTests: XCTestCase { + func testConfigPrintsTodaysTextWithDefaultValue() throws { + try withConfigHome { dir in + let output = try captureStdout { try Config.parse([]).run() } + XCTAssertEqual(output, """ + PureMac CLI settings + Values used when a command-line option is omitted + + purge.older_than_days 7 days default + + Files + Settings \(dir.path)/config.json + Protected \(dir.path)/ignore + + """) + } + } + + func testConfigPrintsSavedValue() throws { + try withConfigHome { dir in + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.set("purge.older_than_days", "14") + let output = try captureStdout { try Config.parse([]).run() } + XCTAssertTrue(output.contains("\n purge.older_than_days 14 days saved\n"), output) + } + } + + func testIgnoreListPrintsTodaysTextWhenEmpty() throws { + try withConfigHome { _ in + let output = try captureStdout { try Ignore.List.parse([]).run() } + XCTAssertEqual(output, "No protected paths. Add one with `puremac ignore add `.\n") + } + } + + func testIgnoreListHintHasACyanCommandWhenColorsAreOn() { + let styled = Term.styled(Ignore.List.emptyHint(quoted: true), colors: true) + XCTAssertTrue(styled.contains("\u{1B}[0m\u{1B}[36mpuremac ignore add "), styled) + } + + func testIgnoreListKeepsZeroWidthCharactersInPaths() throws { + try withConfigHome { _ in + var store = try IgnoreStore(fileURL: AppPaths.ignoreFile) + _ = try store.add("/tmp/puremac-a\u{200B}b") + let output = try captureStdout { try Ignore.List.parse([]).run() } + XCTAssertEqual(output, "Protected paths:\n /tmp/puremac-a\u{200B}b\n") + } + } + + func testIgnoreListPrintsSortedPaths() throws { + try withConfigHome { _ in + var store = try IgnoreStore(fileURL: AppPaths.ignoreFile) + _ = try store.add("/tmp/puremac-b") + _ = try store.add("/tmp/puremac-a") + let output = try captureStdout { try Ignore.List.parse([]).run() } + XCTAssertEqual(output, "Protected paths:\n /tmp/puremac-a\n /tmp/puremac-b\n") + } + } +} + +final class PreferencesSheetTests: XCTestCase { + private let dim = TextStyle(dim: true) + + func testPreferencesSheetListsKeysWithValueAndNote() throws { + try withConfigHome { dir in + var store = try ConfigStore(fileURL: AppPaths.configFile) + var sheet = Config.sheet(store: store) + XCTAssertEqual(sheet.title, "PureMac CLI settings") + XCTAssertEqual(sheet.subtitle, "Values used when a command-line option is omitted") + XCTAssertEqual(sheet.sections.map(\.title), [nil, "Files"]) + guard case .metric("purge.older_than_days", let value, let note) = sheet.sections[0].rows[0] else { return XCTFail("key row") } + XCTAssertEqual(value, [Span("7 days")]) + XCTAssertEqual(note, Span("default", dim)) + + try store.set("purge.older_than_days", "14") + sheet = Config.sheet(store: store) + guard case .metric(_, let saved, let savedNote) = sheet.sections[0].rows[0] else { return XCTFail("key row") } + XCTAssertEqual(saved, [Span("14 days")]) + XCTAssertEqual(savedNote, Span("saved", TextStyle(color: .cyan))) + + XCTAssertEqual(sheet.sections[1].rows.count, 2) + guard case .metric("Settings", let settings, nil) = sheet.sections[1].rows[0] else { return XCTFail("settings row") } + XCTAssertEqual(settings, [Span("\(dir.path)/config.json")]) + } + } + + func testProtectedPathsSheetListsSortedPaths() { + let sheet = Ignore.List.sheet(roots: ["/tmp/b", "/tmp/a"]) + XCTAssertEqual(sheet.title, "Protected paths") + XCTAssertNil(sheet.subtitle) + XCTAssertEqual(sheet.sections.count, 1) + XCTAssertEqual(sheet.sections[0].rows.count, 2) + guard case .path(let first) = sheet.sections[0].rows[0] else { return XCTFail("path row") } + XCTAssertEqual(first, "/tmp/a") + } + + func testProtectedPathsSheetWithoutPathsShowsTheHintWithACyanCommand() { + let sheet = Ignore.List.sheet(roots: []) + guard case .message(let spans) = sheet.sections[0].rows[0] else { return XCTFail("hint row") } + XCTAssertEqual(spans.map(\.text).joined(), "No protected paths. Add one with puremac ignore add .") + XCTAssertEqual(spans.filter { $0.style.color == .cyan }.map(\.text), ["puremac ignore add "]) + XCTAssertEqual(sheet.sections[0].rows.count, 1) + } + + func testHomeMenuOpensSheetsOnlyForStatusPreferencesAndProtectedPaths() throws { + try withConfigHome { _ in + for choice in 0...2 { XCTAssertNil(HomeMenu.sheet(forChoice: choice), "\(choice)") } + XCTAssertEqual(HomeMenu.sheet(forChoice: 3)?.title, "Mac status") + XCTAssertEqual(HomeMenu.sheet(forChoice: 4)?.title, "PureMac CLI settings") + XCTAssertEqual(HomeMenu.sheet(forChoice: 5)?.title, "Protected paths") + XCTAssertNil(HomeMenu.sheet(forChoice: 6)) + } + } + + func testHomeMenuShowsAStoreErrorAsARedRowInsteadOfThrowing() throws { + try withConfigHome { dir in + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try Data("[]".utf8).write(to: AppPaths.configFile) + try Data("relative/path\n".utf8).write(to: AppPaths.ignoreFile) + for (choice, title) in [(4, "PureMac CLI settings"), (5, "Protected paths")] { + let sheet = try XCTUnwrap(HomeMenu.sheet(forChoice: choice)) + XCTAssertEqual(sheet.title, title) + guard case .message(let spans) = sheet.sections[0].rows[0] else { return XCTFail("error row") } + XCTAssertEqual(spans.first?.style, TextStyle(color: .red)) + } + } + } +} From 8b592b48aff12509354e5785b09659e1e3b48e96 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 13:57:30 +0000 Subject: [PATCH 12/21] feat(cli): color sizes in plain reports --- cli/Sources/TerminalUI/Term.swift | 6 - cli/Sources/puremac/Commands/Analyze.swift | 12 +- cli/Sources/puremac/Commands/Purge.swift | 14 +- cli/Sources/puremac/Core/Render.swift | 47 ++++--- cli/Tests/TerminalUITests/GaugeTests.swift | 13 +- cli/Tests/TerminalUITests/TermTests.swift | 7 - .../puremacTests/PlainReportColorTests.swift | 120 ++++++++++++++++++ 7 files changed, 168 insertions(+), 51 deletions(-) create mode 100644 cli/Tests/puremacTests/PlainReportColorTests.swift diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 4019205..99ef989 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -37,12 +37,6 @@ public enum Term { return answer == "y" || answer == "yes" } - public static func bar(fraction: Double, width: Int = 24) -> String { - let filled = filledCount(fraction: fraction, width: width) - return String(repeating: "█", count: filled) - + String(repeating: "░", count: max(0, width) - filled) - } - static func filledCount(fraction: Double, width: Int) -> Int { let clamped = max(0, min(1, fraction)) return Int((Double(max(0, width)) * clamped).rounded()) diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index a55c14e..9b8c823 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -265,18 +265,20 @@ struct Analyze: ParsableCommand { total: Int64, indent: String, depthLeft: Int, - ignore: IgnoreStore = IgnoreStore() + ignore: IgnoreStore = IgnoreStore(), + colors: Bool = Term.colorEnabled ) { for child in children where child.size > 0 || child.isPartial { let fraction = total > 0 ? Double(child.size) / Double(total) : 0 let percentage = String(format: "%5.1f%%", fraction * 100) - let size = ByteCount.human(child.size).padding(toLength: 10, withPad: " ", startingAt: 0) - let partial = child.isPartial ? Term.yellow(" !") : "" + let size = Render.coloredSizeCol(child.size, colors: colors) + let bar = Term.styled(Gauge(fraction: fraction).spans(width: 20, filled: SizeLevel.style(bytes: child.size, focused: false)), colors: colors) + let partial = child.isPartial ? Render.paint(" !", TextStyle(color: .yellow), colors) : "" let name = URL(fileURLWithPath: child.path).lastPathComponent + child.suffix - print("\(indent)\(size) \(Term.dim(percentage)) \(Term.bar(fraction: fraction, width: 20)) \(name)\(partial)") + print("\(indent)\(size) \(Render.paint(percentage, TextStyle(dim: true), colors)) \(bar) \(name)\(partial)") if depthLeft > 0 && child.isDir && !child.isPackage { let snapshot = scanFolder(child.path, ignore: ignore) - printLevel(Array(snapshot.children.prefix(10)), total: child.size, indent: indent + " ", depthLeft: depthLeft - 1, ignore: ignore) + printLevel(Array(snapshot.children.prefix(10)), total: child.size, indent: indent + " ", depthLeft: depthLeft - 1, ignore: ignore, colors: colors) printDiagnostics(snapshot, indent: indent + " ") } } diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 0b0d10a..2d8f62f 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -133,20 +133,20 @@ struct Purge: ParsableCommand { return 7 } - private func renderScan(_ cat: CategoryScan, days: Int) { + func renderScan(_ cat: CategoryScan, days: Int, colors: Bool = Term.colorEnabled) { let projectCount = cat.groups.count print("") - print(Term.bold("Found \(ByteCount.human(cat.allBytes)) across \(projectCount) project\(projectCount == 1 ? "" : "s")")) + print(Render.paint("Found \(ByteCount.human(cat.allBytes)) across \(projectCount) project\(projectCount == 1 ? "" : "s")", TextStyle(bold: true), colors)) for group in cat.groups { print("") - print(" \(Term.cyan(group.tool)) \(Term.dim(ByteCount.human(group.allBytes)))") + print(" \(Render.paint(group.tool, TextStyle(color: .cyan), colors)) \(Render.paint(ByteCount.human(group.allBytes), TextStyle(dim: true), colors))") for item in group.items { - let mark = item.selected ? Term.green("✓") : Term.dim("·") - let recent = item.selected ? "" : Term.dim(" recent") - print(" \(mark) \(Render.sizeCol(item.sizeBytes)) \(Render.shorten(item.path))\(recent)") + let mark = item.selected ? Render.paint("✓", TextStyle(color: .green), colors) : Render.paint("·", TextStyle(dim: true), colors) + let recent = item.selected ? "" : Render.paint(" recent", TextStyle(dim: true), colors) + print(" \(mark) \(Render.coloredSizeCol(item.sizeBytes, colors: colors)) \(Render.shorten(item.path))\(recent)") } } print("") - print(Term.dim("Artifacts newer than \(days) days are shown but left unchecked.")) + print(Render.paint("Artifacts newer than \(days) days are shown but left unchecked.", TextStyle(dim: true), colors)) } } diff --git a/cli/Sources/puremac/Core/Render.swift b/cli/Sources/puremac/Core/Render.swift index 10a6b36..aac7364 100644 --- a/cli/Sources/puremac/Core/Render.swift +++ b/cli/Sources/puremac/Core/Render.swift @@ -6,31 +6,31 @@ enum Render { static let rule = String(repeating: "─", count: 60) static let sizeColumnWidth = 10 - static func scanResults(_ categories: [CategoryScan]) { + static func scanResults(_ categories: [CategoryScan], colors: Bool = Term.colorEnabled) { let total = categories.reduce(Int64(0)) { $0 + $1.allBytes } let itemCount = categories.flatMap(\.groups).flatMap(\.items).count print("") - print(Term.bold("Scan complete")) + print(paint("Scan complete", TextStyle(bold: true), colors)) print( - Term.bold(ByteCount.human(total)) - + Term.dim(" across \(itemCount) item\(itemCount == 1 ? "" : "s")") + paint(ByteCount.human(total), TextStyle(bold: true), colors) + + paint(" across \(itemCount) item\(itemCount == 1 ? "" : "s")", TextStyle(dim: true), colors) ) for category in categories where !category.groups.isEmpty { print("") print( - Term.cyan(Term.bold(Term.sanitize(category.title))) - + Term.dim(" \(ByteCount.human(category.allBytes))") + paint(category.title, TextStyle(color: .cyan, bold: true), colors) + + paint(" \(ByteCount.human(category.allBytes))", TextStyle(dim: true), colors) ) for group in category.groups { print( - " " + Term.bold(Term.sanitize(group.tool)) - + Term.dim(" \(group.items.count) item\(group.items.count == 1 ? "" : "s")") + " " + paint(group.tool, TextStyle(bold: true), colors) + + paint(" \(group.items.count) item\(group.items.count == 1 ? "" : "s")", TextStyle(dim: true), colors) ) for item in group.items { - let mark = item.selected ? Term.cyan("●") : Term.dim("○") + let mark = item.selected ? paint("●", TextStyle(color: .cyan), colors) : paint("○", TextStyle(dim: true), colors) let path = displayedPath(item.path, available: max(12, outputWidth - 18)) - print(" \(mark) \(sizeCol(item.sizeBytes)) \(path)") + print(" \(mark) \(coloredSizeCol(item.sizeBytes, colors: colors)) \(path)") } } } @@ -46,32 +46,33 @@ enum Render { ) } - static func deletionReview(_ categories: [CategoryScan]) { + static func deletionReview(_ categories: [CategoryScan], colors: Bool = Term.colorEnabled) { let selected = categories.flatMap { $0.selectedItems } let total = selected.reduce(Int64(0)) { $0 + $1.sizeBytes } + let rule = paint(String(repeating: "─", count: min(72, outputWidth)), TextStyle(dim: true), colors) print("") - print(Term.yellow(Term.bold("Permanent deletion review"))) - print(Term.dim(String(repeating: "─", count: min(72, outputWidth)))) + print(paint("Permanent deletion review", TextStyle(color: .yellow, bold: true), colors)) + print(rule) for category in categories { let selectedInCategory = category.selectedItems guard !selectedInCategory.isEmpty else { continue } print( - Term.cyan(Term.sanitize(category.title)) - + Term.dim(" \(ByteCount.human(selectedInCategory.reduce(0) { $0 + $1.sizeBytes }))") + paint(category.title, TextStyle(color: .cyan), colors) + + paint(" \(ByteCount.human(selectedInCategory.reduce(0) { $0 + $1.sizeBytes }))", TextStyle(dim: true), colors) ) for group in category.groups { for item in group.items where item.selected { - print(" \(sizeCol(item.sizeBytes)) \(Term.sanitize(group.tool))") + print(" \(coloredSizeCol(item.sizeBytes, colors: colors)) \(Term.sanitize(group.tool))") print(" \(Term.sanitize(item.path))") } } } - print(Term.dim(String(repeating: "─", count: min(72, outputWidth)))) + print(rule) print( - Term.bold(ByteCount.human(total)) - + Term.dim(" \(selected.count) item\(selected.count == 1 ? "" : "s")") + paint(ByteCount.human(total), TextStyle(bold: true), colors) + + paint(" \(selected.count) item\(selected.count == 1 ? "" : "s")", TextStyle(dim: true), colors) ) } @@ -129,6 +130,14 @@ enum Render { pad(ByteCount.human(bytes), sizeColumnWidth) } + static func paint(_ text: String, _ style: TextStyle, _ colors: Bool) -> String { + Term.styled([Span(text, style)], colors: colors) + } + + static func coloredSizeCol(_ bytes: Int64, colors: Bool) -> String { + paint(sizeCol(bytes), SizeLevel.style(bytes: bytes, focused: false), colors) + } + static func pad(_ string: String, _ width: Int) -> String { Term.pad(string, to: width) } diff --git a/cli/Tests/TerminalUITests/GaugeTests.swift b/cli/Tests/TerminalUITests/GaugeTests.swift index 0a2d2af..456bb42 100644 --- a/cli/Tests/TerminalUITests/GaugeTests.swift +++ b/cli/Tests/TerminalUITests/GaugeTests.swift @@ -30,13 +30,12 @@ final class GaugeTests: XCTestCase { XCTAssertEqual(Gauge(fraction: 0.5).spans(width: -3), []) } - func testRoundingMatchesTermBar() { - for width in [1, 5, 12, 24] { - for step in 0...40 { - let fraction = Double(step) / 40 - let text = Gauge(fraction: fraction).spans(width: width).map(\.text).joined() - XCTAssertEqual(text, Term.bar(fraction: fraction, width: width)) - } + func testRoundingOfFilledCells() { + let cases: [(Double, Int, String)] = [ + (0.25, 8, "██░░░░░░"), (0.5, 5, "███░░"), (0.49, 12, "██████░░░░░░"), (0.99, 24, "████████████████████████") + ] + for (fraction, width, expected) in cases { + XCTAssertEqual(Gauge(fraction: fraction).spans(width: width).map(\.text).joined(), expected) } } } diff --git a/cli/Tests/TerminalUITests/TermTests.swift b/cli/Tests/TerminalUITests/TermTests.swift index c61c008..6e7a6b2 100644 --- a/cli/Tests/TerminalUITests/TermTests.swift +++ b/cli/Tests/TerminalUITests/TermTests.swift @@ -27,13 +27,6 @@ final class TermTests: XCTestCase { XCTAssertTrue(value.hasSuffix("ches/tool")) } - func testTermBarOutputIsUnchanged() { - XCTAssertEqual(Term.bar(fraction: 0.25, width: 8), "██░░░░░░") - XCTAssertEqual(Term.bar(fraction: 3, width: 3), "███") - XCTAssertEqual(Term.bar(fraction: 0.5, width: -2), "") - XCTAssertEqual(Term.bar(fraction: 0.5).count, 24) - } - func testWrapPreservesEveryCharacter() { let path = "/Users/example/a folder/with/a/very-long-name/file.bin" let lines = Term.wrap(path, width: 11) diff --git a/cli/Tests/puremacTests/PlainReportColorTests.swift b/cli/Tests/puremacTests/PlainReportColorTests.swift new file mode 100644 index 0000000..14966fc --- /dev/null +++ b/cli/Tests/puremacTests/PlainReportColorTests.swift @@ -0,0 +1,120 @@ +import XCTest +@testable import puremac +import TerminalUI + +final class PlainReportColorTests: XCTestCase { + private let small = ScanItem(path: "/tmp/a/small", sizeBytes: 50_000_000, modified: nil) + private let medium = ScanItem(path: "/tmp/a/medium", sizeBytes: 150_000_000, modified: nil, selected: false) + private let large = ScanItem(path: "/tmp/a/large", sizeBytes: 2_000_000_000, modified: nil) + + private var categories: [CategoryScan] { + [CategoryScan(id: "c", title: "Caches", groups: [ToolGroup(tool: "Xcode", items: [small, medium, large])])] + } + + private func colored(_ bytes: Int64, _ code: Int) -> String { + "\u{1B}[0m\u{1B}[\(code)m\(Render.sizeCol(bytes))\u{1B}[0m" + } + + private func stripped(_ colored: String) -> String { + colored.replacingOccurrences(of: "\u{1B}\\[[0-9;]*m", with: "", options: .regularExpression) + } + + private func assertSameTextWithColors(_ plain: String, _ output: String, file: StaticString = #filePath, line: UInt = #line) { + XCTAssertNotEqual(output, plain, file: file, line: line) + XCTAssertEqual(stripped(output), plain, file: file, line: line) + } + + func testScanResultsPlainTextIsPinned() throws { + let output = try captureStdout { Render.scanResults(categories, colors: false) } + XCTAssertEqual(output, """ + + Scan complete + 2.2 GB across 3 items + + Caches 2.2 GB + Xcode 3 items + ● 50 MB /tmp/a/small + ○ 150 MB /tmp/a/medium + ● 2 GB /tmp/a/large + + """) + } + + func testDeletionReviewPlainTextIsPinned() throws { + let output = try captureStdout { Render.deletionReview(categories, colors: false) } + XCTAssertEqual(output, """ + + Permanent deletion review + ──────────────────────────────────────────────────────────────────────── + Caches 2 GB + 50 MB Xcode + /tmp/a/small + 2 GB Xcode + /tmp/a/large + ──────────────────────────────────────────────────────────────────────── + 2 GB 2 items + + """) + } + + func testPurgeRenderScanPlainTextIsPinned() throws { + let output = try captureStdout { Purge().renderScan(categories[0], days: 7, colors: false) } + XCTAssertEqual(output, """ + + Found 2.2 GB across 1 project + + Xcode 2.2 GB + ✓ 50 MB /tmp/a/small + · 150 MB /tmp/a/medium recent + ✓ 2 GB /tmp/a/large + + Artifacts newer than 7 days are shown but left unchecked. + + """) + } + + func testAnalyzePrintLevelPlainTextIsPinned() throws { + let children = [ + Analyze.Child(path: "/tmp/a/big", size: 300_000_000, isDir: false, isPackage: false, inaccessibleCount: 0, skippedCount: 0), + Analyze.Child(path: "/tmp/a/dir", size: 100_000_000, isDir: false, isPackage: false, inaccessibleCount: 1, skippedCount: 0) + ] + let output = try captureStdout { Analyze().printLevel(children, total: 400_000_000, indent: " ", depthLeft: 0, colors: false) } + XCTAssertEqual(output, """ + 300 MB 75.0% ███████████████░░░░░ big + 100 MB 25.0% █████░░░░░░░░░░░░░░░ dir ! + + """) + } + + func testScanResultsColorsSizesAndStylesWithTheFlag() throws { + let plain = try captureStdout { Render.scanResults(categories, colors: false) } + let output = try captureStdout { Render.scanResults(categories, colors: true) } + assertSameTextWithColors(plain, output) + XCTAssertTrue(output.contains(colored(2_000_000_000, 31))) + XCTAssertTrue(output.contains("\u{1B}[0m\u{1B}[1mScan complete\u{1B}[0m")) + } + + func testDeletionReviewColorsSizesAndStylesWithTheFlag() throws { + let plain = try captureStdout { Render.deletionReview(categories, colors: false) } + let output = try captureStdout { Render.deletionReview(categories, colors: true) } + assertSameTextWithColors(plain, output) + XCTAssertTrue(output.contains(colored(50_000_000, 32))) + XCTAssertFalse(output.contains(colored(150_000_000, 33))) + } + + func testPurgeRenderScanColorsSizesAndStylesWithTheFlag() throws { + let plain = try captureStdout { Purge().renderScan(categories[0], days: 7, colors: false) } + let output = try captureStdout { Purge().renderScan(categories[0], days: 7, colors: true) } + assertSameTextWithColors(plain, output) + XCTAssertTrue(output.contains(colored(150_000_000, 33))) + } + + func testPrintLevelColorsSizeAndFilledBar() throws { + let child = Analyze.Child(path: "/tmp/a/big", size: 300_000_000, isDir: false, isPackage: false, inaccessibleCount: 0, skippedCount: 0) + let output = try captureStdout { Analyze().printLevel([child], total: 400_000_000, indent: " ", depthLeft: 0, colors: true) } + let size = "\u{1B}[0m\u{1B}[33m300 MB \u{1B}[0m" + let bar = "\u{1B}[0m\u{1B}[33m" + String(repeating: "█", count: 15) + "\u{1B}[0m\u{1B}[2m" + String(repeating: "░", count: 5) + "\u{1B}[0m" + let percentage = "\u{1B}[0m\u{1B}[2m 75.0%\u{1B}[0m" + XCTAssertEqual(output, " \(size) \(percentage) \(bar) big\n") + } +} From 75b6bd788401582a6d3232903e9d32d054919f58 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 14:06:16 +0000 Subject: [PATCH 13/21] feat(cli): add configurable project folders and create settings files on first start --- cli/README.md | 2 + cli/Sources/puremac/Commands/Config.swift | 10 +- cli/Sources/puremac/Commands/Purge.swift | 24 +- cli/Sources/puremac/Core/Stores.swift | 104 +++++-- cli/Sources/puremac/PureMac.swift | 1 + cli/Tests/puremacTests/CaptureSupport.swift | 13 + .../puremacTests/ConfigSettingsTests.swift | 279 ++++++++++++++++++ .../puremacTests/PreferencesSheetTests.swift | 17 +- 8 files changed, 395 insertions(+), 55 deletions(-) create mode 100644 cli/Tests/puremacTests/ConfigSettingsTests.swift diff --git a/cli/README.md b/cli/README.md index 185cf40..bb364c5 100644 --- a/cli/README.md +++ b/cli/README.md @@ -36,6 +36,8 @@ puremac purge ~/Projects puremac analyze ~/Projects ``` +`puremac purge` with no path scans the project folders from Preferences, by default ~/Projects, ~/Code, ~/dev, ~/GitHub and ~/Workspace. The first interactive start creates `~/.config/puremac/config.json` and an empty `~/.config/puremac/ignore`; existing files are never overwritten. + Cleanup opens a selection screen. Nothing is selected when the interactive review begins. Move through the list, choose individual paths, and check the running size total. Press Return to remove the selection; a confirmation dialog opens first. | Key | Action | diff --git a/cli/Sources/puremac/Commands/Config.swift b/cli/Sources/puremac/Commands/Config.swift index b2e2115..bcf843a 100644 --- a/cli/Sources/puremac/Commands/Config.swift +++ b/cli/Sources/puremac/Commands/Config.swift @@ -56,12 +56,9 @@ struct Config: ParsableCommand { static let sheetTitle = "PureMac CLI settings" static func sheet(store: ConfigStore) -> InfoSheet { - let keys = ConfigStore.knownKeys.map { key -> InfoRow in - let saved = store.values[key] - let value = saved ?? ConfigStore.defaultValues[key] ?? "" - let note = saved == nil ? Span("default", TextStyle(dim: true)) : Span("saved", TextStyle(color: .cyan)) - return .metric(label: key, value: [Span("\(value) days")], note: note) - } + let days = store.olderThanDays + let note = days == ConfigStore.defaultDays ? Span("default", TextStyle(dim: true)) : Span("saved", TextStyle(color: .cyan)) + let keys = [InfoRow.metric(label: ConfigStore.daysKey, value: [Span("\(days) days")], note: note)] let files = [("Settings", AppPaths.configFile), ("Protected", AppPaths.ignoreFile)].map { label, url in InfoRow.metric(label: label, value: [Span(Render.shorten(url.path))], note: nil) } @@ -71,6 +68,7 @@ struct Config: ParsableCommand { sections: [ InfoSection(title: nil, labelWidth: 26, rows: keys), InfoSection(title: "Files", labelWidth: 12, rows: files), + InfoSection(title: "Project folders", rows: store.projectRoots.map { .path(Render.shorten($0)) }), ], footnote: nil ) diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 2d8f62f..3c37464 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -6,16 +6,16 @@ struct Purge: ParsableCommand { static let configuration = CommandConfiguration( abstract: "Find removable build artifacts inside project folders (node_modules, target, .venv, …).", discussion: """ - With no path, scans ~/Projects, ~/Code, ~/dev, ~/GitHub, ~/Workspace. + With no path, scans the project folders from Preferences, by default ~/Projects, ~/Code, ~/dev, ~/GitHub, ~/Workspace. Interactive review starts empty so recent and older artifacts are both selectable. - puremac purge Scan the default project folders + puremac purge Scan the configured project folders puremac purge ~/Work/app Scan a specific folder Finishing the selector only opens an exact deletion review; a separate confirmation defaults to No. --plain uses a numbered selector with ranges, all, and none. --force removes only artifacts older than the configured threshold without either prompt. --dry-run and --json never delete or open a selector. """ ) - @Argument(help: "Folder(s) to scan. Omit to scan the default project locations.") + @Argument(help: "Folder(s) to scan. Omit to scan the configured project folders.") var paths: [String] = [] @Option(name: .customLong("older-than"), help: "Age threshold used by --force and read-only reports (default 7, or config).") @@ -56,9 +56,11 @@ struct Purge: ParsableCommand { let ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) let days = try resolvedDays() - let roots = paths.isEmpty - ? Purger.defaultRoots - : paths.map { Safety.absolutePath($0) } + let roots = try resolvedRoots() + guard !roots.isEmpty || json else { + print(Term.dim(Purge.noFoldersMessage)) + return + } let scanning = "Scanning " + roots.map { Render.shorten($0) }.joined(separator: ", ") + " …" if mode == .fullscreen { @@ -124,13 +126,17 @@ struct Purge: ParsableCommand { if out.hadFailures { throw ExitCode.failure } } + static let noFoldersMessage = "No project folders configured. Add one in Preferences." static let emptyMessage = "No project artifacts found in readable locations." private func resolvedDays() throws -> Int { if olderThanDays >= 0 { return olderThanDays } - let config = try ConfigStore(fileURL: AppPaths.configFile) - if let v = config.values["purge.older_than_days"], let n = Int(v), (0...3650).contains(n) { return n } - return 7 + return try ConfigStore(fileURL: AppPaths.configFile).olderThanDays + } + + func resolvedRoots() throws -> [String] { + guard paths.isEmpty else { return paths.map { Safety.absolutePath($0) } } + return try ConfigStore(fileURL: AppPaths.configFile).projectRoots } func renderScan(_ cat: CategoryScan, days: Int, colors: Bool = Term.colorEnabled) { diff --git a/cli/Sources/puremac/Core/Stores.swift b/cli/Sources/puremac/Core/Stores.swift index 73844f9..00fb69f 100644 --- a/cli/Sources/puremac/Core/Stores.swift +++ b/cli/Sources/puremac/Core/Stores.swift @@ -17,8 +17,21 @@ enum AppPaths { static var ignoreFile: URL { configDir.appendingPathComponent("ignore") } static var configFile: URL { configDir.appendingPathComponent("config.json") } - static func ensureDir() throws { - try FileManager.default.createDirectory(at: configDir, withIntermediateDirectories: true) + static func ensureDefaults(configFile: URL = configFile, ignoreFile: URL = ignoreFile) throws { + let results = [ + Result { try createIfMissing(configFile, try ConfigStore.defaultFileData()) }, + Result { try createIfMissing(ignoreFile, Data()) }, + ] + for case .failure(let error) in results { throw error } + } + + private static func createIfMissing(_ file: URL, _ data: Data) throws { + guard !FileManager.default.fileExists(atPath: file.path) else { return } + try FileManager.default.createDirectory( + at: file.deletingLastPathComponent(), + withIntermediateDirectories: true + ) + try data.write(to: file, options: .withoutOverwriting) } } @@ -26,6 +39,7 @@ enum StoreError: LocalizedError { case invalidConfigFile(String) case unknownConfigKey(String) case invalidConfigValue(key: String, value: String) + case invalidProjectRoot(String) case invalidIgnorePath case invalidIgnoreFile(String) @@ -37,6 +51,8 @@ enum StoreError: LocalizedError { return "Unknown setting '\(key)'." case .invalidConfigValue(let key, let value): return "Invalid value '\(value)' for \(key). Use a whole number from 1 to 3650." + case .invalidProjectRoot(let path): + return "Project folders must be absolute paths: \(path)" case .invalidIgnorePath: return "Protected paths cannot be empty, the filesystem root, or contain newline or NUL characters." case .invalidIgnoreFile(let path): @@ -180,37 +196,41 @@ struct IgnoreStore { struct ConfigStore { private(set) var values: [String: String] + private var savedRoots: [String]? private let fileURL: URL - static let knownKeys = ["purge.older_than_days"] - static let defaultValues = ["purge.older_than_days": "7"] + static let daysKey = "purge.older_than_days" + static let rootsKey = "purge.roots" + static let knownKeys = [daysKey] + static let defaultDays = 7 - init() { - fileURL = AppPaths.configFile - values = (try? Self.load(from: fileURL)) ?? [:] - } + var olderThanDays: Int { values[Self.daysKey].flatMap { Int($0) } ?? Self.defaultDays } + var projectRoots: [String] { savedRoots ?? Purger.defaultRoots } init(fileURL: URL) throws { self.fileURL = fileURL - values = try Self.load(from: fileURL) + (values, savedRoots) = try Self.load(from: fileURL) } mutating func set(_ key: String, _ value: String) throws { let normalized = try Self.normalizedValue(value, for: key) var updated = values updated[key] = normalized - let data = try JSONSerialization.data( - withJSONObject: updated, - options: [.prettyPrinted, .sortedKeys] - ) - try FileManager.default.createDirectory( - at: fileURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try data.write(to: fileURL, options: .atomic) + try save(values: updated, roots: savedRoots) values = updated } + mutating func setProjectRoots(_ roots: [String]) throws { + let standardized = try roots.map { root -> String in + guard let path = Self.standardizedRoot(root) else { + throw StoreError.invalidProjectRoot(root) + } + return path + } + try save(values: values, roots: standardized) + savedRoots = standardized + } + static func normalizedValue(_ value: String, for key: String) throws -> String { guard knownKeys.contains(key) else { throw StoreError.unknownConfigKey(key) @@ -222,17 +242,49 @@ struct ConfigStore { return String(days) } - private static func load(from fileURL: URL) throws -> [String: String] { - guard FileManager.default.fileExists(atPath: fileURL.path) else { return [:] } + static func defaultFileData() throws -> Data { + try encode(values: [daysKey: String(defaultDays)], roots: Purger.defaultRoots) + } + + private static func standardizedRoot(_ path: String) -> String? { + path.hasPrefix("/") ? (path as NSString).standardizingPath : nil + } + + private static func encode(values: [String: String], roots: [String]?) throws -> Data { + var object: [String: Any] = values + if let roots { object[rootsKey] = roots } + return try JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted, .sortedKeys]) + } + + private func save(values: [String: String], roots: [String]?) throws { + let data = try Self.encode(values: values, roots: roots) + try FileManager.default.createDirectory( + at: fileURL.deletingLastPathComponent(), + withIntermediateDirectories: true + ) + try data.write(to: fileURL, options: .atomic) + } + + private static func load(from fileURL: URL) throws -> ([String: String], [String]?) { + guard FileManager.default.fileExists(atPath: fileURL.path) else { return ([:], nil) } let data = try Data(contentsOf: fileURL) - guard let object = try? JSONSerialization.jsonObject(with: data), - let values = object as? [String: String] - else { + guard let object = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] else { throw StoreError.invalidConfigFile(fileURL.path) } - for (key, value) in values { - _ = try normalizedValue(value, for: key) + var values: [String: String] = [:] + var roots: [String]? + for (key, raw) in object { + if key == rootsKey { + guard let list = raw as? [String] else { throw StoreError.invalidConfigFile(fileURL.path) } + roots = try list.map { root in + guard let path = standardizedRoot(root) else { throw StoreError.invalidConfigFile(fileURL.path) } + return path + } + } else { + guard let text = raw as? String else { throw StoreError.invalidConfigFile(fileURL.path) } + values[key] = try normalizedValue(text, for: key) + } } - return values + return (values, roots) } } diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index fc55a01..e1563d5 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -23,6 +23,7 @@ struct PureMac: ParsableCommand { print(Self.helpMessage()) return } + try? AppPaths.ensureDefaults() try HomeMenu.run() } } diff --git a/cli/Tests/puremacTests/CaptureSupport.swift b/cli/Tests/puremacTests/CaptureSupport.swift index ce1a8c5..c25eb31 100644 --- a/cli/Tests/puremacTests/CaptureSupport.swift +++ b/cli/Tests/puremacTests/CaptureSupport.swift @@ -36,3 +36,16 @@ extension InteractiveReviewModel { return model } } + +func withConfigHome(_ body: (URL) throws -> T) throws -> T { + let directory = FileManager.default.temporaryDirectory + .appendingPathComponent("puremac-config-home-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + let saved = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"] + setenv("XDG_CONFIG_HOME", directory.path, 1) + defer { + if let saved { setenv("XDG_CONFIG_HOME", saved, 1) } else { unsetenv("XDG_CONFIG_HOME") } + try? FileManager.default.removeItem(at: directory) + } + return try body(directory.appendingPathComponent("puremac", isDirectory: true)) +} diff --git a/cli/Tests/puremacTests/ConfigSettingsTests.swift b/cli/Tests/puremacTests/ConfigSettingsTests.swift new file mode 100644 index 0000000..d45d42f --- /dev/null +++ b/cli/Tests/puremacTests/ConfigSettingsTests.swift @@ -0,0 +1,279 @@ +import Foundation +import XCTest +@testable import puremac +import TerminalUI + +private func write(_ text: String, to file: URL) throws { + try FileManager.default.createDirectory(at: file.deletingLastPathComponent(), withIntermediateDirectories: true) + try Data(text.utf8).write(to: file) +} + +final class ConfigSettingsTests: XCTestCase { + private var directory: URL! + private var file: URL { directory.appendingPathComponent("puremac/config.json") } + + override func setUpWithError() throws { + directory = FileManager.default.temporaryDirectory + .appendingPathComponent("puremac-settings-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + } + + override func tearDown() { + try? FileManager.default.removeItem(at: directory) + } + + func testMissingFileGivesTheDefaults() throws { + let store = try ConfigStore(fileURL: file) + XCTAssertEqual(store.olderThanDays, 7) + XCTAssertEqual(store.projectRoots, Purger.defaultRoots) + } + + func testOldFileWithOnlyTheDaysKeyStillLoads() throws { + try write(#"{"purge.older_than_days": "14"}"#, to: file) + let store = try ConfigStore(fileURL: file) + XCTAssertEqual(store.olderThanDays, 14) + XCTAssertEqual(store.projectRoots, Purger.defaultRoots) + } + + func testNewFileLoadsTheRootsInOrder() throws { + try write(#"{"purge.older_than_days": "30", "purge.roots": ["/tmp/b", "/tmp/a"]}"#, to: file) + let store = try ConfigStore(fileURL: file) + XCTAssertEqual(store.olderThanDays, 30) + XCTAssertEqual(store.projectRoots, ["/tmp/b", "/tmp/a"]) + } + + func testWrongTypesAndRootsAreInvalidConfigFiles() throws { + let bad = [ + #"{"purge.roots": "/tmp/a"}"#, + #"{"purge.roots": ["/tmp/a", 3]}"#, + #"{"purge.roots": ["relative/path"]}"#, + #"{"purge.roots": [""]}"#, + #"{"purge.older_than_days": 14}"#, + "[]", + ] + for text in bad { + try write(text, to: file) + XCTAssertThrowsError(try ConfigStore(fileURL: file), text) { error in + guard case StoreError.invalidConfigFile = error else { return XCTFail("\(text): \(error)") } + } + } + } + + func testBadDaysValuesAndUnknownKeysKeepTheirValueErrors() throws { + let bad = [ + (#"{"purge.older_than_days": "0"}"#, "invalidConfigValue"), + (#"{"purge.older_than_days": "x", "purge.roots": []}"#, "invalidConfigValue"), + (#"{"other": "1"}"#, "unknownConfigKey"), + ] + for (text, name) in bad { + try write(text, to: file) + XCTAssertThrowsError(try ConfigStore(fileURL: file), text) { error in + XCTAssertTrue("\(error)".hasPrefix(name), "\(text): \(error)") + } + } + } + + func testDaysWithSurroundingWhitespaceAreStoredNormalized() throws { + try write(#"{"purge.older_than_days": " 14\n"}"#, to: file) + XCTAssertEqual(try ConfigStore(fileURL: file).olderThanDays, 14) + } + + func testEmptyRootsListIsKeptAndNotReplacedByDefaults() throws { + try write(#"{"purge.roots": []}"#, to: file) + XCTAssertEqual(try ConfigStore(fileURL: file).projectRoots, []) + } + + func testRootsRoundTripKeepOrderAndSurviveASetOfTheDays() throws { + var store = try ConfigStore(fileURL: file) + try store.setProjectRoots(["/tmp/z", "/tmp/a/../a", "/tmp/m/"]) + XCTAssertEqual(store.projectRoots, ["/tmp/z", "/tmp/a", "/tmp/m"]) + + var reloaded = try ConfigStore(fileURL: file) + XCTAssertEqual(reloaded.projectRoots, ["/tmp/z", "/tmp/a", "/tmp/m"]) + try reloaded.set("purge.older_than_days", "90") + + let again = try ConfigStore(fileURL: file) + XCTAssertEqual(again.olderThanDays, 90) + XCTAssertEqual(again.projectRoots, ["/tmp/z", "/tmp/a", "/tmp/m"]) + } + + func testSavedFileHasSortedKeysAndIsPrettyPrinted() throws { + var store = try ConfigStore(fileURL: file) + try store.set("purge.older_than_days", "14") + try store.setProjectRoots(["/tmp/a"]) + let text = try String(contentsOf: file, encoding: .utf8) + let days = try XCTUnwrap(text.range(of: "purge.older_than_days")) + let roots = try XCTUnwrap(text.range(of: "purge.roots")) + XCTAssertLessThan(days.lowerBound, roots.lowerBound) + XCTAssertTrue(text.contains("\n \""), text) + } + + func testRelativeRootsAreRejectedAndNothingIsSaved() throws { + var store = try ConfigStore(fileURL: file) + XCTAssertThrowsError(try store.setProjectRoots(["relative"])) { error in + guard case StoreError.invalidProjectRoot("relative") = error else { return XCTFail("\(error)") } + } + XCTAssertEqual(store.projectRoots, Purger.defaultRoots) + XCTAssertFalse(FileManager.default.fileExists(atPath: file.path)) + } + + func testInvalidProjectRootMessageNamesTheFolder() { + XCTAssertEqual( + StoreError.invalidProjectRoot("relative").errorDescription, + "Project folders must be absolute paths: relative" + ) + } + + func testRootsAreNotSettableThroughConfigSet() { + XCTAssertThrowsError(try Config.parse(["set", "purge.roots", "/tmp/a"])) + } + + func testEnsureDefaultsCreatesBothFilesWithDefaults() throws { + let config = directory.appendingPathComponent("puremac/config.json") + let ignore = directory.appendingPathComponent("puremac/ignore") + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + + let store = try ConfigStore(fileURL: config) + XCTAssertEqual(store.olderThanDays, 7) + XCTAssertEqual(store.projectRoots, Purger.defaultRoots) + let saved = try String(contentsOf: config, encoding: .utf8) + XCTAssertTrue(saved.contains("purge.roots") && saved.contains("purge.older_than_days"), saved) + XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "") + XCTAssertEqual(try IgnoreStore(fileURL: ignore).roots, []) + } + + func testEnsureDefaultsNeverOverwritesExistingFiles() throws { + let config = directory.appendingPathComponent("puremac/config.json") + let ignore = directory.appendingPathComponent("puremac/ignore") + try write(#"{"purge.older_than_days": "14"}"#, to: config) + try write("/tmp/keep\n", to: ignore) + + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + + XCTAssertEqual(try String(contentsOf: config, encoding: .utf8), #"{"purge.older_than_days": "14"}"#) + XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "/tmp/keep\n") + } + + func testEnsureDefaultsFillsOnlyTheMissingFile() throws { + let config = directory.appendingPathComponent("puremac/config.json") + let ignore = directory.appendingPathComponent("puremac/ignore") + try write("/tmp/keep\n", to: ignore) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + XCTAssertTrue(FileManager.default.fileExists(atPath: config.path)) + XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "/tmp/keep\n") + } + + func testEnsureDefaultsLeavesAnInvalidConfigFileAlone() throws { + let config = directory.appendingPathComponent("puremac/config.json") + let ignore = directory.appendingPathComponent("puremac/ignore") + try write("[]", to: config) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + XCTAssertEqual(try String(contentsOf: config, encoding: .utf8), "[]") + } + + func testEnsureDefaultsCreatesTheIgnoreFileEvenWhenTheConfigFileFails() throws { + let blocker = directory.appendingPathComponent("blocker") + try write("x", to: blocker) + let config = blocker.appendingPathComponent("config.json") + let ignore = directory.appendingPathComponent("puremac/ignore") + XCTAssertThrowsError(try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore)) + XCTAssertTrue(FileManager.default.fileExists(atPath: ignore.path)) + } + + func testEnsureDefaultsCreatesTheConfigFileEvenWhenTheIgnoreFileFails() throws { + let blocker = directory.appendingPathComponent("blocker") + try write("x", to: blocker) + let config = directory.appendingPathComponent("puremac/config.json") + let ignore = blocker.appendingPathComponent("ignore") + XCTAssertThrowsError(try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore)) + XCTAssertTrue(FileManager.default.fileExists(atPath: config.path)) + } + + func testTheWorkspaceEntryPointCreatesNothingWithoutATerminal() throws { + try withConfigHome { dir in + _ = try captureStdout { try PureMac.parse([]).run() } + XCTAssertFalse(FileManager.default.fileExists(atPath: dir.path)) + } + } + + func testPurgeWithAnEmptyFolderListSaysSoAndDoesNotScan() throws { + try withConfigHome { _ in + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.setProjectRoots([]) + let output = try captureStdout { try Purge.parse(["--dry-run"]).run() } + XCTAssertEqual(output, Term.dim(Purge.noFoldersMessage) + "\n") + } + } + + func testOtherCommandsNeverCreateTheDefaultFiles() throws { + let scanned = directory.appendingPathComponent("scanned") + try FileManager.default.createDirectory(at: scanned, withIntermediateDirectories: true) + try withConfigHome { dir in + _ = try captureStdout { try Config.parse([]).run() } + _ = try captureStdout { try Ignore.List.parse([]).run() } + _ = try captureStdout { try Purge.parse([scanned.path, "--json"]).run() } + _ = try captureStdout { try Purge.parse([scanned.path, "--dry-run"]).run() } + XCTAssertFalse(FileManager.default.fileExists(atPath: dir.path)) + } + } + + func testPurgeWithoutPathsScansTheConfiguredRoots() throws { + try withConfigHome { _ in + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.setProjectRoots(["/tmp/one", "/tmp/two"]) + XCTAssertEqual(try Purge.parse([]).resolvedRoots(), ["/tmp/one", "/tmp/two"]) + } + } + + func testPurgeWithoutPathsFallsBackToTheDefaultsWithoutAFile() throws { + try withConfigHome { _ in + XCTAssertEqual(try Purge.parse([]).resolvedRoots(), Purger.defaultRoots) + } + } + + func testPurgeWithExplicitPathsIgnoresTheConfigFile() throws { + try withConfigHome { _ in + try write("[]", to: AppPaths.configFile) + let explicit = directory.appendingPathComponent("explicit") + try FileManager.default.createDirectory(at: explicit, withIntermediateDirectories: true) + let roots = try Purge.parse([explicit.path + "/../explicit"]).resolvedRoots() + XCTAssertEqual(roots, [Safety.absolutePath(explicit.path)]) + } + } + + func testConfigPlainOutputListsProjectFoldersAfterTheFiles() throws { + try withConfigHome { dir in + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.setProjectRoots(["\(Safety.home)/Work", "/tmp/other"]) + let output = try captureStdout { try Config.parse([]).run() } + XCTAssertEqual(output, """ + PureMac CLI settings + Values used when a command-line option is omitted + + purge.older_than_days 7 days default + + Files + Settings \(dir.path)/config.json + Protected \(dir.path)/ignore + + Project folders + ~/Work + /tmp/other + + """) + } + } + + func testAFileHoldingTheDefaultDaysShowsDefault() throws { + try withConfigHome { _ in + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.set("purge.older_than_days", "7") + let output = try captureStdout { try Config.parse([]).run() } + XCTAssertTrue(output.contains("\n purge.older_than_days 7 days default\n"), output) + try store.set("purge.older_than_days", "8") + let changed = try captureStdout { try Config.parse([]).run() } + XCTAssertTrue(changed.contains("8 days saved"), changed) + } + } +} diff --git a/cli/Tests/puremacTests/PreferencesSheetTests.swift b/cli/Tests/puremacTests/PreferencesSheetTests.swift index 476d5a8..9d8bb2b 100644 --- a/cli/Tests/puremacTests/PreferencesSheetTests.swift +++ b/cli/Tests/puremacTests/PreferencesSheetTests.swift @@ -3,19 +3,6 @@ import XCTest @testable import puremac import TerminalUI -private func withConfigHome(_ body: (URL) throws -> T) throws -> T { - let directory = FileManager.default.temporaryDirectory - .appendingPathComponent("puremac-sheet-tests-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) - let saved = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"] - setenv("XDG_CONFIG_HOME", directory.path, 1) - defer { - if let saved { setenv("XDG_CONFIG_HOME", saved, 1) } else { unsetenv("XDG_CONFIG_HOME") } - try? FileManager.default.removeItem(at: directory) - } - return try body(directory.appendingPathComponent("puremac", isDirectory: true)) -} - final class PlainCommandOutputTests: XCTestCase { func testConfigPrintsTodaysTextWithDefaultValue() throws { try withConfigHome { dir in @@ -30,6 +17,8 @@ final class PlainCommandOutputTests: XCTestCase { Settings \(dir.path)/config.json Protected \(dir.path)/ignore + Project folders + \(Purger.defaultRoots.map { " " + Render.shorten($0) + "\n" }.joined()) """) } } @@ -84,7 +73,7 @@ final class PreferencesSheetTests: XCTestCase { var sheet = Config.sheet(store: store) XCTAssertEqual(sheet.title, "PureMac CLI settings") XCTAssertEqual(sheet.subtitle, "Values used when a command-line option is omitted") - XCTAssertEqual(sheet.sections.map(\.title), [nil, "Files"]) + XCTAssertEqual(sheet.sections.map(\.title), [nil, "Files", "Project folders"]) guard case .metric("purge.older_than_days", let value, let note) = sheet.sections[0].rows[0] else { return XCTFail("key row") } XCTAssertEqual(value, [Span("7 days")]) XCTAssertEqual(note, Span("default", dim)) From 0198e516ffcd058f5c6dfe0402dc0f7b88b47720 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 14:46:53 +0000 Subject: [PATCH 14/21] feat(cli): edit project folders and protected paths inside the UI --- cli/Sources/TerminalUI/Dialog.swift | 58 +- cli/Sources/TerminalUI/Term.swift | 2 +- cli/Sources/TerminalUI/TextInput.swift | 44 ++ cli/Sources/puremac/Commands/Ignore.swift | 19 +- .../puremac/Core/InteractiveReview.swift | 30 +- cli/Sources/puremac/Core/PathListEditor.swift | 307 ++++++++++ cli/Sources/puremac/Core/Stores.swift | 2 +- cli/Sources/puremac/PureMac.swift | 6 +- cli/Tests/TerminalUITests/DialogTests.swift | 46 +- .../TerminalUITests/TextInputTests.swift | 72 +++ .../puremacTests/ConfigSettingsTests.swift | 15 + .../InteractiveScreensTests.swift | 33 ++ .../puremacTests/PathListEditorTests.swift | 547 ++++++++++++++++++ .../puremacTests/PreferencesSheetTests.swift | 25 +- 14 files changed, 1121 insertions(+), 85 deletions(-) create mode 100644 cli/Sources/TerminalUI/TextInput.swift create mode 100644 cli/Sources/puremac/Core/PathListEditor.swift create mode 100644 cli/Tests/TerminalUITests/TextInputTests.swift create mode 100644 cli/Tests/puremacTests/PathListEditorTests.swift diff --git a/cli/Sources/TerminalUI/Dialog.swift b/cli/Sources/TerminalUI/Dialog.swift index 85cc411..fabddfc 100644 --- a/cli/Sources/TerminalUI/Dialog.swift +++ b/cli/Sources/TerminalUI/Dialog.swift @@ -43,11 +43,16 @@ public struct Dialog { } private static let sidePadding = 1 + private static let titleMargin = 2 public static func maxContentWidth(in area: Rect) -> Int { max(1, area.width - 8 - 2 * Dialog.sidePadding) } + public static func maxTitleWidth(in area: Rect) -> Int { + max(1, maxContentWidth(in: area) - titleMargin) + } + public func frame(in area: Rect) -> Rect { placement(in: area).frame } @@ -58,14 +63,14 @@ public struct Dialog { let inner = Window(title: title, borderStyle: borderStyle, titleStyle: titleStyle) .render(in: frame, buffer: &buffer) let content = Rect(x: inner.x + Dialog.sidePadding, y: inner.y, width: max(0, inner.width - 2 * Dialog.sidePadding), height: inner.height) - var row = content.y + layout.blankAboveMessage + var row = content.y + layout.blankAboveFirst for message in layout.messageRows { renderMessage(message, in: content, row: row, buffer: &buffer) row += 1 } row += layout.blankBelowMessage - if !buttons.isEmpty { - renderButtons(in: content, row: row, buffer: &buffer) + for spans in buttonRows(width: content.width) { + renderCentered(spans, in: content, row: row, buffer: &buffer) row += 1 } row += layout.blankBelowButtons @@ -77,14 +82,14 @@ public struct Dialog { private struct Layout { var messageRows: [Span] - var blankAboveMessage = 0 + var blankAboveFirst = 0 var blankBelowMessage = 0 var blankBelowButtons = 0 var blankBelowLast = 0 var hintRows: Int var buttonRows: Int var height: Int { - messageRows.count + blankAboveMessage + blankBelowMessage + blankBelowButtons + blankBelowLast + buttonRows + hintRows + messageRows.count + blankAboveFirst + blankBelowMessage + blankBelowButtons + blankBelowLast + buttonRows + hintRows } } @@ -102,44 +107,45 @@ public struct Dialog { return (frame, layout) } - private var buttonSpans: [Span] { - var spans: [Span] = [] - for (index, button) in buttons.enumerated() { - if index > 0 { spans.append(Span(" ")) } - let title = Term.sanitize(button.title) - let focused = index == focusedButton - let style = TextStyle(color: button.role == .destructive ? .red : nil, inverse: focused) - spans.append(Span(focused ? "› \(title) ‹" : "[ \(title) ]", style)) - } - return spans + private func buttonSpan(_ index: Int) -> Span { + let button = buttons[index] + let title = Term.sanitize(button.title) + let style = TextStyle(color: button.role == .destructive ? .red : nil, inverse: index == focusedButton) + return Span(index == focusedButton ? "› \(title) ‹" : "[ \(title) ]", style) + } + + private func buttonRows(width: Int) -> [[Span]] { + guard !buttons.isEmpty else { return [] } + let spans = buttons.indices.map(buttonSpan) + let sideBySide = spans.enumerated().flatMap { $0.offset == 0 ? [$0.element] : [Span(" "), $0.element] } + return Term.displayWidth(sideBySide) <= width ? [sideBySide] : spans.map { [$0] } } private func contentWidth(maxWidth: Int) -> Int { - let titleWidth = Term.displayWidth(Term.sanitize(title)) + 2 + let titleWidth = Term.displayWidth(Term.sanitize(title)) + Dialog.titleMargin let messageWidth = message.map { Term.displayWidth(Term.sanitize($0.text)) }.max() ?? 0 - let buttonsWidth = Term.displayWidth(buttonSpans) + let buttonsWidth = buttonRows(width: maxWidth).map(Term.displayWidth).max() ?? 0 let hintWidth = hints?.rows(width: .max).first.map(Term.displayWidth) ?? 0 return max(1, min(max(titleWidth, messageWidth, buttonsWidth, hintWidth), maxWidth)) } private func layout(contentWidth: Int, maxRows: Int) -> Layout { let hintRows = hints?.rows(width: contentWidth).count ?? 0 - let buttonRows = buttons.isEmpty ? 0 : 1 + let buttonRows = self.buttonRows(width: contentWidth).count let tailRows = buttonRows + hintRows let wrapped = message.flatMap { paragraph in Term.wordWrap(paragraph.text, width: contentWidth).map { Span($0, paragraph.style) } } var layout = Layout(messageRows: wrapped, hintRows: hintRows, buttonRows: buttonRows) - if !wrapped.isEmpty { - layout.blankAboveMessage = 1 - layout.blankBelowMessage = tailRows > 0 ? 1 : 0 - } + let hasGroups = !wrapped.isEmpty || tailRows > 0 + layout.blankAboveFirst = hasGroups ? 1 : 0 + layout.blankBelowMessage = !wrapped.isEmpty && tailRows > 0 ? 1 : 0 layout.blankBelowButtons = buttonRows > 0 && hintRows > 0 ? 1 : 0 - layout.blankBelowLast = wrapped.isEmpty && tailRows == 0 ? 0 : 1 + layout.blankBelowLast = hasGroups ? 1 : 0 if layout.height > maxRows { layout.blankBelowLast = 0 } if layout.height > maxRows { layout.blankBelowButtons = 0 } if layout.height > maxRows { layout.blankBelowMessage = 0 } - if layout.height > maxRows { layout.blankAboveMessage = 0 } + if layout.height > maxRows { layout.blankAboveFirst = 0 } layout.messageRows = Array(wrapped.prefix(max(0, maxRows - layout.height + wrapped.count))) return layout } @@ -158,8 +164,4 @@ public struct Dialog { buffer.write([span], x: content.x, y: row, maxWidth: content.width) } } - - private func renderButtons(in content: Rect, row: Int, buffer: inout Buffer) { - renderCentered(buttonSpans, in: content, row: row, buffer: &buffer) - } } diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 99ef989..5c1e547 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -123,7 +123,7 @@ public enum Term { return output } - private static func suffix(_ string: String, width: Int) -> String { + static func suffix(_ string: String, width: Int) -> String { var characters: [Character] = [] var used = 0 for character in string.reversed() { diff --git a/cli/Sources/TerminalUI/TextInput.swift b/cli/Sources/TerminalUI/TextInput.swift new file mode 100644 index 0000000..95348ee --- /dev/null +++ b/cli/Sources/TerminalUI/TextInput.swift @@ -0,0 +1,44 @@ +public struct TextInput: Equatable { + public private(set) var text: String + + public init(_ text: String = "") { + self.text = text + } + + public var isEmpty: Bool { text.isEmpty } + + public mutating func insert(_ character: Character) { + text.append(character) + } + + public mutating func backspace() { + text = String(text.dropLast()) + } + + @discardableResult + public mutating func handle(_ key: TerminalKey) -> Bool { + switch key { + case .space: + insert(" ") + case .backspace, .delete: + guard !isEmpty else { return false } + backspace() + case .character(let character): + guard !character.unicodeScalars.allSatisfy({ $0.value < 0x20 || $0.value == 0x7F }) else { return false } + insert(character) + default: + return false + } + return true + } + + public func fieldSpans(label: String, width: Int) -> [Span] { + let room = max(1, width - Term.displayWidth(label) - 1) + let shown = Term.displayWidth(text) > room ? "…" + Term.suffix(text, width: room - 1) : text + return [ + Span(label, TextStyle(color: .cyan)), + Span(shown), + Span(" ", TextStyle(inverse: true)), + ] + } +} diff --git a/cli/Sources/puremac/Commands/Ignore.swift b/cli/Sources/puremac/Commands/Ignore.swift index 5d6a7ce..d66f0f9 100644 --- a/cli/Sources/puremac/Commands/Ignore.swift +++ b/cli/Sources/puremac/Commands/Ignore.swift @@ -38,31 +38,24 @@ struct Ignore: ParsableCommand { func run() throws { let store = try IgnoreStore(fileURL: AppPaths.ignoreFile) guard !store.roots.isEmpty else { - print(Term.styled(Self.emptyHint(quoted: true))) + print(Term.styled(Self.emptyHint())) return } print(Term.bold("Protected paths:")) for line in Self.sheet(roots: store.roots).plainLines(withHeader: false) { print(line) } } - static func emptyHint(quoted: Bool) -> [Span] { - let quote = quoted ? "`" : "" - return [ - Span("No protected paths. Add one with " + quote, TextStyle(dim: true)), + static func emptyHint() -> [Span] { + [ + Span("No protected paths. Add one with `", TextStyle(dim: true)), Span("puremac ignore add ", TextStyle(color: .cyan)), - Span(quote + ".", TextStyle(dim: true)), + Span("`.", TextStyle(dim: true)), ] } static func sheet(roots: [String]) -> InfoSheet { - let rows: [InfoRow] = roots.isEmpty - ? [.message(emptyHint(quoted: false))] - : roots.sorted().map { .path(Render.shorten($0)) } + let rows: [InfoRow] = roots.sorted().map { .path(Render.shorten($0)) } return InfoSheet(title: sheetTitle, subtitle: nil, sections: [InfoSection(title: nil, rows: rows)], footnote: nil) } - - static func currentSheet() throws -> InfoSheet { - sheet(roots: try IgnoreStore(fileURL: AppPaths.ignoreFile).roots) - } } } diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index beed0fb..44fdf80 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -23,13 +23,14 @@ enum ReviewKeyRoute: Equatable { struct InteractiveReviewModel { var categories: [CategoryScan] - var query = "" + private(set) var queryInput = TextInput() var isSearching = false var status = "" var pathOffset = 0 private(set) var focus = 0 private(set) var confirmation: ConfirmationButton? + var query: String { queryInput.text } var isConfirming: Bool { confirmation != nil } init(categories: [CategoryScan]) { @@ -137,12 +138,17 @@ struct InteractiveReviewModel { } mutating func updateQuery(_ value: String) { - query = value + queryInput = TextInput(value) focus = 0 pathOffset = 0 status = "" } + mutating func editQuery(_ key: TerminalKey) { + var edited = queryInput + if edited.handle(key) { updateQuery(edited.text) } + } + mutating func beginConfirmation() -> Bool { guard selectedCount > 0 else { status = "Select at least one item to continue" @@ -279,18 +285,8 @@ enum InteractiveReview { case .escape: model.isSearching = false model.updateQuery("") - case .backspace, .delete: - if !model.query.isEmpty { - model.updateQuery(String(model.query.dropLast())) - } - case .space: - model.updateQuery(model.query + " ") - case .character(let character): - if !character.isASCIIControl { - model.updateQuery(model.query + String(character)) - } default: - break + model.editQuery(key) } continue } @@ -426,9 +422,7 @@ enum InteractiveReview { let found = "\(model.matchingAddresses.count) shown · \(ByteCount.human(model.allBytes))" let left: [Span] if model.isSearching { - let label = "Search " - let query = Term.truncate(model.query, to: max(1, rect.width - label.count - 1)) - left = [Span(label, TextStyle(color: .cyan)), Span(query), Span(" ", TextStyle(inverse: true))] + left = model.queryInput.fieldSpans(label: "Search ", width: rect.width) } else if !model.status.isEmpty { left = [Span(Term.truncate(model.status, to: rect.width), TextStyle(color: .yellow))] } else if !model.query.isEmpty { @@ -524,10 +518,6 @@ enum InteractiveReview { } private extension Character { - var isASCIIControl: Bool { - unicodeScalars.allSatisfy { $0.value < 0x20 || $0.value == 0x7F } - } - var lowercasedString: String { String(self).lowercased() } diff --git a/cli/Sources/puremac/Core/PathListEditor.swift b/cli/Sources/puremac/Core/PathListEditor.swift new file mode 100644 index 0000000..ef3e8c2 --- /dev/null +++ b/cli/Sources/puremac/Core/PathListEditor.swift @@ -0,0 +1,307 @@ +import Foundation +import TerminalUI + +struct PathListError: LocalizedError { + let message: String + + init(_ message: String) { self.message = message } + + static func duplicate(_ path: String) -> PathListError { + PathListError("Already in the list: \(Render.shorten(path))") + } + + var errorDescription: String? { message } +} + +struct RemovalPrompt { + var title: (String) -> String + var button: String +} + +struct PathListConfig { + var title: String + var emptyText: String + var load: () throws -> [String] + var add: (String) throws -> Void + var remove: (String) throws -> Void + var removalPrompt: RemovalPrompt? +} + +extension PathListConfig { + private static func standardized(_ path: String) -> String { + (Safety.absolutePath(path) as NSString).standardizingPath + } + + static var projectFolders: PathListConfig { + PathListConfig( + title: "Project folders", + emptyText: "No project folders. Press A to add one.", + load: { try ConfigStore(fileURL: AppPaths.configFile).projectRoots }, + add: { input in + let typed = input.trimmingCharacters(in: .whitespaces) + guard !typed.isEmpty else { throw PathListError("Enter a folder path") } + let verdict = Safety.isValidScanRoot(typed) + guard verdict.ok else { throw PathListError(verdict.reason ?? "Not a valid project folder") } + var store = try ConfigStore(fileURL: AppPaths.configFile) + let root = standardized(typed) + guard !store.projectRoots.contains(root) else { + throw PathListError.duplicate(root) + } + try store.setProjectRoots(store.projectRoots + [root]) + }, + remove: { path in + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.setProjectRoots(store.projectRoots.filter { $0 != path }) + }, + removalPrompt: nil + ) + } + + static var protectedPaths: PathListConfig { + PathListConfig( + title: "Protected paths", + emptyText: "No protected paths. Press A to add one.", + load: { try IgnoreStore(fileURL: AppPaths.ignoreFile).roots.sorted() }, + add: { path in + var store = try IgnoreStore(fileURL: AppPaths.ignoreFile) + guard try store.add(path) else { + throw PathListError.duplicate(standardized(path)) + } + }, + remove: { path in + var store = try IgnoreStore(fileURL: AppPaths.ignoreFile) + _ = try store.remove(path) + }, + removalPrompt: RemovalPrompt( + title: { "Stop protecting \($0)?" }, + button: "Remove protection" + ) + ) + } +} + +struct PathListEditor { + private let config: PathListConfig + private(set) var paths: [String] = [] + private(set) var focus = 0 + private(set) var input: TextInput? + private(set) var confirmation: ButtonFocus? + private(set) var error: String? + private(set) var loadError: String? + + private static let browseHints = KeyHints([ + KeyHint("↑↓", "move"), KeyHint("A", "add"), KeyHint("D", "remove"), KeyHint("Esc", "back"), + ]) + private static let inputHints = KeyHints([KeyHint("Enter", "add"), KeyHint("Esc", "cancel")]) + private static let maxErrorRows = 2 + private static let buttonCount = 2 + private static let cancelIndex = 0 + private static let removeIndex = buttonCount - 1 + private static let inputLabel = "Add folder " + private static let notFound = " not found" + + init(_ config: PathListConfig) { + self.config = config + reload() + } + + mutating func handle(_ key: TerminalKey) -> Bool { + error = nil + if confirmation != nil { + handleConfirmation(key) + } else if input != nil { + handleInput(key) + } else { + return handleList(key) + } + return false + } + + func acceptsKey(_ key: TerminalKey, tooSmall: Bool) -> Bool { + guard tooSmall else { return true } + if let confirmation { + return key == .escape || (key == .enter && confirmation.index == Self.cancelIndex) + } + return key == .escape + } + + private mutating func handleList(_ key: TerminalKey) -> Bool { + switch key { + case .up: move(-1) + case .down: move(1) + case .escape, .left, .backspace, .delete: return true + case .character(let character): + switch character.lowercased() { + case "q": return true + case "a": input = TextInput("~/") + case "d": beginRemoval() + default: break + } + default: break + } + return false + } + + private mutating func handleInput(_ key: TerminalKey) { + switch key { + case .enter: + guard let text = input?.text else { return } + let add = config.add + if perform({ try add(text) }) { input = nil } + case .escape: input = nil + default: input?.handle(key) + } + } + + private mutating func handleConfirmation(_ key: TerminalKey) { + guard var buttons = confirmation else { return } + if buttons.navigate(key) { + confirmation = buttons + return + } + switch key { + case .enter: + confirmation = nil + if buttons.index == Self.removeIndex { removeFocused() } + case .escape: confirmation = nil + default: break + } + } + + private mutating func move(_ delta: Int) { + focus = min(max(0, paths.count - 1), max(0, focus + delta)) + } + + private mutating func beginRemoval() { + guard paths.indices.contains(focus) else { return } + if config.removalPrompt != nil { + confirmation = ButtonFocus(count: Self.buttonCount, index: Self.cancelIndex) + } else { + removeFocused() + } + } + + private mutating func removeFocused() { + let path = paths[focus] + let remove = config.remove + perform { try remove(path) } + } + + @discardableResult + private mutating func perform(_ change: () throws -> Void) -> Bool { + do { + try change() + } catch { + self.error = error.localizedDescription + return false + } + reload() + return true + } + + private mutating func reload() { + do { + paths = try config.load() + loadError = nil + } catch { + paths = [] + loadError = error.localizedDescription + } + move(0) + } + + func render(width: Int, height: Int) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: config.title, exitHint: "Esc back", width: width, height: height) + } + var buffer = Buffer(width: width, height: height) + let window = Window(title: config.title) + let content = window.render(in: buffer.area, buffer: &buffer) + let hints = input == nil ? Self.browseHints : Self.inputHints + let errorRows = errorRows(width: content.width) + let areas = content.splitRows([ + .fill, + .length(1), + .length(errorRows.count), + .length(input == nil ? 0 : 1), + .length(hints.rows(width: content.width).count), + ]) + let (list, divider, status, field, footer) = (areas[0], areas[1], areas[2], areas[3], areas[4]) + + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + hints.render(in: footer, buffer: &buffer) + for (offset, row) in errorRows.enumerated() { + buffer.write(row, x: status.x, y: status.y + offset, maxWidth: status.width) + } + if let input { + buffer.write(input.fieldSpans(label: Self.inputLabel, width: field.width), x: field.x, y: field.y, maxWidth: field.width) + } + renderList(in: list, buffer: &buffer) + guard let confirmation, let prompt = config.removalPrompt, paths.indices.contains(focus) else { return buffer } + let dialog = Dialog( + title: Self.removalTitle(prompt, path: paths[focus], area: buffer.area), + titleStyle: StatusScreen.warningTitle, + borderStyle: StatusScreen.warningBorder, + buttons: [DialogButton("Cancel"), DialogButton(prompt.button, role: .destructive)], + focusedButton: confirmation.index, + hints: StatusScreen.choiceHints + ) + return StatusScreen.overlay(dialog, on: buffer) + } + + private static func removalTitle(_ prompt: RemovalPrompt, path: String, area: Rect) -> String { + let room = Dialog.maxTitleWidth(in: area) - Term.displayWidth(prompt.title("")) + return prompt.title(Term.truncate(Render.shorten(path), to: max(1, room), middle: true)) + } + + private func errorRows(width: Int) -> [[Span]] { + guard let error else { return [] } + return Array(Term.wordWrap([Span(error, TextStyle(color: .yellow))], width: width).prefix(Self.maxErrorRows)) + } + + private func renderList(in rect: Rect, buffer: inout Buffer) { + guard !paths.isEmpty else { + let message = loadError.map { Span($0, TextStyle(color: .red)) } ?? Span(config.emptyText, TextStyle(dim: true)) + for (offset, row) in Term.wordWrap([message], width: rect.width).prefix(rect.height).enumerated() { + buffer.write(row, x: rect.x, y: rect.y + offset, maxWidth: rect.width) + } + return + } + let start = Scrollbar.centeredOffset(total: paths.count, visible: rect.height, focus: focus) + for (index, path) in paths.enumerated().dropFirst(start).prefix(rect.height) { + renderRow(path, focused: index == focus, in: Rect(x: rect.x, y: rect.y + index - start, width: rect.width, height: 1), buffer: &buffer) + } + Scrollbar(total: paths.count, visible: rect.height, offset: start) + .render(column: buffer.width - 1, rows: rect.y..<(rect.y + rect.height), buffer: &buffer) + } + + private func renderRow(_ path: String, focused: Bool, in rect: Rect, buffer: inout Buffer) { + let rowStyle = TextStyle(inverse: focused) + let note = FileManager.default.fileExists(atPath: path) ? "" : Self.notFound + let noteWidth = Term.displayWidth(note) + let shown = Term.truncate(Render.shorten(path), to: max(1, rect.width - 2 - noteWidth), middle: true) + let rest = max(0, rect.width - 2 - Term.displayWidth(shown) - noteWidth) + buffer.write( + [ + FocusPointer.span(focused: focused), + Span(" " + shown, rowStyle), + Span(note, TextStyle(dim: true, inverse: focused)), + Span(String(repeating: " ", count: rest), rowStyle), + ], + x: rect.x, + y: rect.y, + maxWidth: rect.width + ) + } + + static func run(_ config: PathListConfig, in session: TerminalSession) { + var editor = PathListEditor(config) + while true { + session.draw(editor.render(width: session.width, height: session.height)) + let key = session.readKey() + let tooSmall = !TooSmallScreen.fits(width: session.width, height: session.height) + guard editor.acceptsKey(key, tooSmall: tooSmall) else { continue } + if editor.handle(key) { return } + } + } +} diff --git a/cli/Sources/puremac/Core/Stores.swift b/cli/Sources/puremac/Core/Stores.swift index 00fb69f..792ee29 100644 --- a/cli/Sources/puremac/Core/Stores.swift +++ b/cli/Sources/puremac/Core/Stores.swift @@ -253,7 +253,7 @@ struct ConfigStore { private static func encode(values: [String: String], roots: [String]?) throws -> Data { var object: [String: Any] = values if let roots { object[rootsKey] = roots } - return try JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted, .sortedKeys]) + return try JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]) } private func save(values: [String: String], roots: [String]?) throws { diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index e1563d5..4e4fc34 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -32,6 +32,7 @@ enum HomeMenu { static let title = "PureMac" static let subtitle = "Your Mac, with room to work. / \(puremacVersion)" static let exploreIndex = 2 + static let protectedPathsIndex = 5 static let options: [(title: String, detail: String)] = [ ("Clean caches", "Choose tools and individual paths to remove"), ("Project cleanup", "Review dependencies and generated build artifacts"), @@ -70,6 +71,10 @@ enum HomeMenu { case exploreIndex: guard try ExploreConfirmation.ask() else { continue } try Analyze.parse([]).run() + case protectedPathsIndex: + let session = try TerminalSession() + defer { session.close() } + PathListEditor.run(.protectedPaths, in: session) default: return } } @@ -79,7 +84,6 @@ enum HomeMenu { switch choice { case 3: return InfoSheet.loading(title: Optimize.statusTitle, Optimize.currentStatusSheet) case 4: return InfoSheet.loading(title: Config.sheetTitle, Config.currentSheet) - case 5: return InfoSheet.loading(title: Ignore.List.sheetTitle, Ignore.List.currentSheet) default: return nil } } diff --git a/cli/Tests/TerminalUITests/DialogTests.swift b/cli/Tests/TerminalUITests/DialogTests.swift index b0428c5..824d9a7 100644 --- a/cli/Tests/TerminalUITests/DialogTests.swift +++ b/cli/Tests/TerminalUITests/DialogTests.swift @@ -208,20 +208,39 @@ final class DialogTests: XCTestCase { ]) XCTAssertEqual(render(Dialog(title: "Title", buttons: [DialogButton("OK")]), in: area).rows, [ "╭─ Title ───╮", + "│ │", "│ [ OK ] │", "│ │", "╰───────────╯" ]) - var buttonsAndHints = Dialog(title: "T", buttons: [DialogButton("OK")]) - buttonsAndHints.hints = KeyHints([KeyHint("Esc", "back")]) - XCTAssertEqual(render(buttonsAndHints, in: area).rows, [ + } + + func testDialogWithoutMessageHasABlankRowAboveItsFirstGroup() { + var dialog = Dialog(title: "T", buttons: [DialogButton("OK")]) + dialog.hints = KeyHints([KeyHint("Esc", "back")]) + XCTAssertEqual(render(dialog, in: area).rows, [ "╭─ T ────────╮", + "│ │", "│ [ OK ] │", "│ │", "│ Esc back │", "│ │", "╰────────────╯" ]) + XCTAssertEqual(render(dialog, in: Rect(x: 0, y: 0, width: 40, height: 8)).rows, [ + "╭─ T ────────╮", + "│ │", + "│ [ OK ] │", + "│ │", + "│ Esc back │", + "╰────────────╯" + ]) + XCTAssertEqual(render(dialog, in: Rect(x: 0, y: 0, width: 40, height: 6)).rows, [ + "╭─ T ────────╮", + "│ [ OK ] │", + "│ Esc back │", + "╰────────────╯" + ]) } func testDropsBlankRowsBottomUpBeforeAnyMessageRow() { @@ -337,4 +356,25 @@ final class DialogTests: XCTestCase { "╰───────────────────────╯" ]) } + + func testMaxTitleWidthLeavesRoomForTheBorderPadding() { + XCTAssertEqual(Dialog.maxTitleWidth(in: Rect(x: 0, y: 0, width: 80, height: 24)), 68) + XCTAssertEqual(Dialog.maxTitleWidth(in: Rect(x: 0, y: 0, width: 4, height: 24)), 1) + } + + func testButtonsThatDoNotFitSideBySideStackOnePerRowCentered() throws { + let dialog = Dialog( + title: "Hi", + message: [Span("Sure?")], + buttons: [DialogButton("Cancel"), DialogButton("Remove protection", role: .destructive)] + ) + let result = render(dialog, in: area) + let content = (x: 3, width: result.frame.width - 6) + let cancelRow = 4 + for (offset, title) in ["[ Cancel ]", "[ Remove protection ]"].enumerated() { + let row = result.rows[cancelRow + offset] + let start = try XCTUnwrap(row.range(of: title), row).lowerBound + XCTAssertEqual(row.distance(from: row.startIndex, to: start), content.x + (content.width - title.count) / 2, row) + } + } } diff --git a/cli/Tests/TerminalUITests/TextInputTests.swift b/cli/Tests/TerminalUITests/TextInputTests.swift new file mode 100644 index 0000000..c98924d --- /dev/null +++ b/cli/Tests/TerminalUITests/TextInputTests.swift @@ -0,0 +1,72 @@ +import XCTest +@testable import TerminalUI + +final class TextInputTests: XCTestCase { + func testInsertAppendsAtTheEnd() { + var input = TextInput("ab") + input.insert("c") + XCTAssertEqual(input.text, "abc") + } + + func testBackspaceDropsTheLastCharacterAndIgnoresEmptyText() { + var input = TextInput("ab") + input.backspace() + XCTAssertEqual(input.text, "a") + input.backspace() + input.backspace() + XCTAssertEqual(input.text, "") + XCTAssertTrue(input.isEmpty) + } + + func testHandleEditsOnTypingKeysAndReportsWhetherTheTextChanged() { + var input = TextInput() + XCTAssertTrue(input.handle(.character("a"))) + XCTAssertTrue(input.handle(.space)) + XCTAssertTrue(input.handle(.character("é"))) + XCTAssertEqual(input.text, "a é") + XCTAssertTrue(input.handle(.backspace)) + XCTAssertTrue(input.handle(.delete)) + XCTAssertEqual(input.text, "a") + } + + func testHandleIgnoresControlCharactersAndOtherKeys() { + var input = TextInput("a") + XCTAssertFalse(input.handle(.character("\u{7F}"))) + XCTAssertFalse(input.handle(.character("\n"))) + for key in [TerminalKey.up, .down, .left, .right, .enter, .escape, .tab, .home, .unknown] { + XCTAssertFalse(input.handle(key), "\(key)") + } + XCTAssertEqual(input.text, "a") + } + + func testHandleReportsNoChangeForBackspaceOnEmptyText() { + var input = TextInput() + XCTAssertFalse(input.handle(.backspace)) + } + + func testFieldSpansShowLabelTextAndInverseCursor() { + let spans = TextInput("sec").fieldSpans(label: "Search ", width: 40) + XCTAssertEqual(spans, [ + Span("Search ", TextStyle(color: .cyan)), + Span("sec"), + Span(" ", TextStyle(inverse: true)), + ]) + } + + func testFieldSpansTruncateLongTextToLeaveRoomForTheCursor() { + let spans = TextInput(String(repeating: "x", count: 30)).fieldSpans(label: "Add ", width: 12) + XCTAssertEqual(Term.displayWidth(spans), 12) + XCTAssertEqual(spans.last, Span(" ", TextStyle(inverse: true))) + } + + func testFieldSpansKeepTheEndOfLongTextVisibleWithALeadingEllipsis() { + let spans = TextInput("/Users/someone/projects/final-name").fieldSpans(label: "Add ", width: 20) + XCTAssertEqual(Term.displayWidth(spans), 20) + XCTAssertEqual(spans[1], Span("…ts/final-name")) + } + + func testFieldSpansCountWideLabelCharactersAsTwoColumns() { + let spans = TextInput("abcdefghij").fieldSpans(label: "路径 ", width: 12) + XCTAssertEqual(Term.displayWidth(spans), 12) + } +} diff --git a/cli/Tests/puremacTests/ConfigSettingsTests.swift b/cli/Tests/puremacTests/ConfigSettingsTests.swift index d45d42f..d599a23 100644 --- a/cli/Tests/puremacTests/ConfigSettingsTests.swift +++ b/cli/Tests/puremacTests/ConfigSettingsTests.swift @@ -276,4 +276,19 @@ final class ConfigSettingsTests: XCTestCase { XCTAssertTrue(changed.contains("8 days saved"), changed) } } + + func testSavedFileKeepsSlashesUnescaped() throws { + var store = try ConfigStore(fileURL: file) + try store.setProjectRoots(["/Users/me/Projects"]) + let text = try String(contentsOf: file, encoding: .utf8) + XCTAssertTrue(text.contains("\"/Users/me/Projects\""), text) + XCTAssertFalse(text.contains("\\/"), text) + XCTAssertEqual(try ConfigStore(fileURL: file).projectRoots, ["/Users/me/Projects"]) + } + + func testDefaultFileKeepsSlashesUnescaped() throws { + let text = String(decoding: try ConfigStore.defaultFileData(), as: UTF8.self) + XCTAssertTrue(text.contains("\"\(Safety.home)/Projects\""), text) + XCTAssertFalse(text.contains("\\/"), text) + } } diff --git a/cli/Tests/puremacTests/InteractiveScreensTests.swift b/cli/Tests/puremacTests/InteractiveScreensTests.swift index 364ffd4..3a3f177 100644 --- a/cli/Tests/puremacTests/InteractiveScreensTests.swift +++ b/cli/Tests/puremacTests/InteractiveScreensTests.swift @@ -10,6 +10,30 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertEqual(model.matchingAddresses.count, 3) } + func testEditQueryTypesFiltersAndDeletes() { + var model = InteractiveReviewModel(categories: fixtureCategories()) + for key in [TerminalKey.character("s"), .character("e"), .character("c")] { model.editQuery(key) } + XCTAssertEqual(model.query, "sec") + XCTAssertEqual(model.matchingAddresses.count, 1) + model.editQuery(.backspace) + model.editQuery(.delete) + XCTAssertEqual(model.query, "s") + model.editQuery(.space) + XCTAssertEqual(model.query, "s ") + } + + func testEditQueryIgnoresControlKeysAndKeepsFocusWhenNothingChanged() { + var model = InteractiveReviewModel(categories: fixtureCategories()) + model.move(2) + model.status = "note" + model.editQuery(.backspace) + model.editQuery(.up) + model.editQuery(.character("\u{7F}")) + XCTAssertEqual(model.query, "") + XCTAssertEqual(model.focusedAddress, model.matchingAddresses[2]) + XCTAssertEqual(model.status, "note") + } + func testReviewSelectionAndSearchPreserveExactItems() { var model = InteractiveReviewModel(categories: fixtureCategories()) model.toggleFocused() @@ -114,6 +138,15 @@ final class InteractiveScreensTests: XCTestCase { XCTAssertFalse(line.contains("shown")) } + func testReviewSearchFieldKeepsTheEndOfALongQueryNextToTheCursor() { + var model = InteractiveReviewModel(categories: fixtureCategories()) + model.isSearching = true + model.updateQuery("abcdefghijklmnopqrstuvwxyz0123456789") + let buffer = renderReview(model, width: 40, height: 12) + XCTAssertEqual(buffer.plainLines()[1], "│ Search …klmnopqrstuvwxyz0123456789 │") + XCTAssertEqual(buffer[37, 1].style, TextStyle(inverse: true)) + } + func testReviewRowsShowCategoryGroupAndItemsWithFocus() { var model = InteractiveReviewModel(categories: fixtureCategories()) model.toggleFocused() diff --git a/cli/Tests/puremacTests/PathListEditorTests.swift b/cli/Tests/puremacTests/PathListEditorTests.swift new file mode 100644 index 0000000..7ebb7a6 --- /dev/null +++ b/cli/Tests/puremacTests/PathListEditorTests.swift @@ -0,0 +1,547 @@ +import XCTest +@testable import puremac +import TerminalUI + +private struct Rejected: LocalizedError { + var errorDescription: String? { "that path is not allowed" } +} + +private final class FakeList { + var paths: [String] + var added: [String] = [] + var removed: [String] = [] + var addError: Error? + var loadError: Error? + + init(_ paths: [String]) { self.paths = paths } + + func config(confirmsRemoval: Bool = false) -> PathListConfig { + PathListConfig( + title: "Project folders", + emptyText: "Nothing here yet. Press A to add one.", + load: { + if let error = self.loadError { throw error } + return self.paths + }, + add: { path in + if let error = self.addError { throw error } + self.added.append(path) + self.paths.append(path) + }, + remove: { path in + self.removed.append(path) + self.paths.removeAll { $0 == path } + }, + removalPrompt: confirmsRemoval + ? RemovalPrompt(title: { "Stop protecting \($0)?" }, button: "Remove protection") + : nil + ) + } +} + +final class PathListEditorTests: XCTestCase { + private let existing = FileManager.default.temporaryDirectory.resolvingSymlinksInPath().path + + private func editor(_ list: FakeList, confirmsRemoval: Bool = false) -> PathListEditor { + PathListEditor(list.config(confirmsRemoval: confirmsRemoval)) + } + + private func type(_ text: String, into editor: inout PathListEditor) { + for character in text { _ = editor.handle(character == " " ? .space : .character(character)) } + } + + private func lines(_ editor: PathListEditor, width: Int = 80, height: Int = 24) -> [String] { + editor.render(width: width, height: height).plainLines() + } + + func testStartsWithLoadedPathsAndFirstFocused() { + let editor = editor(FakeList([existing, "/tmp/puremac-b"])) + XCTAssertEqual(editor.paths, [existing, "/tmp/puremac-b"]) + XCTAssertEqual(editor.focus, 0) + } + + func testMovingStaysInsideTheList() { + var editor = editor(FakeList(["/a", "/b"])) + _ = editor.handle(.up) + XCTAssertEqual(editor.focus, 0) + _ = editor.handle(.down) + _ = editor.handle(.down) + XCTAssertEqual(editor.focus, 1) + } + + func testEscapeLeavesAndOtherKeysDoNot() { + var editor = editor(FakeList(["/a"])) + XCTAssertFalse(editor.handle(.down)) + XCTAssertFalse(editor.handle(.character("x"))) + XCTAssertTrue(editor.handle(.escape)) + } + + func testAOpensTheInputPrefilledWithTilde() { + var editor = editor(FakeList([])) + _ = editor.handle(.character("a")) + XCTAssertEqual(editor.input?.text, "~/") + var other = self.editor(FakeList([])) + _ = other.handle(.character("A")) + XCTAssertEqual(other.input?.text, "~/") + } + + func testInputRowShowsLabelTextAndInverseCursorBelowTheStatusRow() { + var editor = editor(FakeList(["/a"])) + _ = editor.handle(.character("a")) + type("pr", into: &editor) + let buffer = editor.render(width: 80, height: 24) + XCTAssertTrue(buffer.plainLines()[21].hasPrefix("│ Add folder ~/pr ")) + XCTAssertEqual(buffer[2, 21].style, TextStyle(color: .cyan)) + XCTAssertEqual(buffer[18, 21].style, TextStyle(inverse: true)) + } + + func testTypingBackspaceAndEnterAddsThePathAndClosesTheInput() { + let list = FakeList([]) + var editor = editor(list) + _ = editor.handle(.character("a")) + type("xy", into: &editor) + _ = editor.handle(.backspace) + type("z", into: &editor) + XCTAssertFalse(editor.handle(.enter)) + XCTAssertEqual(list.added, ["~/xz"]) + XCTAssertNil(editor.input) + XCTAssertNil(editor.error) + XCTAssertEqual(editor.paths, ["~/xz"]) + } + + func testRejectedPathShowsYellowErrorAndKeepsTheInputOpen() { + let list = FakeList(["/a"]) + list.addError = Rejected() + var editor = editor(list) + _ = editor.handle(.character("a")) + _ = editor.handle(.enter) + XCTAssertEqual(editor.input?.text, "~/") + XCTAssertEqual(editor.error, "that path is not allowed") + let buffer = editor.render(width: 80, height: 24) + XCTAssertTrue(buffer.plainLines()[20].hasPrefix("│ that path is not allowed")) + XCTAssertEqual(buffer[2, 20].style, TextStyle(color: .yellow)) + XCTAssertTrue(buffer.plainLines()[21].hasPrefix("│ Add folder ~/ ")) + XCTAssertEqual(list.paths, ["/a"]) + } + + func testLongErrorWrapsOverTwoRowsAboveTheInput() { + let list = FakeList([]) + list.addError = PathListError("Protected paths cannot be empty, the filesystem root, or contain only a very short folder, pick another folder instead") + var editor = editor(list) + _ = editor.handle(.character("a")) + _ = editor.handle(.enter) + let rows = lines(editor) + XCTAssertTrue(rows[19].hasPrefix("│ Protected paths cannot be empty"), rows[19]) + XCTAssertTrue(rows[20].contains("instead"), rows[20]) + XCTAssertTrue(rows[21].hasPrefix("│ Add folder ~/"), rows[21]) + } + + func testEditingClearsTheErrorAndKeepsTheInput() { + let list = FakeList([]) + list.addError = Rejected() + var editor = editor(list) + _ = editor.handle(.character("a")) + _ = editor.handle(.enter) + _ = editor.handle(.character("x")) + XCTAssertNil(editor.error) + XCTAssertEqual(editor.input?.text, "~/x") + } + + func testEscapeInTheInputCancelsItWithoutLeaving() { + var editor = editor(FakeList([])) + _ = editor.handle(.character("a")) + XCTAssertFalse(editor.handle(.escape)) + XCTAssertNil(editor.input) + XCTAssertTrue(editor.handle(.escape)) + } + + func testListKeysTypeIntoTheInputInsteadOfActing() { + var editor = editor(FakeList(["/a", "/b"])) + _ = editor.handle(.character("a")) + type("dd", into: &editor) + XCTAssertEqual(editor.input?.text, "~/dd") + XCTAssertEqual(editor.paths, ["/a", "/b"]) + } + + func testDRemovesTheFocusedPathWithoutAskingAndKeepsFocusInRange() { + let list = FakeList(["/a", "/b"]) + var editor = editor(list) + _ = editor.handle(.down) + _ = editor.handle(.character("d")) + XCTAssertEqual(list.removed, ["/b"]) + XCTAssertEqual(editor.paths, ["/a"]) + XCTAssertEqual(editor.focus, 0) + } + + func testRemoveOnEmptyListDoesNothing() { + let list = FakeList([]) + var editor = editor(list, confirmsRemoval: true) + _ = editor.handle(.character("d")) + XCTAssertTrue(list.removed.isEmpty) + XCTAssertNil(editor.confirmation) + } + + func testRemovalPromptFocusesCancelAndShowsTheDialog() { + var editor = editor(FakeList(["\(Safety.home)/secret"]), confirmsRemoval: true) + _ = editor.handle(.character("d")) + XCTAssertEqual(editor.confirmation?.index, 0) + let text = lines(editor).joined(separator: "\n") + XCTAssertTrue(text.contains("Stop protecting ~/secret?"), text) + XCTAssertTrue(text.contains("› Cancel ‹"), text) + XCTAssertTrue(text.contains("[ Remove protection ]"), text) + XCTAssertTrue(text.contains("Enter select"), text) + XCTAssertTrue(text.contains("Esc back"), text) + } + + func testRemovalPromptEnterOnCancelAndEscapeKeepThePath() { + let list = FakeList(["/a"]) + var editor = editor(list, confirmsRemoval: true) + _ = editor.handle(.character("d")) + XCTAssertFalse(editor.handle(.enter)) + XCTAssertNil(editor.confirmation) + _ = editor.handle(.character("d")) + XCTAssertFalse(editor.handle(.escape)) + XCTAssertNil(editor.confirmation) + XCTAssertTrue(list.removed.isEmpty) + } + + func testRemovalPromptEnterOnRemoveDeletesThePath() { + let list = FakeList(["/a", "/b"]) + var editor = editor(list, confirmsRemoval: true) + _ = editor.handle(.character("d")) + _ = editor.handle(.right) + XCTAssertEqual(editor.confirmation?.index, 1) + _ = editor.handle(.enter) + XCTAssertEqual(list.removed, ["/a"]) + XCTAssertNil(editor.confirmation) + XCTAssertEqual(editor.paths, ["/b"]) + } + + func testRemovalPromptSwallowsListKeys() { + let list = FakeList(["/a", "/b"]) + var editor = editor(list, confirmsRemoval: true) + _ = editor.handle(.character("d")) + _ = editor.handle(.down) + _ = editor.handle(.character("a")) + XCTAssertEqual(editor.focus, 0) + XCTAssertNil(editor.input) + } + + func testFailedRemovalShowsTheError() { + struct Failing: Error, LocalizedError { var errorDescription: String? { "disk is read-only" } } + var config = FakeList(["/a"]).config() + config.remove = { _ in throw Failing() } + var editor = PathListEditor(config) + _ = editor.handle(.character("d")) + XCTAssertEqual(editor.error, "disk is read-only") + XCTAssertEqual(editor.paths, ["/a"]) + let rows = lines(editor) + XCTAssertTrue(rows[20].hasPrefix("├"), rows[20]) + XCTAssertTrue(rows[21].hasPrefix("│ disk is read-only"), rows[21]) + } + + func testBrowseModeWithoutAnErrorPutsTheHintsRightBelowTheDivider() { + let rows = lines(editor(FakeList(["/a"]))) + XCTAssertTrue(rows[21].hasPrefix("├"), rows[21]) + XCTAssertTrue(rows[22].contains("↑↓ move"), rows[22]) + } + + func testLoadFailureShowsAnEmptyListWithTheError() { + let list = FakeList([]) + list.loadError = Rejected() + let editor = editor(list) + XCTAssertEqual(editor.paths, []) + XCTAssertEqual(editor.loadError, "that path is not allowed") + XCTAssertNil(editor.error) + } + + func testLoadFailureStaysInPlaceOfTheEmptyStateAfterAKey() { + let list = FakeList([]) + list.loadError = Rejected() + var editor = editor(list) + _ = editor.handle(.down) + let buffer = editor.render(width: 80, height: 24) + let rows = buffer.plainLines() + XCTAssertTrue(rows[1].hasPrefix("│ that path is not allowed"), rows[1]) + XCTAssertEqual(buffer[2, 1].style, TextStyle(color: .red)) + XCTAssertFalse(rows.joined().contains("Nothing here yet")) + } + + func testLongLoadFailureWrapsInsideTheList() { + let list = FakeList([]) + list.loadError = PathListError("Configuration file is not a valid PureMac settings file: /Users/someone/.config/puremac/config.json") + let rows = lines(editor(list)) + XCTAssertTrue(rows[1].hasPrefix("│ Configuration file is not a valid PureMac settings file: "), rows[1]) + XCTAssertTrue(rows[2].hasPrefix("│ /Users/someone/.config/puremac/config.json "), rows[2]) + } + + func testLoadFailureGoesAwayOnceALoadSucceeds() { + let list = FakeList([]) + list.loadError = Rejected() + var editor = editor(list) + list.loadError = nil + _ = editor.handle(.character("a")) + _ = editor.handle(.enter) + XCTAssertNil(editor.loadError) + XCTAssertEqual(editor.paths, ["~/"]) + } + + func testReloadFailureAfterAnAddClearsTheStaleList() { + let list = FakeList(["/a"]) + var editor = editor(list) + list.loadError = Rejected() + _ = editor.handle(.character("a")) + _ = editor.handle(.enter) + XCTAssertNil(editor.input) + XCTAssertEqual(editor.paths, []) + XCTAssertEqual(editor.loadError, "that path is not allowed") + } + + func testRowsAreShortenedWithFocusPointerAndMissingNote() { + let missing = "\(Safety.home)/puremac-missing-\(UUID().uuidString)" + let shown = Render.shorten(missing) + let editor = editor(FakeList([missing, existing])) + let buffer = editor.render(width: 80, height: 24) + let rows = buffer.plainLines() + XCTAssertTrue(rows[1].hasPrefix("│ › \(shown) not found "), rows[1]) + XCTAssertTrue(rows[1].hasPrefix("│ › ~/puremac-missing-"), rows[1]) + XCTAssertTrue(rows[1].hasSuffix(" │"), rows[1]) + XCTAssertTrue(rows[2].hasPrefix("│ \(existing)"), rows[2]) + XCTAssertFalse(rows[2].contains("not found")) + XCTAssertEqual(buffer[2, 1].style, TextStyle(color: .cyan, inverse: true)) + XCTAssertEqual(buffer[4, 1].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[3 + shown.count, 1].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[4 + shown.count, 1].style, TextStyle(dim: true, inverse: true)) + XCTAssertEqual(buffer[13 + shown.count, 1].style, TextStyle(dim: true, inverse: true)) + XCTAssertEqual(buffer[14 + shown.count, 1].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[77, 1].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[4, 2].style, .plain) + } + + func testTitleHintsAndEmptyState() { + let rows = lines(editor(FakeList([]))) + XCTAssertTrue(rows[0].contains("Project folders"), rows[0]) + XCTAssertTrue(rows[1].hasPrefix("│ Nothing here yet. Press A to add one."), rows[1]) + XCTAssertTrue(rows[22].contains("↑↓ move A add D remove Esc back"), rows[22]) + } + + func testInputModeShowsItsOwnHints() { + var editor = editor(FakeList([])) + _ = editor.handle(.character("a")) + let row = lines(editor)[22] + XCTAssertTrue(row.contains("Enter add Esc cancel"), row) + XCTAssertFalse(row.contains("remove"), row) + } + + func testScrollbarAppearsOnlyWhenTheListDoesNotFit() { + let many = FakeList((0..<40).map { "/p\($0)" }) + XCTAssertTrue(lines(editor(many), height: 12)[1].hasSuffix("┃")) + XCTAssertFalse(lines(editor(FakeList(["/a"])), height: 12)[1].hasSuffix("┃")) + } + + func testFocusedRowScrollsIntoView() { + var editor = editor(FakeList((0..<40).map { "/p\($0)" })) + for _ in 0..<30 { _ = editor.handle(.down) } + let text = lines(editor, height: 12).joined(separator: "\n") + XCTAssertTrue(text.contains("› /p30"), text) + } + + func testTooSmallTerminalShowsTheTooSmallScreen() { + let text = lines(editor(FakeList(["/a"])), width: 39, height: 24).joined(separator: "\n") + XCTAssertTrue(text.contains("Terminal too small"), text) + XCTAssertTrue(text.contains("Esc back"), text) + XCTAssertFalse(text.contains("/a"), text) + } + + func testTooSmallListAcceptsOnlyEscape() { + let editor = editor(FakeList(["/a"])) + XCTAssertTrue(editor.acceptsKey(.escape, tooSmall: true)) + for key in [TerminalKey.character("d"), .character("a"), .enter, .down, .character("q")] { + XCTAssertFalse(editor.acceptsKey(key, tooSmall: true), "\(key)") + XCTAssertTrue(editor.acceptsKey(key, tooSmall: false), "\(key)") + } + } + + func testTooSmallInputAcceptsOnlyEscape() { + var editor = editor(FakeList([])) + _ = editor.handle(.character("a")) + XCTAssertTrue(editor.acceptsKey(.escape, tooSmall: true)) + XCTAssertFalse(editor.acceptsKey(.character("x"), tooSmall: true)) + XCTAssertFalse(editor.acceptsKey(.enter, tooSmall: true)) + } + + func testTooSmallDialogAcceptsEscapeAndEnterOnCancelOnly() { + var editor = editor(FakeList(["/a"]), confirmsRemoval: true) + _ = editor.handle(.character("d")) + XCTAssertTrue(editor.acceptsKey(.escape, tooSmall: true)) + XCTAssertTrue(editor.acceptsKey(.enter, tooSmall: true)) + XCTAssertFalse(editor.acceptsKey(.right, tooSmall: true)) + _ = editor.handle(.right) + XCTAssertFalse(editor.acceptsKey(.enter, tooSmall: true)) + XCTAssertTrue(editor.acceptsKey(.enter, tooSmall: false)) + } + + func testLeavesOnQLeftAndBackspaceToo() { + for key in [TerminalKey.character("q"), .character("Q"), .left, .backspace, .delete] { + var editor = editor(FakeList(["/a"])) + XCTAssertTrue(editor.handle(key), "\(key)") + } + } + + func testQTypesIntoTheInputInsteadOfLeaving() { + var editor = editor(FakeList([])) + _ = editor.handle(.character("a")) + XCTAssertFalse(editor.handle(.character("q"))) + XCTAssertEqual(editor.input?.text, "~/q") + } + + func testRemovalDialogKeepsTheEndOfALongPathAndTheQuestionMark() { + let long = "/Users/someone/projects/client-work/deeply/nested/folder/final-name" + var editor = editor(FakeList([long]), confirmsRemoval: true) + _ = editor.handle(.character("d")) + for width in [40, 80] { + let text = lines(editor, width: width).joined(separator: "\n") + XCTAssertTrue(text.contains("Stop protecting "), "\(width)\n\(text)") + XCTAssertTrue(text.contains("…"), "\(width)\n\(text)") + XCTAssertTrue(text.contains("name?"), "\(width)\n\(text)") + } + } + + func testRemovalDialogShowsTheWholeDestructiveButtonAt40Columns() { + var editor = editor(FakeList(["/Users/someone/projects/final-name"]), confirmsRemoval: true) + _ = editor.handle(.character("d")) + let text = lines(editor, width: 40, height: 12).joined(separator: "\n") + XCTAssertTrue(text.contains("› Cancel ‹"), text) + XCTAssertTrue(text.contains("[ Remove protection ]"), text) + } +} + +final class ProjectFoldersTests: XCTestCase { + private var root: URL! + private var folder: URL { root.appendingPathComponent("work", isDirectory: true) } + + override func setUpWithError() throws { + root = FileManager.default.temporaryDirectory + .appendingPathComponent("puremac-folders-\(UUID().uuidString)", isDirectory: true) + .resolvingSymlinksInPath() + try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true) + } + + override func tearDown() { + try? FileManager.default.removeItem(at: root) + } + + func testAddSavesTheStandardizedFolderThroughTheConfigFile() throws { + try withConfigHome { _ in + let config = PathListConfig.projectFolders + try config.add(folder.path + "/") + XCTAssertEqual(try ConfigStore(fileURL: AppPaths.configFile).projectRoots, Purger.defaultRoots + [folder.path]) + XCTAssertEqual(try config.load(), Purger.defaultRoots + [folder.path]) + } + } + + func testAddRejectsADuplicate() throws { + try withConfigHome { _ in + let config = PathListConfig.projectFolders + try config.add(folder.path) + XCTAssertThrowsError(try config.add(folder.path + "/")) { error in + XCTAssertEqual(error.localizedDescription, "Already in the list: \(Render.shorten(folder.path))") + } + XCTAssertEqual(try config.load().filter { $0 == folder.path }.count, 1) + } + } + + func testAddRejectsWhatSafetyRejectsWithItsReason() throws { + try withConfigHome { _ in + let config = PathListConfig.projectFolders + for path in ["/", Safety.home, "/Library"] { + let reason = try XCTUnwrap(Safety.isValidScanRoot(path).reason) + XCTAssertThrowsError(try config.add(path), path) { error in + XCTAssertEqual(error.localizedDescription, reason) + } + } + XCTAssertFalse(FileManager.default.fileExists(atPath: AppPaths.configFile.path)) + } + } + + func testAddRejectsMissingFoldersAndFiles() throws { + try withConfigHome { _ in + let file = root.appendingPathComponent("file.txt") + try Data().write(to: file) + for path in [root.appendingPathComponent("nope").path, file.path] { + let reason = try XCTUnwrap(Safety.isValidScanRoot(path).reason) + XCTAssertThrowsError(try PathListConfig.projectFolders.add(path), path) { error in + XCTAssertEqual(error.localizedDescription, reason) + } + } + } + } + + func testAddRejectsEmptyInput() throws { + try withConfigHome { _ in + XCTAssertThrowsError(try PathListConfig.projectFolders.add(" ")) { error in + XCTAssertEqual(error.localizedDescription, "Enter a folder path") + } + } + } + + func testAddRejectsTheHomeFolder() throws { + try withConfigHome { _ in + XCTAssertThrowsError(try PathListConfig.projectFolders.add("~/")) { error in + XCTAssertEqual(error.localizedDescription, Safety.isValidScanRoot("~/").reason) + } + } + } + + func testRemoveSavesTheShorterList() throws { + try withConfigHome { _ in + let config = PathListConfig.projectFolders + try config.add(folder.path) + try config.remove(Purger.defaultRoots[0]) + XCTAssertEqual(try config.load(), Array(Purger.defaultRoots.dropFirst()) + [folder.path]) + } + } + + func testProjectFoldersHaveNoRemovalPrompt() { + XCTAssertNil(PathListConfig.projectFolders.removalPrompt) + } +} + +final class ProtectedPathsListTests: XCTestCase { + func testAddAndRemoveGoThroughTheIgnoreFileAndLoadIsSorted() throws { + try withConfigHome { _ in + let config = PathListConfig.protectedPaths + try config.add("/tmp/puremac-b") + try config.add("/tmp/puremac-a") + XCTAssertEqual(try config.load(), ["/tmp/puremac-a", "/tmp/puremac-b"]) + try config.remove("/tmp/puremac-a") + XCTAssertEqual(try config.load(), ["/tmp/puremac-b"]) + XCTAssertEqual(try IgnoreStore(fileURL: AppPaths.ignoreFile).roots, ["/tmp/puremac-b"]) + } + } + + func testAddKeepsTheStoreValidationError() throws { + try withConfigHome { _ in + XCTAssertThrowsError(try PathListConfig.protectedPaths.add("/")) { error in + XCTAssertEqual(error.localizedDescription, StoreError.invalidIgnorePath.localizedDescription) + } + } + } + + func testAddingAPathThatIsAlreadyListedThrowsAndKeepsOneCopy() throws { + try withConfigHome { _ in + let config = PathListConfig.protectedPaths + try config.add("/tmp/puremac-a") + XCTAssertThrowsError(try config.add("/tmp/puremac-a/")) { error in + XCTAssertEqual(error.localizedDescription, "Already in the list: /tmp/puremac-a") + } + XCTAssertEqual(try config.load(), ["/tmp/puremac-a"]) + } + } + + func testRemovalAsksWithTheShortenedPathAndTheDestructiveLabel() throws { + let prompt = try XCTUnwrap(PathListConfig.protectedPaths.removalPrompt) + XCTAssertEqual(prompt.title("~/secret"), "Stop protecting ~/secret?") + XCTAssertEqual(prompt.button, "Remove protection") + } +} diff --git a/cli/Tests/puremacTests/PreferencesSheetTests.swift b/cli/Tests/puremacTests/PreferencesSheetTests.swift index 9d8bb2b..81d9008 100644 --- a/cli/Tests/puremacTests/PreferencesSheetTests.swift +++ b/cli/Tests/puremacTests/PreferencesSheetTests.swift @@ -40,7 +40,7 @@ final class PlainCommandOutputTests: XCTestCase { } func testIgnoreListHintHasACyanCommandWhenColorsAreOn() { - let styled = Term.styled(Ignore.List.emptyHint(quoted: true), colors: true) + let styled = Term.styled(Ignore.List.emptyHint(), colors: true) XCTAssertTrue(styled.contains("\u{1B}[0m\u{1B}[36mpuremac ignore add "), styled) } @@ -100,20 +100,12 @@ final class PreferencesSheetTests: XCTestCase { XCTAssertEqual(first, "/tmp/a") } - func testProtectedPathsSheetWithoutPathsShowsTheHintWithACyanCommand() { - let sheet = Ignore.List.sheet(roots: []) - guard case .message(let spans) = sheet.sections[0].rows[0] else { return XCTFail("hint row") } - XCTAssertEqual(spans.map(\.text).joined(), "No protected paths. Add one with puremac ignore add .") - XCTAssertEqual(spans.filter { $0.style.color == .cyan }.map(\.text), ["puremac ignore add "]) - XCTAssertEqual(sheet.sections[0].rows.count, 1) - } - - func testHomeMenuOpensSheetsOnlyForStatusPreferencesAndProtectedPaths() throws { + func testHomeMenuOpensSheetsOnlyForStatusAndPreferences() throws { try withConfigHome { _ in for choice in 0...2 { XCTAssertNil(HomeMenu.sheet(forChoice: choice), "\(choice)") } XCTAssertEqual(HomeMenu.sheet(forChoice: 3)?.title, "Mac status") XCTAssertEqual(HomeMenu.sheet(forChoice: 4)?.title, "PureMac CLI settings") - XCTAssertEqual(HomeMenu.sheet(forChoice: 5)?.title, "Protected paths") + XCTAssertNil(HomeMenu.sheet(forChoice: 5)) XCTAssertNil(HomeMenu.sheet(forChoice: 6)) } } @@ -122,13 +114,10 @@ final class PreferencesSheetTests: XCTestCase { try withConfigHome { dir in try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) try Data("[]".utf8).write(to: AppPaths.configFile) - try Data("relative/path\n".utf8).write(to: AppPaths.ignoreFile) - for (choice, title) in [(4, "PureMac CLI settings"), (5, "Protected paths")] { - let sheet = try XCTUnwrap(HomeMenu.sheet(forChoice: choice)) - XCTAssertEqual(sheet.title, title) - guard case .message(let spans) = sheet.sections[0].rows[0] else { return XCTFail("error row") } - XCTAssertEqual(spans.first?.style, TextStyle(color: .red)) - } + let sheet = try XCTUnwrap(HomeMenu.sheet(forChoice: 4)) + XCTAssertEqual(sheet.title, "PureMac CLI settings") + guard case .message(let spans) = sheet.sections[0].rows[0] else { return XCTFail("error row") } + XCTAssertEqual(spans.first?.style, TextStyle(color: .red)) } } } From 2f09430529e38b1e246a135f737021fb52f89b2b Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 15:00:59 +0000 Subject: [PATCH 15/21] feat(cli): make preferences editable inside the UI --- cli/Sources/puremac/Commands/Config.swift | 4 - cli/Sources/puremac/Core/PathListEditor.swift | 12 +- .../puremac/Core/PreferencesScreen.swift | 189 ++++++++++ cli/Sources/puremac/PureMac.swift | 17 +- .../puremacTests/PathListEditorTests.swift | 57 +++ .../puremacTests/PreferencesScreenTests.swift | 336 ++++++++++++++++++ .../puremacTests/PreferencesSheetTests.swift | 21 -- 7 files changed, 601 insertions(+), 35 deletions(-) create mode 100644 cli/Sources/puremac/Core/PreferencesScreen.swift create mode 100644 cli/Tests/puremacTests/PreferencesScreenTests.swift diff --git a/cli/Sources/puremac/Commands/Config.swift b/cli/Sources/puremac/Commands/Config.swift index bcf843a..d1c9b94 100644 --- a/cli/Sources/puremac/Commands/Config.swift +++ b/cli/Sources/puremac/Commands/Config.swift @@ -73,8 +73,4 @@ struct Config: ParsableCommand { footnote: nil ) } - - static func currentSheet() throws -> InfoSheet { - sheet(store: try ConfigStore(fileURL: AppPaths.configFile)) - } } diff --git a/cli/Sources/puremac/Core/PathListEditor.swift b/cli/Sources/puremac/Core/PathListEditor.swift index ef3e8c2..3c3fedb 100644 --- a/cli/Sources/puremac/Core/PathListEditor.swift +++ b/cli/Sources/puremac/Core/PathListEditor.swift @@ -25,6 +25,7 @@ struct PathListConfig { var add: (String) throws -> Void var remove: (String) throws -> Void var removalPrompt: RemovalPrompt? + var inputLabel = "Add folder" } extension PathListConfig { @@ -75,7 +76,8 @@ extension PathListConfig { removalPrompt: RemovalPrompt( title: { "Stop protecting \($0)?" }, button: "Remove protection" - ) + ), + inputLabel: "Add path" ) } } @@ -97,7 +99,6 @@ struct PathListEditor { private static let buttonCount = 2 private static let cancelIndex = 0 private static let removeIndex = buttonCount - 1 - private static let inputLabel = "Add folder " private static let notFound = " not found" init(_ config: PathListConfig) { @@ -147,7 +148,10 @@ struct PathListEditor { case .enter: guard let text = input?.text else { return } let add = config.add - if perform({ try add(text) }) { input = nil } + let before = Set(paths) + guard perform({ try add(text) }) else { return } + input = nil + if let added = paths.firstIndex(where: { !before.contains($0) }) { focus = added } case .escape: input = nil default: input?.handle(key) } @@ -234,7 +238,7 @@ struct PathListEditor { buffer.write(row, x: status.x, y: status.y + offset, maxWidth: status.width) } if let input { - buffer.write(input.fieldSpans(label: Self.inputLabel, width: field.width), x: field.x, y: field.y, maxWidth: field.width) + buffer.write(input.fieldSpans(label: config.inputLabel + " ", width: field.width), x: field.x, y: field.y, maxWidth: field.width) } renderList(in: list, buffer: &buffer) guard let confirmation, let prompt = config.removalPrompt, paths.indices.contains(focus) else { return buffer } diff --git a/cli/Sources/puremac/Core/PreferencesScreen.swift b/cli/Sources/puremac/Core/PreferencesScreen.swift new file mode 100644 index 0000000..eb9eb74 --- /dev/null +++ b/cli/Sources/puremac/Core/PreferencesScreen.swift @@ -0,0 +1,189 @@ +import Foundation +import TerminalUI + +enum PreferencesAction: Equatable { + case back, openProjectFolders, openProtectedPaths +} + +struct PreferencesScreen { + enum Row: Int, CaseIterable { + case age, projectFolders, protectedPaths + } + + private(set) var days = ConfigStore.defaultDays + private(set) var folderCount = Purger.defaultRoots.count + private(set) var pathCount = 0 + private(set) var focus = Row.age + private var loadError: String? + private var configUnreadable = false + private var saveError: String? + private let setupError: String? + + static let presets = [1, 3, 7, 14, 30, 60, 90, 180, 365] + private static let title = "Preferences" + private static let hints = KeyHints([ + KeyHint("↑↓", "move"), KeyHint("←→", "change"), KeyHint("Enter", "open"), KeyHint("Esc", "back"), + ]) + private static let ageLabel = "Preselect artifacts older than" + private static let foldersLabel = "Project folders" + private static let pathsLabel = "Protected paths" + private static var widestValue: Int { Term.displayWidth(ageValue(presets.max() ?? 0)) } + private static let maxErrorRows = 3 + + init(setupError: Error? = nil) { + self.setupError = setupError.map { "Could not create settings files: \($0.localizedDescription)" } + reload() + } + + private static func ageValue(_ days: Int) -> String { + "‹ \(CleanupFlow.counted(days, "day")) ›" + } + + mutating func reload() { + loadError = nil + configUnreadable = false + do { + let store = try ConfigStore(fileURL: AppPaths.configFile) + days = store.olderThanDays + folderCount = store.projectRoots.count + } catch { + days = ConfigStore.defaultDays + folderCount = Purger.defaultRoots.count + loadError = error.localizedDescription + configUnreadable = true + } + do { + pathCount = try IgnoreStore(fileURL: AppPaths.ignoreFile).roots.count + } catch { + pathCount = 0 + loadError = loadError ?? error.localizedDescription + } + } + + mutating func handle(_ key: TerminalKey) -> PreferencesAction? { + saveError = nil + switch key { + case .up: move(-1) + case .down: move(1) + case .left: if focus == .age { changeDays(to: Self.presets.last { $0 < days }) } + case .right: if focus == .age { changeDays(to: Self.presets.first { $0 > days }) } + case .enter: + switch focus { + case .age: break + case .projectFolders: return .openProjectFolders + case .protectedPaths: return .openProtectedPaths + } + case .escape: return .back + case .character(let character): return character.lowercased() == "q" ? .back : nil + default: break + } + return nil + } + + func acceptsKey(_ key: TerminalKey, tooSmall: Bool) -> Bool { + !tooSmall || key == .escape + } + + private mutating func move(_ delta: Int) { + let index = min(Row.allCases.count - 1, max(0, focus.rawValue + delta)) + focus = Row(rawValue: index) ?? focus + } + + private mutating func changeDays(to target: Int?) { + guard let target, !configUnreadable else { return } + do { + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.set(ConfigStore.daysKey, String(target)) + days = target + } catch { + saveError = error.localizedDescription + } + } + + func render(width: Int, height: Int) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: Self.title, exitHint: "Esc back", width: width, height: height) + } + var buffer = Buffer(width: width, height: height) + let window = Window(title: Self.title) + let content = window.render(in: buffer.area, buffer: &buffer) + let lines = listLines(width: content.width) + let footerRows = Self.hints.rows(width: content.width).count + let areas = content.splitRows([.fill, .length(1), .length(1), .length(footerRows)]) + let (main, saved, divider, footer) = (areas[0], areas[1], areas[2], areas[3]) + let parts = main.splitRows([.length(lines.count), .fill]) + let (list, status) = (parts[0], parts[1]) + + for (offset, line) in lines.prefix(list.height).enumerated() { + buffer.write(line, x: list.x, y: list.y + offset, maxWidth: list.width) + } + let errors = errorRows(width: content.width) + for (offset, row) in errors.prefix(status.height).enumerated() { + buffer.write(row, x: status.x, y: status.y + offset, maxWidth: status.width) + } + if let first = errors.first, status.height == 0 { + buffer.write(first, x: saved.x, y: saved.y, maxWidth: saved.width) + } else { + let location = Term.truncate("Saved in " + Render.shorten(AppPaths.configDir.path), to: saved.width, middle: true) + buffer.write(location, x: saved.x, y: saved.y, style: TextStyle(dim: true)) + } + window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) + Self.hints.render(in: footer, buffer: &buffer) + return buffer + } + + private func errorRows(width: Int) -> [[Span]] { + let messages = [ + setupError.map { Span($0, TextStyle(color: .yellow)) }, + saveError.map { Span($0, TextStyle(color: .yellow)) }, + loadError.map { Span($0, TextStyle(color: .red)) }, + ].compactMap { $0 } + return Array(messages.flatMap { Term.wordWrap([$0], width: width) }.prefix(Self.maxErrorRows)) + } + + private func listLines(width: Int) -> [[Span]] { + let rows: [(row: Row, label: String, value: String)] = [ + (.age, Self.ageLabel, Self.ageValue(days)), + (.projectFolders, Self.foldersLabel, "\(CleanupFlow.counted(folderCount, "folder")) ›"), + (.protectedPaths, Self.pathsLabel, "\(CleanupFlow.counted(pathCount, "path")) ›"), + ] + let valueWidth = rows.map { Term.displayWidth($0.value) }.reduce(Self.widestValue, max) + let widestLabel = rows.map { Term.displayWidth($0.label) }.max() ?? 1 + let labelWidth = max(1, min(widestLabel, width - 2 - 2 - valueWidth)) + func line(_ item: (row: Row, label: String, value: String)) -> [Span] { + let text = " " + Term.pad(Term.truncate(item.label, to: labelWidth), to: labelWidth) + " " + item.value + return [ + FocusPointer.span(focused: focus == item.row), + Span(Term.pad(text, to: width - 1), TextStyle(inverse: focus == item.row)), + ] + } + return [ + [Span("Project cleanup", TextStyle(bold: true))], + line(rows[0]), + line(rows[1]), + [], + [Span("Protection", TextStyle(bold: true))], + line(rows[2]), + ] + } + + static func run(setupError: Error?, in session: TerminalSession) { + var screen = PreferencesScreen(setupError: setupError) + while true { + session.draw(screen.render(width: session.width, height: session.height)) + let key = session.readKey() + let tooSmall = !TooSmallScreen.fits(width: session.width, height: session.height) + guard screen.acceptsKey(key, tooSmall: tooSmall) else { continue } + switch screen.handle(key) { + case .back: return + case .openProjectFolders: + PathListEditor.run(.projectFolders, in: session) + screen.reload() + case .openProtectedPaths: + PathListEditor.run(.protectedPaths, in: session) + screen.reload() + case nil: break + } + } + } +} diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index 4e4fc34..2521549 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -23,8 +23,9 @@ struct PureMac: ParsableCommand { print(Self.helpMessage()) return } - try? AppPaths.ensureDefaults() - try HomeMenu.run() + var setupError: Error? + do { try AppPaths.ensureDefaults() } catch { setupError = error } + try HomeMenu.run(setupError: setupError) } } @@ -32,17 +33,18 @@ enum HomeMenu { static let title = "PureMac" static let subtitle = "Your Mac, with room to work. / \(puremacVersion)" static let exploreIndex = 2 + static let preferencesIndex = 4 static let protectedPathsIndex = 5 static let options: [(title: String, detail: String)] = [ ("Clean caches", "Choose tools and individual paths to remove"), ("Project cleanup", "Review dependencies and generated build artifacts"), ("Explore storage", "Browse folders and find what takes up space"), ("System status", "Inspect memory and available disk space"), - ("Preferences", "View cleanup settings and configuration paths"), - ("Protected paths", "View folders excluded from cleanup") + ("Preferences", "Change cleanup age, project folders, and protection"), + ("Protected paths", "Choose paths excluded from cleanup") ] - static func run() throws { + static func run(setupError: Error?) throws { var focus = 0 while let choice = try TerminalMenu.choose(title: title, subtitle: subtitle, options: options, initialSelection: focus) { focus = choice @@ -71,6 +73,10 @@ enum HomeMenu { case exploreIndex: guard try ExploreConfirmation.ask() else { continue } try Analyze.parse([]).run() + case preferencesIndex: + let session = try TerminalSession() + defer { session.close() } + PreferencesScreen.run(setupError: setupError, in: session) case protectedPathsIndex: let session = try TerminalSession() defer { session.close() } @@ -83,7 +89,6 @@ enum HomeMenu { static func sheet(forChoice choice: Int) -> InfoSheet? { switch choice { case 3: return InfoSheet.loading(title: Optimize.statusTitle, Optimize.currentStatusSheet) - case 4: return InfoSheet.loading(title: Config.sheetTitle, Config.currentSheet) default: return nil } } diff --git a/cli/Tests/puremacTests/PathListEditorTests.swift b/cli/Tests/puremacTests/PathListEditorTests.swift index 7ebb7a6..ebf58f4 100644 --- a/cli/Tests/puremacTests/PathListEditorTests.swift +++ b/cli/Tests/puremacTests/PathListEditorTests.swift @@ -12,6 +12,7 @@ private final class FakeList { var removed: [String] = [] var addError: Error? var loadError: Error? + var sorted = false init(_ paths: [String]) { self.paths = paths } @@ -27,6 +28,7 @@ private final class FakeList { if let error = self.addError { throw error } self.added.append(path) self.paths.append(path) + if self.sorted { self.paths.sort() } }, remove: { path in self.removed.append(path) @@ -76,6 +78,61 @@ final class PathListEditorTests: XCTestCase { XCTAssertTrue(editor.handle(.escape)) } + func testProjectFoldersLabelTheInputAddFolderAndProtectedPathsAddPath() throws { + XCTAssertEqual(PathListConfig.projectFolders.inputLabel, "Add folder") + XCTAssertEqual(PathListConfig.protectedPaths.inputLabel, "Add path") + var config = FakeList([]).config() + config.inputLabel = "Add path" + var editor = PathListEditor(config) + _ = editor.handle(.character("a")) + XCTAssertTrue(lines(editor)[21].hasPrefix("│ Add path ~/ "), lines(editor)[21]) + } + + func testFocusMovesToTheNewEntryAfterAnAdd() { + let list = FakeList(["/b", "/d"]) + list.sorted = true + var editor = editor(list) + _ = editor.handle(.character("a")) + for _ in 0..<2 { _ = editor.handle(.backspace) } + type("/c", into: &editor) + _ = editor.handle(.enter) + XCTAssertEqual(editor.paths, ["/b", "/c", "/d"]) + XCTAssertEqual(editor.focus, 1) + } + + func testFocusMovesToTheEndWhenTheNewEntryIsAppended() { + var editor = editor(FakeList(["/a", "/b"])) + _ = editor.handle(.character("a")) + type("x", into: &editor) + _ = editor.handle(.enter) + XCTAssertEqual(editor.focus, 2) + } + + func testFocusStaysWhenAnAddFails() { + let list = FakeList(["/a", "/b"]) + list.addError = Rejected() + var editor = editor(list) + _ = editor.handle(.down) + _ = editor.handle(.character("a")) + _ = editor.handle(.enter) + XCTAssertEqual(editor.focus, 1) + } + + func testProtectedPathsFocusFollowsTheSortedPosition() throws { + try withConfigHome { _ in + var store = try IgnoreStore(fileURL: AppPaths.ignoreFile) + _ = try store.add("/tmp/puremac-a") + _ = try store.add("/tmp/puremac-c") + var editor = PathListEditor(.protectedPaths) + _ = editor.handle(.character("a")) + for _ in 0..<2 { _ = editor.handle(.backspace) } + type("/tmp/puremac-b", into: &editor) + _ = editor.handle(.enter) + XCTAssertEqual(editor.paths, ["/tmp/puremac-a", "/tmp/puremac-b", "/tmp/puremac-c"]) + XCTAssertEqual(editor.focus, 1) + } + } + func testAOpensTheInputPrefilledWithTilde() { var editor = editor(FakeList([])) _ = editor.handle(.character("a")) diff --git a/cli/Tests/puremacTests/PreferencesScreenTests.swift b/cli/Tests/puremacTests/PreferencesScreenTests.swift new file mode 100644 index 0000000..3315c82 --- /dev/null +++ b/cli/Tests/puremacTests/PreferencesScreenTests.swift @@ -0,0 +1,336 @@ +import Foundation +import XCTest +@testable import puremac +import TerminalUI + +private struct Broken: LocalizedError { + var errorDescription: String? { "disk is full" } +} + +final class PreferencesScreenTests: XCTestCase { + private func savedDays() throws -> Int { + try ConfigStore(fileURL: AppPaths.configFile).olderThanDays + } + + private func setDays(_ days: Int) throws { + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.set(ConfigStore.daysKey, String(days)) + } + + private func lines(_ screen: PreferencesScreen, width: Int = 160, height: Int = 24) -> [String] { + screen.render(width: width, height: height).plainLines() + } + + func testStartsWithTheStoredValuesAndTheAgeRowFocused() throws { + try withConfigHome { _ in + let screen = PreferencesScreen() + XCTAssertEqual(screen.days, 7) + XCTAssertEqual(screen.folderCount, Purger.defaultRoots.count) + XCTAssertEqual(screen.pathCount, 0) + XCTAssertEqual(screen.focus, .age) + } + } + + func testRightAndLeftStepThroughThePresetsAndSaveImmediately() throws { + try withConfigHome { _ in + var screen = PreferencesScreen() + XCTAssertNil(screen.handle(.right)) + XCTAssertEqual(screen.days, 14) + XCTAssertEqual(try savedDays(), 14) + _ = screen.handle(.left) + _ = screen.handle(.left) + XCTAssertEqual(screen.days, 3) + XCTAssertEqual(try savedDays(), 3) + } + } + + func testPresetsStopAtBothEnds() throws { + try withConfigHome { _ in + var screen = PreferencesScreen() + for _ in 0..<12 { _ = screen.handle(.left) } + XCTAssertEqual(screen.days, 1) + for _ in 0..<12 { _ = screen.handle(.right) } + XCTAssertEqual(screen.days, 365) + XCTAssertEqual(try savedDays(), 365) + } + } + + func testAValueBetweenPresetsMovesToTheNearestPresetInThatDirection() throws { + try withConfigHome { _ in + try setDays(10) + var right = PreferencesScreen() + _ = right.handle(.right) + XCTAssertEqual(right.days, 14) + var left = PreferencesScreen() + _ = left.handle(.left) + XCTAssertEqual(left.days, 7) + try setDays(1000) + var past = PreferencesScreen() + _ = past.handle(.right) + XCTAssertEqual(past.days, 1000) + _ = past.handle(.left) + XCTAssertEqual(past.days, 365) + } + } + + func testUpAndDownMoveBetweenTheThreeRowsAndStopAtTheEnds() throws { + try withConfigHome { _ in + var screen = PreferencesScreen() + _ = screen.handle(.up) + XCTAssertEqual(screen.focus, .age) + _ = screen.handle(.down) + XCTAssertEqual(screen.focus, .projectFolders) + _ = screen.handle(.down) + _ = screen.handle(.down) + XCTAssertEqual(screen.focus, .protectedPaths) + _ = screen.handle(.up) + XCTAssertEqual(screen.focus, .projectFolders) + } + } + + func testLeftAndRightChangeNothingOnTheListRows() throws { + try withConfigHome { _ in + var screen = PreferencesScreen() + _ = screen.handle(.down) + XCTAssertNil(screen.handle(.right)) + XCTAssertNil(screen.handle(.left)) + XCTAssertEqual(screen.days, 7) + XCTAssertEqual(screen.focus, .projectFolders) + } + } + + func testEnterOpensTheEditorsAndDoesNothingOnTheAgeRow() throws { + try withConfigHome { _ in + var screen = PreferencesScreen() + XCTAssertNil(screen.handle(.enter)) + _ = screen.handle(.down) + XCTAssertEqual(screen.handle(.enter), .openProjectFolders) + _ = screen.handle(.down) + XCTAssertEqual(screen.handle(.enter), .openProtectedPaths) + } + } + + func testEscapeAndQGoBack() throws { + try withConfigHome { _ in + for key in [TerminalKey.escape, .character("q"), .character("Q")] { + var screen = PreferencesScreen() + XCTAssertEqual(screen.handle(key), .back, "\(key)") + } + var screen = PreferencesScreen() + XCTAssertNil(screen.handle(.character("x"))) + } + } + + func testReloadPicksUpChangesMadeInTheEditors() throws { + try withConfigHome { _ in + var screen = PreferencesScreen() + var ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) + _ = try ignore.add("/tmp/puremac-a") + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.setProjectRoots(["/tmp/puremac-x"]) + screen.reload() + XCTAssertEqual(screen.pathCount, 1) + XCTAssertEqual(screen.folderCount, 1) + } + } + + func testRendersTitleSectionsRowsAndHints() throws { + try withConfigHome { dir in + let rows = lines(PreferencesScreen()) + let text = rows.joined(separator: "\n") + XCTAssertTrue(rows[0].contains("Preferences"), rows[0]) + XCTAssertTrue(rows[1].hasPrefix("│ Project cleanup"), rows[1]) + XCTAssertTrue(rows[2].hasPrefix("│ › Preselect artifacts older than ‹ 7 days ›"), rows[2]) + XCTAssertTrue(rows[3].hasPrefix("│ Project folders"), rows[3]) + XCTAssertTrue(rows[3].contains("\(Purger.defaultRoots.count) folders ›"), rows[3]) + XCTAssertTrue(rows[5].hasPrefix("│ Protection"), rows[5]) + XCTAssertTrue(rows[6].hasPrefix("│ Protected paths"), rows[6]) + XCTAssertTrue(rows[6].contains("0 paths ›"), rows[6]) + XCTAssertTrue(text.contains("Saved in \(Render.shorten(dir.path))"), text) + XCTAssertTrue(rows[22].contains("↑↓ move ←→ change Enter open Esc back"), rows[22]) + } + } + + func testSingularCounts() throws { + try withConfigHome { _ in + var ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) + _ = try ignore.add("/tmp/puremac-a") + var store = try ConfigStore(fileURL: AppPaths.configFile) + try store.setProjectRoots(["/tmp/puremac-x"]) + try store.set(ConfigStore.daysKey, "1") + let text = lines(PreferencesScreen()).joined(separator: "\n") + XCTAssertTrue(text.contains("‹ 1 day ›"), text) + XCTAssertTrue(text.contains("1 folder ›"), text) + XCTAssertTrue(text.contains("1 path ›"), text) + } + } + + func testFocusedRowIsInverseWithACyanPointer() throws { + try withConfigHome { _ in + let buffer = PreferencesScreen().render(width: 80, height: 24) + XCTAssertEqual(buffer[2, 2].style, TextStyle(color: .cyan, inverse: true)) + XCTAssertEqual(buffer[4, 2].style, TextStyle(inverse: true)) + XCTAssertEqual(buffer[4, 3].style, .plain) + } + } + + func testSavedInRowIsDimAboveTheDivider() throws { + try withConfigHome { _ in + let buffer = PreferencesScreen().render(width: 160, height: 24) + let rows = buffer.plainLines() + XCTAssertTrue(rows[20].hasPrefix("│ Saved in "), rows[20]) + XCTAssertTrue(rows[21].hasPrefix("├"), rows[21]) + XCTAssertEqual(buffer[2, 20].style, TextStyle(dim: true)) + } + } + + func testSetupErrorShowsAsAYellowRow() throws { + try withConfigHome { _ in + let buffer = PreferencesScreen(setupError: Broken()).render(width: 160, height: 24) + let rows = buffer.plainLines() + let index = try XCTUnwrap(rows.firstIndex { $0.hasPrefix("│ Could not create settings files: disk is full") }) + XCTAssertEqual(buffer[2, index].style, TextStyle(color: .yellow)) + XCTAssertFalse(lines(PreferencesScreen()).joined().contains("Could not create")) + } + } + + func testSetupErrorStaysAfterKeysAndReload() throws { + try withConfigHome { _ in + var screen = PreferencesScreen(setupError: Broken()) + _ = screen.handle(.right) + _ = screen.handle(.down) + screen.reload() + XCTAssertTrue(lines(screen).joined().contains("Could not create settings files: disk is full")) + } + } + + func testUnreadableConfigShowsARedRowInsteadOfFailing() throws { + try withConfigHome { dir in + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try Data("[]".utf8).write(to: AppPaths.configFile) + let screen = PreferencesScreen() + let buffer = screen.render(width: 160, height: 24) + let rows = buffer.plainLines() + let index = try XCTUnwrap(rows.firstIndex { $0.contains("not a valid") }) + XCTAssertEqual(buffer[2, index].style, TextStyle(color: .red)) + XCTAssertEqual(screen.days, ConfigStore.defaultDays) + } + } + + func testFailedSaveShowsAYellowRowUntilTheNextKey() throws { + try withConfigHome { dir in + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try Data("{}".utf8).write(to: AppPaths.configFile) + try FileManager.default.setAttributes([.posixPermissions: 0o500], ofItemAtPath: dir.path) + defer { try? FileManager.default.setAttributes([.posixPermissions: 0o700], ofItemAtPath: dir.path) } + var screen = PreferencesScreen() + _ = screen.handle(.right) + XCTAssertEqual(screen.days, 7) + let buffer = screen.render(width: 160, height: 24) + let rows = buffer.plainLines() + let index = try XCTUnwrap(rows.firstIndex { $0.contains("permission") }) + XCTAssertEqual(buffer[2, index].style, TextStyle(color: .yellow)) + _ = screen.handle(.down) + XCTAssertFalse(lines(screen).joined().contains("permission")) + } + } + + func testSetupErrorNeverHidesTheListRowsInSmallWindows() throws { + try withConfigHome { _ in + for size in [(80, 12), (40, 12)] { + var screen = PreferencesScreen(setupError: Broken()) + _ = screen.handle(.down) + _ = screen.handle(.down) + XCTAssertEqual(screen.focus, .protectedPaths) + let rows = lines(screen, width: size.0, height: size.1) + for label in ["Project cleanup", "Preselect", "Project folders", "Protection", "Protected paths"] { + XCTAssertTrue(rows.contains { $0.contains(label) }, "\(label) at \(size): \(rows)") + } + } + } + } + + func testErrorTakesTheSavedInRowWhenThereIsNoRoomBelowTheList() throws { + try withConfigHome { _ in + let buffer = PreferencesScreen(setupError: Broken()).render(width: 40, height: 12) + let rows = buffer.plainLines() + let index = try XCTUnwrap(rows.firstIndex { $0.contains("Could not create") }, "\(rows)") + XCTAssertEqual(buffer[2, index].style, TextStyle(color: .yellow)) + XCTAssertFalse(rows.joined().contains("Saved in")) + } + } + + func testValuesStayInOneColumnWhenTheWindowIsNarrow() throws { + try withConfigHome { _ in + func start(of value: String, in rows: [String]) -> Int? { + rows.compactMap { row in + row.range(of: value).map { row.distance(from: row.startIndex, to: $0.lowerBound) } + }.first + } + var columns: [[Int?]] = [] + var labels: [String] = [] + for days in [7, 365] { + try setDays(days) + let rows = lines(PreferencesScreen(), width: 40, height: 12) + columns.append([ + start(of: "‹ \(days) days ›", in: rows), + start(of: "\(Purger.defaultRoots.count) folders ›", in: rows), + start(of: "0 paths ›", in: rows), + ]) + labels.append(String(rows[2].prefix { $0 != "‹" })) + } + for set in columns { XCTAssertEqual(Set(set.map { $0 ?? -1 }).count, 1, "\(columns)") } + XCTAssertNotNil(columns[0][0]) + XCTAssertEqual(columns[0], columns[1]) + XCTAssertEqual(labels[0], labels[1]) + } + } + + func testUnreadableConfigShowsTheErrorOnceWhenChangingDays() throws { + try withConfigHome { dir in + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try Data("[]".utf8).write(to: AppPaths.configFile) + var screen = PreferencesScreen() + _ = screen.handle(.right) + let text = lines(screen).joined(separator: "\n") + XCTAssertEqual(text.components(separatedBy: "not a valid").count - 1, 1, text) + } + } + + func testLongConfigPathIsShortenedWithAMiddleEllipsis() throws { + try withConfigHome { _ in + let rows = lines(PreferencesScreen(), width: 50) + XCTAssertTrue(rows[20].contains("…"), rows[20]) + XCTAssertTrue(rows[20].hasSuffix(" │"), rows[20]) + } + } + + func testNarrowWindowKeepsRowsInsideTheFrame() throws { + try withConfigHome { _ in + for row in lines(PreferencesScreen(), width: 40, height: 12) { + XCTAssertEqual(Term.displayWidth(row), 40, row) + } + let rows = lines(PreferencesScreen(), width: 40, height: 12) + XCTAssertTrue(rows[2].contains("‹ 7 days ›"), rows[2]) + } + } + + func testTooSmallTerminalShowsTheTooSmallScreenAndAcceptsOnlyEscape() throws { + try withConfigHome { _ in + let screen = PreferencesScreen() + let text = lines(screen, width: 39, height: 24).joined(separator: "\n") + XCTAssertTrue(text.contains("Terminal too small"), text) + XCTAssertTrue(text.contains("Esc back"), text) + XCTAssertTrue(screen.acceptsKey(.escape, tooSmall: true)) + for key in [TerminalKey.right, .enter, .down, .character("q")] { + XCTAssertFalse(screen.acceptsKey(key, tooSmall: true), "\(key)") + XCTAssertTrue(screen.acceptsKey(key, tooSmall: false), "\(key)") + } + } + } + + func testHomeMenuOpensAnInfoSheetOnlyForStatus() { + for choice in [0, 1, 2, 4, 5, 6] { XCTAssertNil(HomeMenu.sheet(forChoice: choice), "\(choice)") } + XCTAssertEqual(HomeMenu.sheet(forChoice: 3)?.title, "Mac status") + } +} diff --git a/cli/Tests/puremacTests/PreferencesSheetTests.swift b/cli/Tests/puremacTests/PreferencesSheetTests.swift index 81d9008..f883877 100644 --- a/cli/Tests/puremacTests/PreferencesSheetTests.swift +++ b/cli/Tests/puremacTests/PreferencesSheetTests.swift @@ -99,25 +99,4 @@ final class PreferencesSheetTests: XCTestCase { guard case .path(let first) = sheet.sections[0].rows[0] else { return XCTFail("path row") } XCTAssertEqual(first, "/tmp/a") } - - func testHomeMenuOpensSheetsOnlyForStatusAndPreferences() throws { - try withConfigHome { _ in - for choice in 0...2 { XCTAssertNil(HomeMenu.sheet(forChoice: choice), "\(choice)") } - XCTAssertEqual(HomeMenu.sheet(forChoice: 3)?.title, "Mac status") - XCTAssertEqual(HomeMenu.sheet(forChoice: 4)?.title, "PureMac CLI settings") - XCTAssertNil(HomeMenu.sheet(forChoice: 5)) - XCTAssertNil(HomeMenu.sheet(forChoice: 6)) - } - } - - func testHomeMenuShowsAStoreErrorAsARedRowInsteadOfThrowing() throws { - try withConfigHome { dir in - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) - try Data("[]".utf8).write(to: AppPaths.configFile) - let sheet = try XCTUnwrap(HomeMenu.sheet(forChoice: 4)) - XCTAssertEqual(sheet.title, "PureMac CLI settings") - guard case .message(let spans) = sheet.sections[0].rows[0] else { return XCTFail("error row") } - XCTAssertEqual(spans.first?.style, TextStyle(color: .red)) - } - } } From 34bf39a328f82add1602e7b3584b4b38b9e0c6d2 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 15:19:47 +0000 Subject: [PATCH 16/21] feat(cli): show system status as framed panels with facts about this Mac --- cli/Sources/TerminalUI/Buffer.swift | 29 +- cli/Sources/puremac/Commands/Optimize.swift | 32 ++- cli/Sources/puremac/Core/InfoSheet.swift | 91 +------ cli/Sources/puremac/Core/SystemInfo.swift | 68 ++++- .../puremac/Core/SystemStatusScreen.swift | 162 ++++++++++++ cli/Sources/puremac/PureMac.swift | 18 +- cli/Tests/TerminalUITests/BufferTests.swift | 22 ++ cli/Tests/puremacTests/InfoSheetTests.swift | 240 +++-------------- .../puremacTests/OptimizeConfigTests.swift | 33 ++- .../puremacTests/PreferencesScreenTests.swift | 5 - .../SystemStatusScreenTests.swift | 250 ++++++++++++++++++ 11 files changed, 623 insertions(+), 327 deletions(-) create mode 100644 cli/Sources/puremac/Core/SystemStatusScreen.swift create mode 100644 cli/Tests/puremacTests/SystemStatusScreenTests.swift diff --git a/cli/Sources/TerminalUI/Buffer.swift b/cli/Sources/TerminalUI/Buffer.swift index 29e094d..95668a6 100644 --- a/cli/Sources/TerminalUI/Buffer.swift +++ b/cli/Sources/TerminalUI/Buffer.swift @@ -14,7 +14,23 @@ public struct Rect: Equatable { } public func splitRows(_ constraints: [RowConstraint]) -> [Rect] { - var remaining = max(0, height) + var top = y + return Rect.sizes(constraints, total: height).map { rowHeight in + defer { top += rowHeight } + return Rect(x: x, y: top, width: width, height: rowHeight) + } + } + + public func splitColumns(_ constraints: [RowConstraint]) -> [Rect] { + var left = x + return Rect.sizes(constraints, total: width).map { columnWidth in + defer { left += columnWidth } + return Rect(x: left, y: y, width: columnWidth, height: height) + } + } + + private static func sizes(_ constraints: [RowConstraint], total: Int) -> [Int] { + var remaining = max(0, total) let fixed: [Int?] = constraints.map { constraint in guard case .length(let length) = constraint else { return nil } let taken = min(max(0, length), remaining) @@ -23,18 +39,11 @@ public struct Rect: Equatable { } let fills = fixed.filter { $0 == nil }.count var fillIndex = 0 - let heights: [Int] = fixed.map { height in - if let height { return height } + return fixed.map { size in + if let size { return size } defer { fillIndex += 1 } return remaining / fills + (fillIndex < remaining % fills ? 1 : 0) } - - var top = y - return heights.map { rowHeight in - let row = Rect(x: x, y: top, width: width, height: rowHeight) - top += row.height - return row - } } } diff --git a/cli/Sources/puremac/Commands/Optimize.swift b/cli/Sources/puremac/Commands/Optimize.swift index 32a2db4..78c6b88 100644 --- a/cli/Sources/puremac/Commands/Optimize.swift +++ b/cli/Sources/puremac/Commands/Optimize.swift @@ -41,6 +41,7 @@ struct Optimize: ParsableCommand { } static let statusTitle = "Mac status" + static let statusFootnote = "No maintenance ran. Use `puremac clean --dry-run` to review removable files." static func currentStatusSheet() throws -> InfoSheet { let memory = try SystemInfo.memoryStatus() @@ -49,7 +50,7 @@ struct Optimize: ParsableCommand { memory: memory, pressure: SystemInfo.memoryPressure(), volume: volume, - uptime: ProcessInfo.processInfo.systemUptime + machine: SystemInfo.machine() ) } @@ -57,23 +58,23 @@ struct Optimize: ParsableCommand { memory: MemoryStatus, pressure: MemoryPressure?, volume: VolumeStatus, - uptime: TimeInterval + machine: MachineInfo ) -> InfoSheet { InfoSheet( title: statusTitle, subtitle: "Read-only measurements from macOS", sections: [ + thisMacSection(machine), memorySection(memory, pressure: pressure), storageSection(volume), - InfoSection(title: nil, rows: [.message([Span("Uptime", TextStyle(dim: true)), Span(" " + formatUptime(uptime))])]), ], - footnote: "No maintenance ran. Use `puremac clean --dry-run` to review removable files." + footnote: statusFootnote ) } static func memorySheet(_ status: MemoryStatus, pressure: MemoryPressure?) -> InfoSheet { InfoSheet( - title: "Memory", + title: memoryTitle, sections: [memorySection(status, pressure: pressure)], footnote: "No memory was purged. macOS reclaims inactive memory when applications need it." ) @@ -81,12 +82,27 @@ struct Optimize: ParsableCommand { static func storageSheet(_ status: VolumeStatus) -> InfoSheet { InfoSheet( - title: "Storage", + title: storageTitle, sections: [storageSection(status)], footnote: "No storage was changed. APFS managed capacity is an estimate controlled by macOS." ) } + static let memoryTitle = "Memory" + static let storageTitle = "Storage" + + static func thisMacSection(_ machine: MachineInfo) -> InfoSection { + let facts: [(String, String?)] = [ + ("Chip", machine.chip), + ("Cores", machine.cores), + ("Memory", machine.memory.map(ByteCount.human)), + ("macOS", machine.macOS), + ("Model", machine.model), + ("Uptime", formatUptime(machine.uptime)), + ] + return InfoSection(title: "This Mac", rows: facts.compactMap { label, value in value.map { metric(label, $0) } }) + } + static func memorySection(_ status: MemoryStatus, pressure: MemoryPressure?) -> InfoSection { let used = ByteCount.human(status.total - status.free) var rows: [InfoRow] = [ @@ -107,7 +123,7 @@ struct Optimize: ParsableCommand { metric("Compressed", ByteCount.human(status.compressed)), metric("Wired", ByteCount.human(status.wired)), ] - return InfoSection(title: "Memory", rows: rows) + return InfoSection(title: memoryTitle, rows: rows) } static func storageSection(_ status: VolumeStatus) -> InfoSection { @@ -126,7 +142,7 @@ struct Optimize: ParsableCommand { let note = "Managed capacity may include purgeable files and is not guaranteed free space." rows.append(.message([Span(note, TextStyle(dim: true))])) } - return InfoSection(title: "Storage", rows: rows) + return InfoSection(title: storageTitle, rows: rows) } private static func metric(_ label: String, _ value: String) -> InfoRow { diff --git a/cli/Sources/puremac/Core/InfoSheet.swift b/cli/Sources/puremac/Core/InfoSheet.swift index 59d580a..0a59ad7 100644 --- a/cli/Sources/puremac/Core/InfoSheet.swift +++ b/cli/Sources/puremac/Core/InfoSheet.swift @@ -6,21 +6,8 @@ struct InfoSheet { var sections: [InfoSection] var footnote: String? - private static let backHint = KeyHint("Esc", "back") - private static let hints = KeyHints([KeyHint("↑↓", "scroll"), backHint]) private static let gaugeWidth = 20 - private var window: Window { Window(title: title) } - - static func loading(title: String, _ build: () throws -> InfoSheet) -> InfoSheet { - do { - return try build() - } catch { - let message = Span(error.localizedDescription, TextStyle(color: .red)) - return InfoSheet(title: title, subtitle: nil, sections: [InfoSection(title: nil, rows: [.message([message])])], footnote: nil) - } - } - func plainLines(withHeader: Bool = true, colors: Bool = Term.colorEnabled) -> [String] { var lines: [[Span]] = [] if withHeader { @@ -31,90 +18,38 @@ struct InfoSheet { return (lines + bodyLines()).map { Term.styled($0, colors: colors) } } - func render(width: Int, height: Int, offset: Int) -> Buffer { - guard TooSmallScreen.fits(width: width, height: height) else { - return TooSmallScreen.render(title: title, exitHint: "\(Self.backHint.key) \(Self.backHint.action)", width: width, height: height) - } - var buffer = Buffer(width: width, height: height) - window.render(in: buffer.area, buffer: &buffer) - let layout = layout(width: width, height: height) - let list = layout.list - let start = max(0, min(offset, layout.maxOffset)) - for (index, spans) in layout.lines.dropFirst(start).prefix(list.height).enumerated() { - Self.write(spans, in: Rect(x: list.x, y: list.y + index, width: list.width, height: 1), buffer: &buffer) - } - Scrollbar(total: layout.lines.count, visible: list.height, offset: start) - .render(column: width - 1, rows: list.y..<(list.y + list.height), buffer: &buffer) - window.renderDivider(atRow: layout.divider.y, in: buffer.area, buffer: &buffer) - Self.hints.render(in: layout.footer, buffer: &buffer) - return buffer - } - - func maxOffset(width: Int, height: Int) -> Int { - guard TooSmallScreen.fits(width: width, height: height) else { return 0 } - return layout(width: width, height: height).maxOffset - } - - func show(in session: TerminalSession) { - var scroll = InfoSheetScroll() - while true { - session.draw(render(width: session.width, height: session.height, offset: scroll.offset)) - if scroll.handle(session.readKey(), maxOffset: maxOffset(width: session.width, height: session.height)) { return } - } - } - - private struct Layout { - var list: Rect - var divider: Rect - var footer: Rect - var lines: [[Span]] - var maxOffset: Int { max(0, lines.count - list.height) } - } - - private func layout(width: Int, height: Int) -> Layout { - let content = window.contentRect(in: Rect(x: 0, y: 0, width: width, height: height)) - let areas = content.splitRows([.fill, .length(1), .length(Self.hints.rows(width: content.width).count)]) - let list = areas[0] - var lines = bodyLines(wrappingTo: list.width) - if let subtitle { - lines = Self.wrapped([Span(subtitle, TextStyle(dim: true))], indent: "", width: list.width) + [[]] + lines - } - return Layout(list: list, divider: areas[1], footer: areas[2], lines: lines) - } - - private func bodyLines(wrappingTo width: Int? = nil) -> [[Span]] { + private func bodyLines() -> [[Span]] { var lines: [[Span]] = [] for section in sections { if !lines.isEmpty { lines.append([]) } if let title = section.title { lines.append([Span(title, TextStyle(bold: true))]) } - lines += section.rows.flatMap { Self.lines($0, labelWidth: section.labelWidth, wrappingTo: width) } + lines += section.rows.flatMap { Self.lines($0, labelWidth: section.labelWidth, wrappingTo: nil) } } if let footnote { lines.append([]) - let note = [Span(footnote, TextStyle(dim: true))] - lines += width.map { Self.wrapped(note, indent: "", width: $0) } ?? [note] + lines.append([Span(footnote, TextStyle(dim: true))]) } return lines } - private static func lines(_ row: InfoRow, labelWidth: Int, wrappingTo width: Int?) -> [[Span]] { + static func lines(_ row: InfoRow, labelWidth: Int, indent: String = " ", wrappingTo width: Int?) -> [[Span]] { switch row { case .metric(let label, let value, let note): let labelSpan = Span(Term.pad(label, to: labelWidth), TextStyle(dim: true)) let noteSpans = note.map { [Span(" "), $0] } ?? [] - let row = [Span(" "), labelSpan, Span(" ")] + value + noteSpans + let row = [Span(indent), labelSpan, Span(" ")] + value + noteSpans guard let width, Term.displayWidth(row) > width else { return [row] } - return [[Span(" "), Span(label, TextStyle(dim: true))], [Span(" ")] + fitted(value, to: width - 4 - Term.displayWidth(noteSpans)) + noteSpans] + let deeper = indent + " " + return [[Span(indent), Span(label, TextStyle(dim: true))], [Span(deeper)] + fitted(value, to: width - deeper.count - Term.displayWidth(noteSpans)) + noteSpans] case .gauge(let fraction, let color, let text): - let barWidth = width.map { min(gaugeWidth, $0 - 3 - Term.displayWidth(text)) } ?? gaugeWidth + let barWidth = width.map { min(gaugeWidth, $0 - indent.count - 1 - Term.displayWidth(text)) } ?? gaugeWidth let bar = Gauge(fraction: fraction).spans(width: barWidth, filled: color.map { TextStyle(color: $0) } ?? .plain) - return [[Span(" ")] + bar + [Span(bar.isEmpty ? text : " " + text)]] + return [[Span(indent)] + bar + [Span(bar.isEmpty ? text : " " + text)]] case .path(let path): - let shown = width.map { Term.truncate(path, to: max(1, $0 - 2), middle: true) } ?? path - return [[Span(" " + shown)]] + return [[Span(indent + path)]] case .message(let spans): - guard let width else { return [[Span(" ")] + spans] } - return wrapped(spans, indent: " ", width: width) + guard let width else { return [[Span(indent)] + spans] } + return wrapped(spans, indent: indent, width: width) } } @@ -127,7 +62,7 @@ struct InfoSheet { Term.wordWrap(spans, width: max(1, width - indent.count)).map { [Span(indent)] + $0 } } - private static func write(_ spans: [Span], in rect: Rect, buffer: inout Buffer) { + static func write(_ spans: [Span], in rect: Rect, buffer: inout Buffer) { guard Term.displayWidth(spans) > rect.width else { buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width) return diff --git a/cli/Sources/puremac/Core/SystemInfo.swift b/cli/Sources/puremac/Core/SystemInfo.swift index a90f9bd..abbeeb2 100644 --- a/cli/Sources/puremac/Core/SystemInfo.swift +++ b/cli/Sources/puremac/Core/SystemInfo.swift @@ -68,6 +68,45 @@ struct VolumeStatus: Equatable { } } +struct MachineInfo: Equatable { + let chip: String? + let cores: String? + let memory: Int64? + let macOS: String + let model: String? + let uptime: TimeInterval +} + +struct Sysctl { + let string: (String) -> String? + let int: (String) -> Int64? + + static let system = Sysctl(string: readString, int: readInt) + + private static func readString(_ name: String) -> String? { + var size = 0 + guard sysctlbyname(name, nil, &size, nil, 0) == 0, size > 0 else { return nil } + var buffer = [CChar](repeating: 0, count: size) + guard sysctlbyname(name, &buffer, &size, nil, 0) == 0 else { return nil } + return String(cString: buffer) + } + + private static func readInt(_ name: String) -> Int64? { + var size = 0 + guard sysctlbyname(name, nil, &size, nil, 0) == 0 else { return nil } + switch size { + case MemoryLayout.size: + var value: Int32 = 0 + return sysctlbyname(name, &value, &size, nil, 0) == 0 ? Int64(value) : nil + case MemoryLayout.size: + var value: Int64 = 0 + return sysctlbyname(name, &value, &size, nil, 0) == 0 ? value : nil + default: + return nil + } + } +} + enum SystemInfoError: LocalizedError { case memoryUnavailable(kern_return_t) case volumeUnavailable(String) @@ -111,10 +150,7 @@ enum SystemInfo { } static func memoryPressure() -> MemoryPressure? { - var level: Int32 = 0 - var size = MemoryLayout.size - guard sysctlbyname("kern.memorystatus_vm_pressure_level", &level, &size, nil, 0) == 0 else { return nil } - return MemoryPressure(level: Int(level)) + Sysctl.system.int("kern.memorystatus_vm_pressure_level").flatMap { MemoryPressure(level: Int($0)) } } static func volumeStatus(_ path: String) throws -> VolumeStatus { @@ -137,4 +173,28 @@ enum SystemInfo { ) } + static func machine( + sysctl: Sysctl = .system, + version: OperatingSystemVersion = ProcessInfo.processInfo.operatingSystemVersion, + uptime: TimeInterval = ProcessInfo.processInfo.systemUptime + ) -> MachineInfo { + var macOS = "\(version.majorVersion).\(version.minorVersion)" + if version.patchVersion > 0 { macOS += ".\(version.patchVersion)" } + if let build = sysctl.string("kern.osversion") { macOS += " (\(build))" } + return MachineInfo( + chip: sysctl.string("machdep.cpu.brand_string"), + cores: coreSummary(sysctl), + memory: sysctl.int("hw.memsize"), + macOS: macOS, + model: sysctl.string("hw.model"), + uptime: uptime + ) + } + + private static func coreSummary(_ sysctl: Sysctl) -> String? { + if let performance = sysctl.int("hw.perflevel0.physicalcpu"), let efficiency = sysctl.int("hw.perflevel1.physicalcpu") { + return "\(CleanupFlow.counted(Int(performance + efficiency), "core")) (\(performance) performance, \(efficiency) efficiency)" + } + return sysctl.int("hw.ncpu").map { CleanupFlow.counted(Int($0), "core") } + } } diff --git a/cli/Sources/puremac/Core/SystemStatusScreen.swift b/cli/Sources/puremac/Core/SystemStatusScreen.swift new file mode 100644 index 0000000..3671537 --- /dev/null +++ b/cli/Sources/puremac/Core/SystemStatusScreen.swift @@ -0,0 +1,162 @@ +import TerminalUI + +struct SystemStatusScreen { + struct Panel { + var section: InfoSection + var window: Window + + init(section: InfoSection, info: Span? = nil) { + self.section = section + window = Window(title: section.title ?? "", info: info?.text) + if let style = info?.style { window.infoStyle = style } + } + } + + static let title = "System status" + private static let hints = KeyHints([KeyHint("↑↓", "scroll"), KeyHint("Esc", "back")]) + private static let sideBySideWidth = 80 + private static let frame = Window(title: "") + + private static func inset(width: Int) -> Rect { + frame.contentRect(in: Rect(x: 0, y: 0, width: width, height: 3)) + } + + private static var chromeRows: Int { 3 - inset(width: 3).height } + + var thisMac: Panel + var memory: Panel + var storage: Panel + + static func make( + machine: MachineInfo, + memory: Result, + pressure: MemoryPressure?, + volume: Result + ) -> SystemStatusScreen { + SystemStatusScreen( + thisMac: Panel(section: Optimize.thisMacSection(machine)), + memory: panel( + Optimize.memoryTitle, memory, + section: { Optimize.memorySection($0, pressure: pressure) }, + info: { _ in pressure.map { Span($0.label, TextStyle(color: $0.color, bold: true)) } } + ), + storage: panel( + Optimize.storageTitle, volume, + section: Optimize.storageSection, + info: { Span("\(Int($0.freeFraction * 100))% free", TextStyle(color: $0.freeColor, bold: true)) } + ) + ) + } + + static func current() -> SystemStatusScreen { + make( + machine: SystemInfo.machine(), + memory: Result { try SystemInfo.memoryStatus() }, + pressure: SystemInfo.memoryPressure(), + volume: Result { try SystemInfo.volumeStatus("/") } + ) + } + + static func run(in session: TerminalSession) { + let screen = current() + var scroll = InfoSheetScroll() + while true { + session.draw(screen.render(width: session.width, height: session.height, offset: scroll.offset)) + if scroll.handle(session.readKey(), maxOffset: screen.maxOffset(width: session.width, height: session.height)) { return } + } + } + + func render(width: Int, height: Int, offset: Int) -> Buffer { + guard TooSmallScreen.fits(width: width, height: height) else { + return TooSmallScreen.render(title: Self.title, exitHint: "Esc back", width: width, height: height) + } + var buffer = Buffer(width: width, height: height) + let layout = layout(width: width, height: height) + let start = max(0, min(offset, layout.maxOffset)) + for (panel, rect, lines) in layout.panels { + let shifted = Rect(x: rect.x, y: rect.y - start, width: rect.width, height: rect.height) + let content = panel.window.render(in: shifted, buffer: &buffer) + for (index, spans) in lines.enumerated() { + InfoSheet.write(spans, in: Rect(x: content.x, y: content.y + index, width: content.width, height: 1), buffer: &buffer) + } + } + let inset = Self.inset(width: width) + for (index, spans) in layout.footnote.enumerated() { + buffer.write(spans, x: inset.x, y: layout.footnoteTop + index - start, maxWidth: inset.width) + } + buffer.clear(layout.footer) + if layout.scrolls { + Scrollbar(total: layout.total, visible: layout.viewport, offset: start) + .render(column: width - 1, rows: 0.. Int { + guard TooSmallScreen.fits(width: width, height: height) else { return 0 } + return layout(width: width, height: height).maxOffset + } + + private struct Layout { + var panels: [(panel: Panel, rect: Rect, lines: [[Span]])] + var footnote: [[Span]] + var footnoteTop: Int + var viewport: Int + var footer: Rect + var scrolls: Bool + var total: Int { footnoteTop + footnote.count } + var maxOffset: Int { max(0, total - viewport) } + } + + private func layout(width: Int, height: Int) -> Layout { + let full = layout(width: width, height: height, panelWidth: width) + return full.maxOffset > 0 ? layout(width: width, height: height, panelWidth: width - 1) : full + } + + private func layout(width: Int, height: Int, panelWidth: Int) -> Layout { + let footerRows = Self.hints.rows(width: Self.inset(width: width).width).count + let viewport = max(0, height - footerRows) + let sideBySide = width >= Self.sideBySideWidth + let groups = sideBySide ? [[thisMac], [memory, storage]] : [[thisMac], [memory], [storage]] + var panels: [(panel: Panel, rect: Rect, lines: [[Span]])] = [] + var top = 0 + for group in groups { + let columns = Rect(x: 0, y: top, width: panelWidth, height: 1).splitColumns(group.map { _ in .fill }) + let lines = zip(group, columns).map { panel, column in + let width = panel.window.contentRect(in: Rect(x: column.x, y: top, width: column.width, height: Self.chromeRows + 1)).width + return panel.section.rows.flatMap { InfoSheet.lines($0, labelWidth: panel.section.labelWidth, indent: "", wrappingTo: width) } + } + let panelHeight = (lines.map(\.count).max() ?? 0) + Self.chromeRows + for (index, panel) in group.enumerated() { + let column = columns[index] + panels.append((panel, Rect(x: column.x, y: top, width: column.width, height: panelHeight), lines[index])) + } + top += panelHeight + } + let note = [Span(Optimize.statusFootnote, TextStyle(dim: true))] + return Layout( + panels: panels, + footnote: Term.wordWrap(note, width: max(1, Self.inset(width: panelWidth).width)), + footnoteTop: top, + viewport: viewport, + footer: Rect(x: 0, y: viewport, width: width, height: footerRows), + scrolls: panelWidth < width + ) + } + + private static func panel( + _ title: String, + _ result: Result, + section: (Value) -> InfoSection, + info: (Value) -> Span? + ) -> Panel { + switch result { + case .success(let value): + return Panel(section: section(value), info: info(value)) + case .failure(let error): + let message = Span(error.localizedDescription, TextStyle(color: .red)) + return Panel(section: InfoSection(title: title, rows: [.message([message])])) + } + } +} diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index 2521549..4b042c0 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -33,6 +33,7 @@ enum HomeMenu { static let title = "PureMac" static let subtitle = "Your Mac, with room to work. / \(puremacVersion)" static let exploreIndex = 2 + static let statusIndex = 3 static let preferencesIndex = 4 static let protectedPathsIndex = 5 static let options: [(title: String, detail: String)] = [ @@ -48,12 +49,6 @@ enum HomeMenu { var focus = 0 while let choice = try TerminalMenu.choose(title: title, subtitle: subtitle, options: options, initialSelection: focus) { focus = choice - if let sheet = sheet(forChoice: choice) { - let session = try TerminalSession() - defer { session.close() } - sheet.show(in: session) - continue - } switch choice { case 0: guard let category = try TerminalMenu.choose( @@ -73,6 +68,10 @@ enum HomeMenu { case exploreIndex: guard try ExploreConfirmation.ask() else { continue } try Analyze.parse([]).run() + case statusIndex: + let session = try TerminalSession() + defer { session.close() } + SystemStatusScreen.run(in: session) case preferencesIndex: let session = try TerminalSession() defer { session.close() } @@ -85,11 +84,4 @@ enum HomeMenu { } } } - - static func sheet(forChoice choice: Int) -> InfoSheet? { - switch choice { - case 3: return InfoSheet.loading(title: Optimize.statusTitle, Optimize.currentStatusSheet) - default: return nil - } - } } diff --git a/cli/Tests/TerminalUITests/BufferTests.swift b/cli/Tests/TerminalUITests/BufferTests.swift index d965c4d..01b3d47 100644 --- a/cli/Tests/TerminalUITests/BufferTests.swift +++ b/cli/Tests/TerminalUITests/BufferTests.swift @@ -26,6 +26,28 @@ final class BufferTests: XCTestCase { XCTAssertEqual(rows.map(\.y), [0, 3, 5, 5]) } + func testSplitColumnsLengthsAndFills() { + let rect = Rect(x: 3, y: 2, width: 10, height: 4) + let columns = rect.splitColumns([.length(2), .fill, .length(3)]) + XCTAssertEqual(columns, [ + Rect(x: 3, y: 2, width: 2, height: 4), + Rect(x: 5, y: 2, width: 5, height: 4), + Rect(x: 10, y: 2, width: 3, height: 4) + ]) + } + + func testSplitColumnsFillsShareRemainderToFirst() { + let columns = Rect(x: 0, y: 0, width: 7, height: 4).splitColumns([.fill, .fill, .fill]) + XCTAssertEqual(columns.map(\.width), [3, 2, 2]) + XCTAssertEqual(columns.map(\.x), [0, 3, 5]) + } + + func testSplitColumnsOverflowGivesLaterItemsNoWidth() { + let columns = Rect(x: 0, y: 0, width: 5, height: 4).splitColumns([.length(3), .length(4), .length(2), .fill]) + XCTAssertEqual(columns.map(\.width), [3, 2, 0, 0]) + XCTAssertEqual(columns.map(\.x), [0, 3, 5, 5]) + } + func testNewBufferIsBlankAndClamped() { let buffer = Buffer(width: 3, height: 2) XCTAssertEqual(buffer.area, Rect(x: 0, y: 0, width: 3, height: 2)) diff --git a/cli/Tests/puremacTests/InfoSheetTests.swift b/cli/Tests/puremacTests/InfoSheetTests.swift index 7ef1bd9..80c0c0a 100644 --- a/cli/Tests/puremacTests/InfoSheetTests.swift +++ b/cli/Tests/puremacTests/InfoSheetTests.swift @@ -64,116 +64,6 @@ final class InfoSheetTests: XCTestCase { ) } - func testWindowShowsTitleSubtitleRowsAndHints() { - let buffer = sample().render(width: 60, height: 20, offset: 0) - let lines = buffer.plainLines() - XCTAssertEqual(lines.count, 20) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 60 }) - XCTAssertTrue(lines[0].hasPrefix("╭─ Mac status ")) - XCTAssertTrue(lines[1].contains("Read-only measurements")) - XCTAssertEqual(buffer[2, 1].style, dim) - XCTAssertTrue(lines.contains { $0.contains("Memory") }) - XCTAssertTrue(lines.contains { $0.contains("██████████░░░░░░░░░░ 8 GB in use of 16 GB") }) - XCTAssertTrue(lines.contains { $0.contains("Nothing ran.") }) - XCTAssertTrue(lines.contains { $0.hasPrefix("├") && $0.hasSuffix("┤") }) - XCTAssertTrue(lines.contains { $0.contains("↑↓ scroll") && $0.contains("Esc back") }) - XCTAssertFalse(lines.contains { $0.contains("┃") }) - } - - func testWindowScrollsAndShowsAScrollbarWhenRowsDoNotFit() { - let sheet = sample(extraRows: 30) - let top = sheet.render(width: 60, height: 14, offset: 0) - XCTAssertTrue(top.plainLines().contains { $0.contains("┃") }) - XCTAssertTrue(top.plainLines().contains { $0.contains("Read-only measurements") }) - let scrolled = sheet.render(width: 60, height: 14, offset: 5) - XCTAssertFalse(scrolled.plainLines().contains { $0.contains("Read-only measurements") }) - let bottom = sheet.render(width: 60, height: 14, offset: 10_000) - XCTAssertTrue(bottom.plainLines().contains { $0.contains("Nothing ran.") }) - } - - func testWindowTruncatesLongMetricRows() { - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, rows: [.metric(label: "Path", value: [Span(String(repeating: "a", count: 60))], note: nil)])], - footnote: nil - ) - let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() - XCTAssertTrue(lines.contains { $0.contains("…") }) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) - } - - func testWindowWrapsMessageRowsWithSeveralSpansKeepingStyles() { - let cyan = TextStyle(color: .cyan) - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, rows: [ - .message([Span("No protected paths. Add one with ", dim), Span("`puremac ignore add `", cyan), Span(".", dim)]) - ])], - footnote: nil - ) - let buffer = sheet.render(width: 40, height: 12, offset: 0) - let lines = buffer.plainLines() - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) - XCTAssertFalse(lines.contains { $0.contains("…") }) - let text = lines.joined(separator: " ") - for word in ["protected", "puremac", "ignore", "add", "`."] { XCTAssertTrue(text.contains(word), word) } - let intro = lines.firstIndex { $0.contains("Add one with") } - let command = lines.firstIndex { $0.contains("puremac") } - XCTAssertNotNil(intro) - XCTAssertNotEqual(intro, command, "the hint wraps onto a second row") - let row = command ?? 0 - let styled = (0..<40).filter { buffer[$0, row].style == cyan }.map { buffer[$0, row].symbol }.joined() - XCTAssertEqual(styled, "`puremac ignore add `") - XCTAssertEqual(buffer[4, intro ?? 0].style, dim) - XCTAssertTrue(lines[row].hasPrefix("│ `"), lines[row]) - } - - func testWindowGaugeShrinksItsBarSoTheWholeTextFitsAt40Columns() { - let text = "107.4 GB free of 536.9 GB" - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, rows: [.gauge(fraction: 0.8, color: .green, text: text)])], - footnote: nil - ) - let narrow = sheet.render(width: 40, height: 12, offset: 0).plainLines() - let row = narrow.first { $0.contains("█") } - XCTAssertNotNil(row) - XCTAssertTrue(row?.contains(text) == true, row ?? "") - XCTAssertFalse(narrow.contains { $0.contains("…") }) - let wide = sheet.render(width: 80, height: 12, offset: 0).plainLines() - let bar = wide.first { $0.contains("█") }?.filter { "█░".contains($0) }.count - XCTAssertEqual(bar, 20) - } - - func testWindowGaugeWithoutRoomForABarShowsOnlyItsText() { - let text = String(repeating: "y", count: 33) - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, rows: [.gauge(fraction: 0.5, color: .green, text: text)])], - footnote: nil - ) - let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() - let row = lines.first { $0.contains(text) } - XCTAssertNotNil(row) - XCTAssertTrue(row?.hasPrefix("│ " + text) == true, row ?? "") - XCTAssertFalse(lines.contains { $0.contains("█") || $0.contains("░") || $0.contains("…") }) - } - - func testWindowShowsALongPathRowAsOneMiddleTruncatedRow() { - let path = "/Users/x/Projects/some/deep/folder/name-0" - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, rows: [.path(path), .path("/tmp/short")])], - footnote: nil - ) - let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() - let rows = lines.filter { $0.contains("/Users") || $0.contains("name-0") } - XCTAssertEqual(rows.count, 1, "\(rows)") - XCTAssertTrue(rows[0].contains("…") && rows[0].contains("name-0"), rows[0]) - XCTAssertTrue(rows[0].hasPrefix("│ /Users"), rows[0]) - XCTAssertTrue(lines.contains { $0.hasPrefix("│ /tmp/short ") }) - } - func testPlainLinesShowAPathRowWithTwoSpacesAndNoTruncation() { let path = "/Users/x/Projects/some/deep/folder/name-0" let sheet = InfoSheet(title: "T", subtitle: nil, sections: [InfoSection(title: nil, rows: [.path(path)])], footnote: nil) @@ -185,24 +75,6 @@ final class InfoSheetTests: XCTestCase { XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" /tmp/a\u{200B}b"]) } - func testMaxOffsetIsZeroWhenEverythingFitsOrTheScreenIsTooSmall() { - XCTAssertEqual(sample().maxOffset(width: 60, height: 30), 0) - XCTAssertEqual(sample(extraRows: 30).maxOffset(width: 39, height: 11), 0) - } - - func testMaxOffsetIsTheLargestOffsetThatStillMovesTheWindow() { - let sheet = sample(extraRows: 30) - let most = sheet.maxOffset(width: 60, height: 14) - XCTAssertGreaterThan(most, 0) - XCTAssertEqual(sheet.render(width: 60, height: 14, offset: most), sheet.render(width: 60, height: 14, offset: most + 5)) - XCTAssertNotEqual(sheet.render(width: 60, height: 14, offset: most - 1), sheet.render(width: 60, height: 14, offset: most)) - } - - func testMaxOffsetCountsWrappedRows() { - let long = InfoSheet(title: "T", subtitle: nil, sections: [InfoSection(title: nil, rows: [.message([Span(Array(repeating: "word", count: 80).joined(separator: " "))])])], footnote: nil) - XCTAssertGreaterThan(long.maxOffset(width: 40, height: 12), long.maxOffset(width: 100, height: 12)) - } - func testSectionLabelWidthPadsPlainLabels() { let sheet = InfoSheet( title: "T", subtitle: nil, @@ -212,86 +84,60 @@ final class InfoSheetTests: XCTestCase { XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" Name x"]) } - func testWindowMovesAMetricValueAndNoteToASecondRowWhenTheRowIsTooWide() { - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, labelWidth: 26, rows: [ - .metric(label: "purge.older_than_days", value: [Span("7 days")], note: Span("default", dim)), - .metric(label: "Short", value: [Span("x")], note: nil), - ])], - footnote: nil - ) - let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() - let label = lines.firstIndex { $0.contains("purge.older_than_days") } - XCTAssertNotNil(label) - XCTAssertFalse(lines[label ?? 0].contains("…")) - XCTAssertTrue(lines[(label ?? 0) + 1].hasPrefix("│ 7 days default"), lines[(label ?? 0) + 1]) - XCTAssertTrue(lines.contains { $0.hasPrefix("│ Short") && $0.contains(" x") }, "a row that fits stays on one line") - let wide = sheet.render(width: 80, height: 12, offset: 0).plainLines() - XCTAssertTrue(wide.contains { $0.contains("purge.older_than_days") && $0.contains("7 days default") }) + private func plain(_ lines: [[Span]]) -> [String] { lines.map { $0.map(\.text).joined() } } + + func testMetricMovesValueAndNoteToASecondRowWhenTheRowIsTooWide() { + let row = InfoRow.metric(label: "purge.older_than_days", value: [Span("7 days")], note: Span("default", dim)) + let narrow = plain(InfoSheet.lines(row, labelWidth: 26, wrappingTo: 36)) + XCTAssertEqual(narrow, [" purge.older_than_days", " 7 days default"]) + let wide = plain(InfoSheet.lines(row, labelWidth: 26, wrappingTo: 76)) + XCTAssertEqual(wide.count, 1) + XCTAssertTrue(wide[0].contains("7 days default")) + let short = InfoRow.metric(label: "Short", value: [Span("x")], note: nil) + XCTAssertEqual(InfoSheet.lines(short, labelWidth: 26, wrappingTo: 36).count, 1) } - func testWindowMiddleTruncatesALongMetricValueOnItsSecondRow() { + func testMetricMiddleTruncatesALongValueOnItsSecondRow() { let path = "/Users/someone/.config/puremac/deep/config.json" - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, labelWidth: 12, rows: [.metric(label: "Settings", value: [Span(path)], note: nil)])], - footnote: nil - ) - let lines = sheet.render(width: 40, height: 12, offset: 0).plainLines() - let row = lines.first { $0.contains("config.json") } - XCTAssertNotNil(row) - XCTAssertTrue(row?.hasPrefix("│ /Users") == true && row?.contains("…") == true, row ?? "") - XCTAssertTrue(lines.contains { $0.contains("Settings") }) - XCTAssertEqual(sheet.plainLines(withHeader: false, colors: false), [" Settings " + path]) + let rows = plain(InfoSheet.lines(.metric(label: "Settings", value: [Span(path)], note: nil), labelWidth: 12, wrappingTo: 36)) + XCTAssertEqual(rows.count, 2) + XCTAssertTrue(rows[1].hasPrefix(" /Users") && rows[1].contains("…") && rows[1].hasSuffix("config.json"), rows[1]) + XCTAssertLessThanOrEqual(rows[1].count, 36) } - func testLoadingReturnsTheSheetOrARedErrorRow() { - struct Failure: LocalizedError { var errorDescription: String? { "disk unavailable" } } - let ok = InfoSheet(title: "T", subtitle: nil, sections: [], footnote: nil) - XCTAssertEqual(InfoSheet.loading(title: "Fallback") { ok }.title, "T") - let failed = InfoSheet.loading(title: "Mac status") { throw Failure() } - XCTAssertEqual(failed.title, "Mac status") - XCTAssertEqual(failed.sections.count, 1) - guard case .message(let spans) = failed.sections[0].rows[0] else { return XCTFail("message row") } - XCTAssertEqual(spans, [Span("disk unavailable", TextStyle(color: .red))]) + func testGaugeShrinksItsBarSoTheWholeTextFits() { + let text = "107.4 GB free of 536.9 GB" + let row = InfoRow.gauge(fraction: 0.8, color: .green, text: text) + let narrow = plain(InfoSheet.lines(row, labelWidth: 17, wrappingTo: 36))[0] + XCTAssertTrue(narrow.hasSuffix(text), narrow) + XCTAssertLessThanOrEqual(narrow.count, 36) + XCTAssertEqual(plain(InfoSheet.lines(row, labelWidth: 17, wrappingTo: 76))[0].filter { "█░".contains($0) }.count, 20) } - func testWindowWrapsLongMessagesAndFootnoteInsteadOfCutting() { - let note = "Managed capacity may include purgeable files and is not guaranteed free space." - let footnote = "No maintenance ran. Use `puremac clean --dry-run` to review removable files." - let sheet = InfoSheet( - title: "T", subtitle: nil, - sections: [InfoSection(title: nil, rows: [.message([Span(note, dim)])])], - footnote: footnote - ) - for width in [80, 50] { - let lines = sheet.render(width: width, height: 20, offset: 0).plainLines() - XCTAssertFalse(lines.contains { $0.contains("…") }, "\(width)") - XCTAssertTrue(lines.contains { $0.contains("space.") }, "\(width)") - XCTAssertTrue(lines.contains { $0.contains("--dry-run`") }, "\(width)") - XCTAssertTrue(lines.contains { $0.contains("removable files.") }, "\(width)") - } - let wrapped = sheet.render(width: 50, height: 20, offset: 0).plainLines().filter { $0.contains("purgeable") || $0.contains("guaranteed") } - XCTAssertTrue(wrapped.allSatisfy { $0.contains("│ ") }, "continuation keeps the row indent") + func testGaugeWithoutRoomForABarShowsOnlyItsText() { + let text = String(repeating: "y", count: 33) + let row = plain(InfoSheet.lines(.gauge(fraction: 0.5, color: .green, text: text), labelWidth: 17, wrappingTo: 36)) + XCTAssertEqual(row, [" " + text]) } - func testWindowWrapsLongSubtitle() { - let subtitle = "Read-only measurements taken from macOS system counters at the moment you opened this view" - let sheet = InfoSheet(title: "T", subtitle: subtitle, sections: [], footnote: nil) - let buffer = sheet.render(width: 40, height: 12, offset: 0) - let lines = buffer.plainLines() - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) - let text = lines.joined(separator: " ") - for word in subtitle.split(separator: " ") { XCTAssertTrue(text.contains(word), String(word)) } - XCTAssertFalse(text.contains("…")) + func testMessageWrapsKeepingSpanStyles() { + let cyan = TextStyle(color: .cyan) + let spans = [Span("No protected paths. Add one with ", dim), Span("`puremac ignore add `", cyan), Span(".", dim)] + let rows = InfoSheet.lines(.message(spans), labelWidth: 17, wrappingTo: 36) + XCTAssertGreaterThan(rows.count, 1) + XCTAssertTrue(plain(rows).allSatisfy { $0.hasPrefix(" ") && $0.count <= 36 }) + let styled = rows.flatMap { $0 }.filter { $0.style == cyan }.map(\.text).joined(separator: " ") + XCTAssertEqual(styled, "`puremac ignore add `") + XCTAssertFalse(plain(rows).joined().contains("…")) } - func testBelowMinimumUsesTooSmallScreen() { - XCTAssertEqual( - sample().render(width: 39, height: 11, offset: 0), - TooSmallScreen.render(title: "Mac status", exitHint: "Esc back", width: 39, height: 11) - ) + func testWriteCutsAnOverlongRowWithAnEllipsis() { + var buffer = Buffer(width: 10, height: 1) + InfoSheet.write([Span(String(repeating: "a", count: 30))], in: Rect(x: 0, y: 0, width: 10, height: 1), buffer: &buffer) + XCTAssertEqual(buffer.plainLines(), ["aaaaaaaaa…"]) + var fits = Buffer(width: 10, height: 1) + InfoSheet.write([Span("short")], in: Rect(x: 0, y: 0, width: 10, height: 1), buffer: &fits) + XCTAssertEqual(fits.plainLines()[0].trimmingCharacters(in: .whitespaces), "short") } func testScrollMovesByOneAndStaysInRange() { diff --git a/cli/Tests/puremacTests/OptimizeConfigTests.swift b/cli/Tests/puremacTests/OptimizeConfigTests.swift index 763d117..45a4304 100644 --- a/cli/Tests/puremacTests/OptimizeConfigTests.swift +++ b/cli/Tests/puremacTests/OptimizeConfigTests.swift @@ -41,10 +41,10 @@ final class OptimizeConfigTests: XCTestCase { let memory = MemoryStatus(total: 17_179_869_184, free: 4_294_967_296, inactive: 1_073_741_824, active: 2_147_483_648, wired: 3_221_225_472, compressed: 536_870_912) let volume = VolumeStatus(availableNow: 107_374_182_400, availableForImportantUsage: 161_061_273_600, total: 536_870_912_000) - let sheet = Optimize.statusSheet(memory: memory, pressure: .normal, volume: volume, uptime: 176_461) + let sheet = Optimize.statusSheet(memory: memory, pressure: .normal, volume: volume, machine: testMachine) XCTAssertEqual(sheet.plainLines(colors: false), goldenStatus) XCTAssertEqual( - Optimize.statusSheet(memory: memory, pressure: nil, volume: volume, uptime: 176_461).plainLines(colors: false), + Optimize.statusSheet(memory: memory, pressure: nil, volume: volume, machine: testMachine).plainLines(colors: false), goldenStatus.filter { !$0.hasPrefix(" Pressure") } ) } @@ -62,8 +62,9 @@ final class OptimizeConfigTests: XCTestCase { func testStatusViewPrintsTheSheetLinesWithoutEscapeCodes() throws { let output = try captureStdout { try Optimize.parse([]).run() } let lines = output.split(separator: "\n", omittingEmptySubsequences: false).map(String.init) - XCTAssertEqual(lines.prefix(4), ["Mac status", "Read-only measurements from macOS", "", "Memory"]) - XCTAssertEqual(lines.filter { $0 == "Storage" || $0.hasPrefix(" Uptime ") }.count, 2) + XCTAssertEqual(lines.prefix(4), ["Mac status", "Read-only measurements from macOS", "", "This Mac"]) + XCTAssertEqual(lines.filter { $0 == "This Mac" || $0 == "Memory" || $0 == "Storage" }, ["This Mac", "Memory", "Storage"]) + XCTAssertEqual(lines.filter { $0.hasPrefix(" Uptime ") }.count, 1) XCTAssertEqual(lines.last(where: { !$0.isEmpty }), "No maintenance ran. Use `puremac clean --dry-run` to review removable files.") XCTAssertTrue(lines.allSatisfy { !$0.contains("\u{1B}") }) } @@ -271,15 +272,12 @@ final class SystemStatusTests: XCTestCase { XCTAssertEqual(rows.count, 4) } - func testStatusSheetHasTitleSubtitleSectionsUptimeAndFootnote() { + func testStatusSheetHasTitleSubtitleSectionsAndFootnote() { let volume = VolumeStatus(availableNow: 50, availableForImportantUsage: 50, total: 100) - let sheet = Optimize.statusSheet(memory: memory, pressure: .normal, volume: volume, uptime: 3_661) + let sheet = Optimize.statusSheet(memory: memory, pressure: .normal, volume: volume, machine: testMachine) XCTAssertEqual(sheet.title, "Mac status") XCTAssertEqual(sheet.subtitle, "Read-only measurements from macOS") - XCTAssertEqual(sheet.sections.map(\.title), ["Memory", "Storage", nil]) - XCTAssertEqual(sheet.sections[2].rows.count, 1) - guard case .message(let uptime) = sheet.sections[2].rows[0] else { return XCTFail("uptime message") } - XCTAssertEqual(uptime, [Span("Uptime", TextStyle(dim: true)), Span(" 1h 1m")]) + XCTAssertEqual(sheet.sections.map(\.title), ["This Mac", "Memory", "Storage"]) XCTAssertEqual(sheet.footnote, "No maintenance ran. Use `puremac clean --dry-run` to review removable files.") } } @@ -288,6 +286,14 @@ private let goldenStatus: [String] = [ "Mac status", "Read-only measurements from macOS", "", + "This Mac", + " Chip Apple M4 Pro", + " Cores 14 cores (10 performance, 4 efficiency)", + " Memory 25.8 GB", + " macOS 26.0.1 (25A354)", + " Model Mac16,7", + " Uptime 2d 1h 1m", + "", "Memory", " ███████████████░░░░░ 12.9 GB in use of 17.2 GB", " Pressure Normal", @@ -305,8 +311,6 @@ private let goldenStatus: [String] = [ " Managed by macOS 53.7 GB", " Managed capacity may include purgeable files and is not guaranteed free space.", "", - " Uptime 2d 1h 1m", - "", "No maintenance ran. Use `puremac clean --dry-run` to review removable files.", ] @@ -334,3 +338,8 @@ private let goldenPurgeable: [String] = [ "", "No storage was changed. APFS managed capacity is an estimate controlled by macOS.", ] + +private let testMachine = MachineInfo( + chip: "Apple M4 Pro", cores: "14 cores (10 performance, 4 efficiency)", memory: 25_769_803_776, + macOS: "26.0.1 (25A354)", model: "Mac16,7", uptime: 176_461 +) diff --git a/cli/Tests/puremacTests/PreferencesScreenTests.swift b/cli/Tests/puremacTests/PreferencesScreenTests.swift index 3315c82..455ad08 100644 --- a/cli/Tests/puremacTests/PreferencesScreenTests.swift +++ b/cli/Tests/puremacTests/PreferencesScreenTests.swift @@ -328,9 +328,4 @@ final class PreferencesScreenTests: XCTestCase { } } } - - func testHomeMenuOpensAnInfoSheetOnlyForStatus() { - for choice in [0, 1, 2, 4, 5, 6] { XCTAssertNil(HomeMenu.sheet(forChoice: choice), "\(choice)") } - XCTAssertEqual(HomeMenu.sheet(forChoice: 3)?.title, "Mac status") - } } diff --git a/cli/Tests/puremacTests/SystemStatusScreenTests.swift b/cli/Tests/puremacTests/SystemStatusScreenTests.swift new file mode 100644 index 0000000..91509fc --- /dev/null +++ b/cli/Tests/puremacTests/SystemStatusScreenTests.swift @@ -0,0 +1,250 @@ +import Foundation +import XCTest +@testable import puremac +import TerminalUI + +final class MachineInfoTests: XCTestCase { + private let strings = [ + "machdep.cpu.brand_string": "Apple M4 Pro", + "hw.model": "Mac16,7", + "kern.osversion": "25A354", + ] + private let ints: [String: Int64] = [ + "hw.perflevel0.physicalcpu": 10, + "hw.perflevel1.physicalcpu": 4, + "hw.ncpu": 14, + "hw.memsize": 25_769_803_776, + ] + + private func machine( + strings: [String: String]? = nil, + ints: [String: Int64]? = nil, + version: OperatingSystemVersion = OperatingSystemVersion(majorVersion: 26, minorVersion: 0, patchVersion: 1) + ) -> MachineInfo { + let strings = strings ?? self.strings + let ints = ints ?? self.ints + return SystemInfo.machine(sysctl: Sysctl(string: { strings[$0] }, int: { ints[$0] }), version: version, uptime: 3_661) + } + + func testFormatsFactsFromInjectedValues() { + XCTAssertEqual(machine(), MachineInfo( + chip: "Apple M4 Pro", + cores: "14 cores (10 performance, 4 efficiency)", + memory: 25_769_803_776, + macOS: "26.0.1 (25A354)", + model: "Mac16,7", + uptime: 3_661 + )) + } + + func testFallsBackToLogicalCoreCountWithoutPerformanceLevels() { + var ints = self.ints + ints["hw.perflevel1.physicalcpu"] = nil + XCTAssertEqual(machine(ints: ints).cores, "14 cores") + ints["hw.ncpu"] = 1 + XCTAssertEqual(machine(ints: ints).cores, "1 core") + } + + func testMissingValuesAreNilAndZeroPatchIsHidden() { + let info = machine(strings: [:], ints: [:], version: OperatingSystemVersion(majorVersion: 15, minorVersion: 2, patchVersion: 0)) + XCTAssertEqual(info, MachineInfo(chip: nil, cores: nil, memory: nil, macOS: "15.2", model: nil, uptime: 3_661)) + } + + func testSystemReaderFindsRealKeysAndRejectsUnknownOnes() { + XCTAssertNotNil(Sysctl.system.string("hw.model")) + XCTAssertNotNil(Sysctl.system.int("hw.memsize")) + XCTAssertNotNil(Sysctl.system.int("hw.ncpu")) + XCTAssertNil(Sysctl.system.string("puremac.no.such.key")) + XCTAssertNil(Sysctl.system.int("puremac.no.such.key")) + } + + func testThisMacSectionListsRowsInOrderAndOmitsMissingOnes() { + let section = Optimize.thisMacSection(machine()) + XCTAssertEqual(section.title, "This Mac") + XCTAssertEqual(section.rows.map(label), ["Chip", "Cores", "Memory", "macOS", "Model", "Uptime"]) + let sparse = Optimize.thisMacSection(MachineInfo(chip: nil, cores: nil, memory: nil, macOS: "15.2", model: nil, uptime: 60)) + XCTAssertEqual(sparse.rows.map(label), ["macOS", "Uptime"]) + } + + private func label(_ row: InfoRow) -> String? { + guard case .metric(let label, _, _) = row else { return nil } + return label + } +} + +final class SystemStatusScreenTests: XCTestCase { + private let machine = MachineInfo( + chip: "Apple M4 Pro", cores: "14 cores (10 performance, 4 efficiency)", memory: 25_769_803_776, + macOS: "26.0.1 (25A354)", model: "Mac16,7", uptime: 176_461 + ) + private let memory = MemoryStatus( + total: 17_179_869_184, free: 4_294_967_296, inactive: 1_073_741_824, + active: 2_147_483_648, wired: 3_221_225_472, compressed: 536_870_912 + ) + private let volume = VolumeStatus(availableNow: 107_374_182_400, availableForImportantUsage: 161_061_273_600, total: 536_870_912_000) + + private func screen(pressure: MemoryPressure? = .normal) -> SystemStatusScreen { + SystemStatusScreen.make(machine: machine, memory: .success(memory), pressure: pressure, volume: .success(volume)) + } + + private func lines(width: Int, height: Int, offset: Int = 0) -> [String] { + screen().render(width: width, height: height, offset: offset).plainLines() + } + + func testWideTerminalPutsMemoryAndStorageSideBySideUnderThisMac() { + let lines = lines(width: 100, height: 30) + XCTAssertEqual(lines.count, 30) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 100 }) + XCTAssertTrue(lines[0].hasPrefix("╭─ This Mac "), lines[0]) + XCTAssertTrue(lines[0].hasSuffix("╮")) + let panelTops = lines.filter { $0.contains("╭─ Memory ") } + XCTAssertEqual(panelTops.count, 1) + XCTAssertTrue(panelTops[0].contains("╮╭─ Storage "), panelTops[0]) + XCTAssertTrue(panelTops[0].contains(" Normal ─╮"), panelTops[0]) + XCTAssertTrue(panelTops[0].contains(" 20% free ─╮"), panelTops[0]) + } + + func testRowsSitOneColumnInsideTheFrameWithoutExtraIndent() { + let lines = lines(width: 100, height: 30) + XCTAssertTrue(lines[1].hasPrefix("│ Chip "), lines[1]) + let gauge = lines.first { $0.contains("12.9 GB in use") } + XCTAssertTrue(gauge?.hasPrefix("│ █") == true, gauge ?? "") + } + + func testEachSideBySidePanelTakesHalfTheWidth() { + let line = lines(width: 81, height: 30).first { $0.contains("╭─ Memory ") } + XCTAssertEqual(line?.range(of: "╭─ Storage").map { line!.distance(from: line!.startIndex, to: $0.lowerBound) }, 41) + } + + func testEightyColumnsIsTheFirstSideBySideWidth() { + let wide = lines(width: 80, height: 40) + let top = wide.first { $0.contains("╭─ Memory ") } + XCTAssertTrue(top?.contains("╮╭─ Storage ") == true, top ?? "") + XCTAssertEqual(wide.filter { $0.contains("╯╰") }.count, 1) + XCTAssertFalse(lines(width: 79, height: 60).contains { $0.contains("╯╰") }) + } + + func testStorageTitleShowsTheFlooredPercentSoItNeverCrossesTheColorThreshold() { + func info(availableNow: Int64) -> (text: String, color: TerminalColor?) { + let volume = VolumeStatus(availableNow: availableNow, availableForImportantUsage: availableNow, total: 1_000) + let screen = SystemStatusScreen.make(machine: machine, memory: .success(memory), pressure: .normal, volume: .success(volume)) + let buffer = screen.render(width: 100, height: 30, offset: 0) + let lines = buffer.plainLines() + let top = lines.firstIndex { $0.contains("╭─ Storage ") }! + let range = lines[top].range(of: #"\d+% free"#, options: .regularExpression)! + let column = lines[top].distance(from: lines[top].startIndex, to: range.lowerBound) + return (String(lines[top][range]), buffer[column, top].style.color) + } + XCTAssertEqual(info(availableNow: 196).text, "19% free") + XCTAssertEqual(info(availableNow: 196).color, .yellow) + XCTAssertEqual(info(availableNow: 96).text, "9% free") + XCTAssertEqual(info(availableNow: 96).color, .red) + } + + func testNarrowTerminalStacksThePanels() { + let lines = lines(width: 79, height: 50) + let tops = lines.enumerated().filter { $0.element.hasPrefix("╭") } + XCTAssertEqual(tops.count, 3) + XCTAssertTrue(tops[1].element.hasPrefix("╭─ Memory ")) + XCTAssertTrue(tops[2].element.hasPrefix("╭─ Storage ")) + XCTAssertFalse(lines.contains { $0.contains("╮╭") }) + } + + func testPanelsHoldTheFactsAndTheFootnoteAndHintsFollow() { + let lines = lines(width: 100, height: 30) + let text = lines.joined(separator: "\n") + for fact in ["Chip", "Apple M4 Pro", "14 cores (10 performance, 4 efficiency)", "26.0.1 (25A354)", "Mac16,7", "2d 1h 1m", + "12.9 GB in use of 17.2 GB", "Wired", "107.4 GB free of 536.9 GB", "Managed by macOS"] { + XCTAssertTrue(text.contains(fact), fact) + } + let footnote = lines.firstIndex { $0.contains(Optimize.statusFootnote) } + let lastBottom = lines.lastIndex { $0.hasPrefix("╰") } + XCTAssertNotNil(footnote) + XCTAssertLessThan(lastBottom ?? 0, footnote ?? 0) + XCTAssertTrue(lines.last?.hasPrefix(" ↑↓ scroll") == true, lines.last ?? "") + XCTAssertTrue(lines.last?.contains("Esc back") == true) + XCTAssertEqual(lines[footnote ?? 0].prefix(2), " ") + } + + func testScrollbarThumbIsOneContinuousRunAndFramesStayWhole() { + let screen = screen() + for (width, height) in [(80, 12), (60, 14), (40, 12)] { + for offset in 0...screen.maxOffset(width: width, height: height) { + let lines = screen.render(width: width, height: height, offset: offset).plainLines().dropLast() + let rows = lines.enumerated().filter { $0.element.hasSuffix("┃") }.map(\.offset) + XCTAssertFalse(rows.isEmpty, "\(width)x\(height) offset \(offset)") + XCTAssertEqual(rows.count, (rows.last ?? 0) - (rows.first ?? 0) + 1, "\(width)x\(height) offset \(offset)") + XCTAssertFalse(lines.contains { String($0.dropLast()).hasSuffix("┃") }, "\(width)x\(height) offset \(offset)") + } + } + } + + func testStylesLabelsDimAndPressureAndFreeInfoInTheirColors() { + let buffer = screen(pressure: .warning).render(width: 100, height: 30, offset: 0) + let lines = buffer.plainLines() + let chip = lines.firstIndex { $0.contains("Chip") }! + let column = lines[chip].distance(from: lines[chip].startIndex, to: lines[chip].range(of: "Chip")!.lowerBound) + XCTAssertTrue(buffer[column, chip].style.dim) + let top = lines.firstIndex { $0.contains("╭─ Memory ") }! + let warning = lines[top].distance(from: lines[top].startIndex, to: lines[top].range(of: "Warning")!.lowerBound) + XCTAssertEqual(buffer[warning, top].style.color, .yellow) + let free = lines[top].distance(from: lines[top].startIndex, to: lines[top].range(of: "20% free")!.lowerBound) + XCTAssertEqual(buffer[free, top].style.color, .green) + } + + func testMemoryPanelHasNoInfoWithoutPressure() { + let top = screen(pressure: nil).render(width: 100, height: 30, offset: 0).plainLines().first { $0.contains("╭─ Memory ") } + XCTAssertFalse(top?.contains("Normal") == true) + XCTAssertTrue(top?.contains("╭─ Memory ─") == true) + } + + func testErrorsShowInRedInsideTheirPanel() { + struct Failure: LocalizedError { var errorDescription: String? { "no memory data" } } + let broken = SystemStatusScreen.make(machine: machine, memory: .failure(Failure()), pressure: nil, volume: .success(volume)) + let buffer = broken.render(width: 100, height: 30, offset: 0) + let lines = buffer.plainLines() + let row = lines.firstIndex { $0.contains("no memory data") }! + let column = lines[row].distance(from: lines[row].startIndex, to: lines[row].range(of: "no memory")!.lowerBound) + XCTAssertEqual(buffer[column, row].style.color, .red) + XCTAssertTrue(lines.contains { $0.contains("107.4 GB free of 536.9 GB") }) + } + + func testScrollsWholeScreenWhenContentDoesNotFit() { + let screen = screen() + let width = 60, height = 14 + let maxOffset = screen.maxOffset(width: width, height: height) + XCTAssertGreaterThan(maxOffset, 0) + let top = screen.render(width: width, height: height, offset: 0).plainLines() + let bottom = screen.render(width: width, height: height, offset: maxOffset).plainLines() + XCTAssertTrue(top[0].hasPrefix("╭─ This Mac ")) + XCTAssertFalse(bottom[0].hasPrefix("╭─ This Mac ")) + XCTAssertTrue(bottom.contains { $0.contains(Optimize.statusFootnote.prefix(20)) }) + XCTAssertEqual(screen.render(width: width, height: height, offset: maxOffset + 9).plainLines(), bottom) + for lines in [top, bottom] { + XCTAssertTrue(lines.last?.contains("↑↓ scroll") == true) + XCTAssertTrue(lines.dropLast().contains { $0.hasSuffix("┃") }) + } + } + + func testNoScrollbarOrOffsetWhenEverythingFits() { + let screen = screen() + XCTAssertEqual(screen.maxOffset(width: 100, height: 60), 0) + XCTAssertFalse(screen.render(width: 100, height: 60, offset: 0).plainLines().contains { $0.contains("┃") }) + } + + func testBelowMinimumUsesTooSmallScreen() { + XCTAssertEqual( + screen().render(width: 39, height: 20, offset: 0), + TooSmallScreen.render(title: "System status", exitHint: "Esc back", width: 39, height: 20) + ) + XCTAssertEqual( + screen().render(width: 80, height: 11, offset: 0), + TooSmallScreen.render(title: "System status", exitHint: "Esc back", width: 80, height: 11) + ) + XCTAssertEqual(screen().maxOffset(width: 39, height: 20), 0) + } + + func testHomeMenuStatusEntryIsSystemStatus() { + XCTAssertEqual(HomeMenu.options[HomeMenu.statusIndex].title, "System status") + } +} From d5264384b78e33b533d73ee4af998165fa968dce Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 15:23:24 +0000 Subject: [PATCH 17/21] fix(cli): show memory in binary units like About This Mac --- cli/Sources/puremac/Commands/Optimize.swift | 18 +++++------ cli/Sources/puremac/Core/ByteCount.swift | 10 ++++-- .../puremacTests/OptimizeConfigTests.swift | 32 +++++++++---------- .../SystemStatusScreenTests.swift | 4 +-- cli/Tests/puremacTests/puremacTests.swift | 12 +++++++ 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/cli/Sources/puremac/Commands/Optimize.swift b/cli/Sources/puremac/Commands/Optimize.swift index 78c6b88..bb2d676 100644 --- a/cli/Sources/puremac/Commands/Optimize.swift +++ b/cli/Sources/puremac/Commands/Optimize.swift @@ -95,7 +95,7 @@ struct Optimize: ParsableCommand { let facts: [(String, String?)] = [ ("Chip", machine.chip), ("Cores", machine.cores), - ("Memory", machine.memory.map(ByteCount.human)), + ("Memory", machine.memory.map(ByteCount.memory)), ("macOS", machine.macOS), ("Model", machine.model), ("Uptime", formatUptime(machine.uptime)), @@ -104,24 +104,24 @@ struct Optimize: ParsableCommand { } static func memorySection(_ status: MemoryStatus, pressure: MemoryPressure?) -> InfoSection { - let used = ByteCount.human(status.total - status.free) + let used = ByteCount.memory(status.total - status.free) var rows: [InfoRow] = [ .gauge( fraction: status.usedFraction, color: pressure?.color, - text: "\(used) in use of \(ByteCount.human(status.total))" + text: "\(used) in use of \(ByteCount.memory(status.total))" ) ] if let pressure { rows.append(.metric(label: "Pressure", value: [Span(pressure.label, TextStyle(color: pressure.color))], note: nil)) } rows += [ - metric("Installed", ByteCount.human(status.total)), - metric("Free now", ByteCount.human(status.free)), - metric("Active", ByteCount.human(status.active)), - metric("Inactive", ByteCount.human(status.inactive)), - metric("Compressed", ByteCount.human(status.compressed)), - metric("Wired", ByteCount.human(status.wired)), + metric("Installed", ByteCount.memory(status.total)), + metric("Free now", ByteCount.memory(status.free)), + metric("Active", ByteCount.memory(status.active)), + metric("Inactive", ByteCount.memory(status.inactive)), + metric("Compressed", ByteCount.memory(status.compressed)), + metric("Wired", ByteCount.memory(status.wired)), ] return InfoSection(title: memoryTitle, rows: rows) } diff --git a/cli/Sources/puremac/Core/ByteCount.swift b/cli/Sources/puremac/Core/ByteCount.swift index 21e1174..6c52441 100644 --- a/cli/Sources/puremac/Core/ByteCount.swift +++ b/cli/Sources/puremac/Core/ByteCount.swift @@ -1,13 +1,17 @@ import Foundation enum ByteCount { - static func human(_ bytes: Int64) -> String { + static func human(_ bytes: Int64) -> String { format(bytes, base: 1000) } + + static func memory(_ bytes: Int64) -> String { format(bytes, base: 1024) } + + private static func format(_ bytes: Int64, base: Double) -> String { if bytes <= 0 { return "Zero KB" } let units = ["bytes", "KB", "MB", "GB", "TB", "PB"] var value = Double(bytes) var idx = 0 - while value >= 1000 && idx < units.count - 1 { - value /= 1000 + while value >= base && idx < units.count - 1 { + value /= base idx += 1 } if idx == 0 { return "\(Int(value)) bytes" } diff --git a/cli/Tests/puremacTests/OptimizeConfigTests.swift b/cli/Tests/puremacTests/OptimizeConfigTests.swift index 45a4304..52d1a57 100644 --- a/cli/Tests/puremacTests/OptimizeConfigTests.swift +++ b/cli/Tests/puremacTests/OptimizeConfigTests.swift @@ -237,7 +237,7 @@ final class SystemStatusTests: XCTestCase { guard case .gauge(let fraction, let color, let text) = rows[0] else { return XCTFail("gauge first") } XCTAssertEqual(fraction, 0.75, accuracy: 0.0001) XCTAssertEqual(color, .yellow) - XCTAssertEqual(text, "\(ByteCount.human(12_000_000_000)) in use of \(ByteCount.human(16_000_000_000))") + XCTAssertEqual(text, "11.2 GB in use of 14.9 GB") guard case .metric("Pressure", let value, nil) = rows[1] else { return XCTFail("pressure second") } XCTAssertEqual(value, [Span("Warning", TextStyle(color: .yellow))]) XCTAssertEqual(rows.dropFirst(2).compactMap { row -> String? in @@ -289,20 +289,20 @@ private let goldenStatus: [String] = [ "This Mac", " Chip Apple M4 Pro", " Cores 14 cores (10 performance, 4 efficiency)", - " Memory 25.8 GB", + " Memory 24 GB", " macOS 26.0.1 (25A354)", " Model Mac16,7", " Uptime 2d 1h 1m", "", "Memory", - " ███████████████░░░░░ 12.9 GB in use of 17.2 GB", + " ███████████████░░░░░ 12 GB in use of 16 GB", " Pressure Normal", - " Installed 17.2 GB", - " Free now 4.3 GB", - " Active 2.1 GB", - " Inactive 1.1 GB", - " Compressed 536.9 MB", - " Wired 3.2 GB", + " Installed 16 GB", + " Free now 4 GB", + " Active 2 GB", + " Inactive 1 GB", + " Compressed 512 MB", + " Wired 3 GB", "", "Storage", " ████████████████░░░░ 107.4 GB free of 536.9 GB", @@ -316,14 +316,14 @@ private let goldenStatus: [String] = [ private let goldenRam: [String] = [ "Memory", - " ███████████████░░░░░ 12.9 GB in use of 17.2 GB", + " ███████████████░░░░░ 12 GB in use of 16 GB", " Pressure Normal", - " Installed 17.2 GB", - " Free now 4.3 GB", - " Active 2.1 GB", - " Inactive 1.1 GB", - " Compressed 536.9 MB", - " Wired 3.2 GB", + " Installed 16 GB", + " Free now 4 GB", + " Active 2 GB", + " Inactive 1 GB", + " Compressed 512 MB", + " Wired 3 GB", "", "No memory was purged. macOS reclaims inactive memory when applications need it.", ] diff --git a/cli/Tests/puremacTests/SystemStatusScreenTests.swift b/cli/Tests/puremacTests/SystemStatusScreenTests.swift index 91509fc..d794641 100644 --- a/cli/Tests/puremacTests/SystemStatusScreenTests.swift +++ b/cli/Tests/puremacTests/SystemStatusScreenTests.swift @@ -107,7 +107,7 @@ final class SystemStatusScreenTests: XCTestCase { func testRowsSitOneColumnInsideTheFrameWithoutExtraIndent() { let lines = lines(width: 100, height: 30) XCTAssertTrue(lines[1].hasPrefix("│ Chip "), lines[1]) - let gauge = lines.first { $0.contains("12.9 GB in use") } + let gauge = lines.first { $0.contains("12 GB in use") } XCTAssertTrue(gauge?.hasPrefix("│ █") == true, gauge ?? "") } @@ -154,7 +154,7 @@ final class SystemStatusScreenTests: XCTestCase { let lines = lines(width: 100, height: 30) let text = lines.joined(separator: "\n") for fact in ["Chip", "Apple M4 Pro", "14 cores (10 performance, 4 efficiency)", "26.0.1 (25A354)", "Mac16,7", "2d 1h 1m", - "12.9 GB in use of 17.2 GB", "Wired", "107.4 GB free of 536.9 GB", "Managed by macOS"] { + "12 GB in use of 16 GB", "Wired", "107.4 GB free of 536.9 GB", "Managed by macOS"] { XCTAssertTrue(text.contains(fact), fact) } let footnote = lines.firstIndex { $0.contains(Optimize.statusFootnote) } diff --git a/cli/Tests/puremacTests/puremacTests.swift b/cli/Tests/puremacTests/puremacTests.swift index ded7b31..26510f2 100644 --- a/cli/Tests/puremacTests/puremacTests.swift +++ b/cli/Tests/puremacTests/puremacTests.swift @@ -4,6 +4,18 @@ import XCTest final class PureMacTests: XCTestCase { let home = FileManager.default.homeDirectoryForCurrentUser.path + func testMemoryFormattingUsesBinaryUnits() { + XCTAssertEqual(ByteCount.memory(51_539_607_552), "48 GB") + XCTAssertEqual(ByteCount.memory(17_179_869_184), "16 GB") + XCTAssertEqual(ByteCount.memory(536_870_912), "512 MB") + XCTAssertEqual(ByteCount.memory(1_610_612_736), "1.5 GB") + XCTAssertEqual(ByteCount.memory(1_000_000), "976.6 KB") + XCTAssertEqual(ByteCount.memory(1_024), "1 KB") + XCTAssertEqual(ByteCount.memory(1_023), "1023 bytes") + XCTAssertEqual(ByteCount.memory(0), "Zero KB") + XCTAssertEqual(ByteCount.human(51_539_607_552), "51.5 GB") + } + func testByteCountFormatting() { XCTAssertEqual(ByteCount.human(0), "Zero KB") XCTAssertEqual(ByteCount.human(1_000), "1 KB") From 90197ca330ef2aea88152f522c8a1cd475d98038 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 15:49:50 +0000 Subject: [PATCH 18/21] feat(cli): ask before project cleanup and show scan progress --- cli/Sources/puremac/Commands/Clean.swift | 37 +++-- cli/Sources/puremac/Commands/Purge.swift | 12 +- .../puremac/Core/CategoryScanner.swift | 21 ++- cli/Sources/puremac/Core/CleanupFlow.swift | 74 +++++++--- cli/Sources/puremac/Core/Purger.swift | 15 ++- cli/Sources/puremac/Core/ScanStatus.swift | 34 +++++ ...irmation.swift => StartConfirmation.swift} | 42 +++--- cli/Sources/puremac/Core/StatusScreen.swift | 33 +++-- cli/Sources/puremac/PureMac.swift | 36 ++++- cli/Tests/puremacTests/CleanScanTests.swift | 47 +++++++ cli/Tests/puremacTests/CleanupFlowTests.swift | 70 +++++++++- .../ExploreConfirmationTests.swift | 79 ----------- cli/Tests/puremacTests/PurgerScanTests.swift | 119 +++++++++++++++++ .../puremacTests/ScanProgressTests.swift | 77 +++++++++++ cli/Tests/puremacTests/ScanStatusTests.swift | 48 +++++++ .../puremacTests/StartConfirmationTests.swift | 126 ++++++++++++++++++ .../puremacTests/StatusScreenTests.swift | 42 ++++-- 17 files changed, 747 insertions(+), 165 deletions(-) create mode 100644 cli/Sources/puremac/Core/ScanStatus.swift rename cli/Sources/puremac/Core/{ExploreConfirmation.swift => StartConfirmation.swift} (56%) create mode 100644 cli/Tests/puremacTests/CleanScanTests.swift delete mode 100644 cli/Tests/puremacTests/ExploreConfirmationTests.swift create mode 100644 cli/Tests/puremacTests/PurgerScanTests.swift create mode 100644 cli/Tests/puremacTests/ScanStatusTests.swift create mode 100644 cli/Tests/puremacTests/StartConfirmationTests.swift diff --git a/cli/Sources/puremac/Commands/Clean.swift b/cli/Sources/puremac/Commands/Clean.swift index 669ffd8..d96560c 100644 --- a/cli/Sources/puremac/Commands/Clean.swift +++ b/cli/Sources/puremac/Commands/Clean.swift @@ -53,13 +53,8 @@ struct Clean: ParsableCommand { let ids = category.map { [$0] } ?? Clean.validIDs let ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) - let scanning = "Scanning " + ids.map(Clean.title).joined(separator: ", ") + " …" + let scanning = "Scanning " + ids.map(Clean.title).joined(separator: ", ") let progress = ScanProgress.forMode(mode) - let scan = { - ids.map { id in - CategoryScanner.scan(categoryID: id, title: Clean.title(id), ignore: ignore, progress: progress) - }.filter { !$0.groups.isEmpty } - } if mode == .fullscreen { let labels = CleanupFlow.Labels( scanning: scanning, @@ -67,14 +62,16 @@ struct Clean: ParsableCommand { reviewTitle: "Choose items to clean", noun: "item" ) - let result = try CleanupFlow.run(labels: labels, ignore: ignore, scan: scan) + let result = try CleanupFlow.run(labels: labels, ignore: ignore) { status, cancel in + Clean.scan(ids: ids, ignore: ignore, progress: progress, status: status, cancel: cancel) + } try CleanupFlow.finish(result, labels: labels) return } if !json { - Term.err(Term.dim(scanning)) + Term.err(Term.dim(scanning + " …")) } - let cats = scan() + let cats = Clean.scan(ids: ids, ignore: ignore, progress: progress) if json { print(try JSONReport.string(cats)) @@ -133,6 +130,28 @@ struct Clean: ParsableCommand { static let emptyMessage = "No cleanup candidates found in readable locations." + typealias CategoryScanFunction = (String, String, IgnoreStore, ScanProgress, () -> Bool) -> CategoryScan + + static func scan( + ids: [String], + ignore: IgnoreStore, + progress: ScanProgress, + status: WorkProgress? = nil, + cancel: CancelFlag? = nil, + scanCategory: CategoryScanFunction = CategoryScanner.scan + ) -> [CategoryScan] { + var scans: [CategoryScan] = [] + for (index, id) in ids.enumerated() { + if cancel?.isCancelled == true { break } + let title = Clean.title(id) + status?.update { $0.beginCategory(title: title, position: index + 1, count: ids.count) } + let scan = scanCategory(id, title, ignore, progress) { cancel?.isCancelled == true } + status?.update { $0.addFound(in: scan) } + scans.append(scan) + } + return scans.filter { !$0.groups.isEmpty } + } + static func title(_ id: String) -> String { Catalog.categoryTitles.first { $0.id == id }?.title ?? id.capitalized } diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 3c37464..6c5f81e 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -62,7 +62,7 @@ struct Purge: ParsableCommand { return } - let scanning = "Scanning " + roots.map { Render.shorten($0) }.joined(separator: ", ") + " …" + let scanning = "Scanning " + roots.map { Render.shorten($0) }.joined(separator: ", ") if mode == .fullscreen { let labels = CleanupFlow.Labels( scanning: scanning, @@ -70,14 +70,18 @@ struct Purge: ParsableCommand { reviewTitle: "Choose project artifacts", noun: "artifact" ) - let result = try CleanupFlow.run(labels: labels, ignore: ignore) { - let cat = Purger.scan(roots: roots, olderThanDays: days, ignore: ignore) + let result = try CleanupFlow.run(labels: labels, ignore: ignore) { status, cancel in + let cat = Purger.scan( + roots: roots, olderThanDays: days, ignore: ignore, + progress: { event in status.update { $0.apply(event) } }, + isCancelled: { cancel.isCancelled } + ) return cat.groups.isEmpty ? [] : [cat] } try CleanupFlow.finish(result, labels: labels) return } - if !json { Term.err(Term.dim(scanning)) } + if !json { Term.err(Term.dim(scanning + " …")) } let cat = Purger.scan(roots: roots, olderThanDays: days, ignore: ignore) if json { print(try JSONReport.string([cat])); return } diff --git a/cli/Sources/puremac/Core/CategoryScanner.swift b/cli/Sources/puremac/Core/CategoryScanner.swift index 6cd0c9d..184f4d6 100644 --- a/cli/Sources/puremac/Core/CategoryScanner.swift +++ b/cli/Sources/puremac/Core/CategoryScanner.swift @@ -20,16 +20,18 @@ enum CategoryScanner { categoryID id: String, title: String, ignore: IgnoreStore, - progress: ScanProgress = .stderr + progress: ScanProgress = .stderr, + isCancelled: () -> Bool = { false } ) -> CategoryScan { progress.write(" scanning \(title)…\r") - let groups = id == "trash" ? scanTrash(ignore: ignore) : scanCatalog(id: id, ignore: ignore) + let groups = id == "trash" + ? scanTrash(roots: trashRoots(), ignore: ignore, isCancelled: isCancelled) + : scanCatalog(targets: Catalog.targets(for: id), ignore: ignore, isCancelled: isCancelled) progress.write(" \r") return CategoryScan(id: id, title: title, groups: groups) } - private static func scanCatalog(id: String, ignore: IgnoreStore) -> [ToolGroup] { - let targets = Catalog.targets(for: id) + static func scanCatalog(targets: [Target], ignore: IgnoreStore, isCancelled: () -> Bool) -> [ToolGroup] { var candidates: [(target: Int, path: String)] = [] for (ti, target) in targets.enumerated() { let paths = target.contents @@ -44,6 +46,7 @@ enum CategoryScanner { } } candidates = uniqueCandidates(candidates) + if isCancelled() { return [] } let measurements = concurrentMeasurements(candidates.map { $0.path }) var itemsByTarget = [Int: [ScanItem]](minimumCapacity: targets.count) @@ -116,16 +119,20 @@ enum CategoryScanner { return accepted.map { ($0.target, $0.path) } } - private static func scanTrash(ignore: IgnoreStore) -> [ToolGroup] { - let fm = FileManager.default + private static func trashRoots() -> [String] { var roots = ["\(Safety.home)/.Trash"] let uid = getuid() - if let vols = try? fm.contentsOfDirectory(atPath: "/Volumes") { + if let vols = try? FileManager.default.contentsOfDirectory(atPath: "/Volumes") { for vol in vols { roots.append("/Volumes/\(vol)/.Trashes/\(uid)") } } + return roots + } + static func scanTrash(roots: [String], ignore: IgnoreStore, isCancelled: () -> Bool) -> [ToolGroup] { + let fm = FileManager.default var groups: [ToolGroup] = [] for root in roots where !Safety.hasSymlinkComponent(root) && !Safety.isCloudOrDataless(root) { + if isCancelled() { break } guard let children = try? fm.contentsOfDirectory(atPath: root), !children.isEmpty else { continue } let paths = children.map { "\(root)/\($0)" }.filter { passesPreFilter($0, ignore: ignore) } let unique = uniqueCandidates(paths.map { (target: 0, path: $0) }) diff --git a/cli/Sources/puremac/Core/CleanupFlow.swift b/cli/Sources/puremac/Core/CleanupFlow.swift index 6529aed..9858d95 100644 --- a/cli/Sources/puremac/Core/CleanupFlow.swift +++ b/cli/Sources/puremac/Core/CleanupFlow.swift @@ -27,21 +27,37 @@ enum CleanupFlow { let empty: String let reviewTitle: String let noun: String + + var initialStatus: ScanStatus { ScanStatus(headline: scanning) } } + typealias Scan = (WorkProgress, CancelFlag) -> [CategoryScan] + static func run( labels: Labels, ignore: IgnoreStore, - scan: () -> [CategoryScan] + scan: @escaping Scan ) throws -> CleanupFlowResult { let session = try TerminalSession() defer { session.close() } - session.draw(scanningScreen(labels: labels, width: session.width, height: session.height)) - let categories = scan() + var scanCancelled = false + let categories = session.runWithSpinner( + progress: labels.initialStatus, + render: { tick, status in + scanningScreen(status: status, tick: tick, width: session.width, height: session.height) + }, + onKey: { key, cancel in + if cancelsScan(key) { + scanCancelled = true + cancel.cancel() + } + }, + work: scan + ) + if scanCancelled { return .cancelled } guard !categories.isEmpty else { - session.draw(emptyScreen(labels: labels, width: session.width, height: session.height)) - while !closesInfoDialog(session.readKey()) {} + showInfo(on: session) { emptyScreen(labels: labels, width: session.width, height: session.height) } return .nothingFound } @@ -64,8 +80,9 @@ enum CleanupFlow { } } ) - session.draw(resultScreen(outcome: outcome, review: review, labels: labels, width: session.width, height: session.height)) - while !closesInfoDialog(session.readKey()) {} + showInfo(on: session) { + resultScreen(outcome: outcome, review: review, labels: labels, width: session.width, height: session.height) + } return .finished(outcome) } @@ -82,34 +99,53 @@ enum CleanupFlow { } static func closesInfoDialog(_ key: TerminalKey) -> Bool { + key == .enter || isEscapeOrQ(key) + } + + static func showInfo(on session: TerminalSession, _ screen: () -> Buffer) { + repeat { + session.draw(screen()) + } while !closesInfoDialog(session.readKey()) + } + + static func cancelsScan(_ key: TerminalKey) -> Bool { + isEscapeOrQ(key) + } + + private static func isEscapeOrQ(_ key: TerminalKey) -> Bool { switch key { - case .enter, .escape: return true + case .escape: return true case .character(let character): return character.lowercased() == "q" default: return false } } - static func scanningScreen(labels: Labels, width: Int, height: Int) -> Buffer { + static func scanningScreen(status: ScanStatus, tick: Int, width: Int, height: Int) -> Buffer { StatusScreen.render( title: "PureMac", - message: labels.scanning, - detail: nil, - hint: StatusScreen.cancelHint, + rows: [ + StatusRow(Spinner.frame(tick: tick) + " " + status.headline, truncatesInMiddle: true), + StatusRow(status.folder.map(Render.shorten) ?? "", style: TextStyle(dim: true), truncatesInMiddle: true), + StatusRow("Found \(counted(status.foundCount, "item")) · \(ByteCount.human(status.foundBytes))") + ], + hint: StatusScreen.scanHint, width: width, height: height ) } static func emptyScreen(labels: Labels, width: Int, height: Int) -> Buffer { - let dialog = Dialog( + infoScreen( title: "Nothing to clean", - message: [Span(labels.empty)], - buttons: [DialogButton("OK")], - focusedButton: 0 + message: labels.empty, + on: scanningScreen(status: labels.initialStatus, tick: 0, width: width, height: height) ) - return StatusScreen.overlay( - dialog, - on: scanningScreen(labels: labels, width: width, height: height), + } + + static func infoScreen(title: String, message: String, on background: Buffer) -> Buffer { + StatusScreen.overlay( + Dialog(title: title, message: [Span(message)], buttons: [DialogButton("OK")], focusedButton: 0), + on: background, tooSmallExitHint: closeHint ) } diff --git a/cli/Sources/puremac/Core/Purger.swift b/cli/Sources/puremac/Core/Purger.swift index fac3a8f..5f4ebb2 100644 --- a/cli/Sources/puremac/Core/Purger.swift +++ b/cli/Sources/puremac/Core/Purger.swift @@ -18,19 +18,27 @@ enum Purger { artifactNames.contains(name) || artifactPrefixes.contains { name.hasPrefix($0) } } - static func scan(roots: [String], olderThanDays: Int, ignore: IgnoreStore) -> CategoryScan { + static func scan( + roots: [String], + olderThanDays: Int, + ignore: IgnoreStore, + progress: ((PurgeScanEvent) -> Void)? = nil, + isCancelled: () -> Bool = { false } + ) -> CategoryScan { let fm = FileManager.default let cutoff = Date().addingTimeInterval(-Double(olderThanDays) * 86_400) var byProject: [String: [ScanItem]] = [:] var order: [String] = [] - for rootURL in scanRoots(roots) { + walk: for rootURL in scanRoots(roots) { + progress?(.root(rootURL.path)) guard let en = fm.enumerator(at: rootURL, includingPropertiesForKeys: [.isDirectoryKey, .isSymbolicLinkKey], options: [.skipsPackageDescendants], errorHandler: { _, _ in true }) else { continue } for case let url as URL in en { + if isCancelled() { break walk } let name = url.lastPathComponent let vals = try? url.resourceValues(forKeys: [.isDirectoryKey, .isSymbolicLinkKey]) if vals?.isSymbolicLink == true { en.skipDescendants(); continue } @@ -41,6 +49,8 @@ enum Purger { continue } + progress?(.walking(url.path)) + if isArtifact(name) { en.skipDescendants() if Safety.ignoredPathProtectsCandidate(url.path, ignore: ignore) { continue } @@ -51,6 +61,7 @@ enum Purger { let old = (mod ?? .distantFuture) < cutoff let project = projectLabel(url, level: en.level, root: rootURL) let item = ScanItem(path: url.path, sizeBytes: measurement.bytes, modified: mod, selected: old) + progress?(.found(bytes: measurement.bytes)) byProject[project, default: []].append(item) if !order.contains(project) { order.append(project) } } diff --git a/cli/Sources/puremac/Core/ScanStatus.swift b/cli/Sources/puremac/Core/ScanStatus.swift new file mode 100644 index 0000000..68771a4 --- /dev/null +++ b/cli/Sources/puremac/Core/ScanStatus.swift @@ -0,0 +1,34 @@ +enum PurgeScanEvent: Equatable { + case root(String) + case walking(String) + case found(bytes: Int64) +} + +struct ScanStatus { + var headline: String + var folder: String? + var foundCount = 0 + var foundBytes: Int64 = 0 + + mutating func apply(_ event: PurgeScanEvent) { + switch event { + case .root(let path): + headline = "Scanning " + Render.shorten(path) + folder = nil + case .walking(let path): + folder = path + case .found(let bytes): + foundCount += 1 + foundBytes += bytes + } + } + + mutating func beginCategory(title: String, position: Int, count: Int) { + headline = "Scanning \(title), \(position) of \(count)" + } + + mutating func addFound(in category: CategoryScan) { + foundCount += category.groups.reduce(0) { $0 + $1.items.count } + foundBytes += category.allBytes + } +} diff --git a/cli/Sources/puremac/Core/ExploreConfirmation.swift b/cli/Sources/puremac/Core/StartConfirmation.swift similarity index 56% rename from cli/Sources/puremac/Core/ExploreConfirmation.swift rename to cli/Sources/puremac/Core/StartConfirmation.swift index 1bf681e..bfa3b13 100644 --- a/cli/Sources/puremac/Core/ExploreConfirmation.swift +++ b/cli/Sources/puremac/Core/StartConfirmation.swift @@ -1,16 +1,34 @@ import TerminalUI -enum ExploreChoice: Equatable { +enum StartChoice: Equatable { case start, back } -struct ExploreConfirmation { +struct StartConfirmation { + let title: String + let message: String + let menuSelection: Int + + static let explore = StartConfirmation( + title: "Explore your home folder?", + message: "Measuring every folder can take a few minutes.", + menuSelection: HomeMenu.exploreIndex + ) + + static func projectCleanup(folderCount: Int) -> StartConfirmation { + StartConfirmation( + title: "Scan your project folders?", + message: "Searching \(CleanupFlow.counted(folderCount, "folder")) for build artifacts can take a few minutes.", + menuSelection: HomeMenu.projectCleanupIndex + ) + } + private static let buttons = [DialogButton("Cancel"), DialogButton("Start")] static let startIndex = buttons.count - 1 private(set) var focus = ButtonFocus(count: buttons.count, index: startIndex) - mutating func handle(_ key: TerminalKey) -> ExploreChoice? { + mutating func handle(_ key: TerminalKey) -> StartChoice? { if focus.navigate(key) { return nil } switch key { case .enter: @@ -29,21 +47,13 @@ struct ExploreConfirmation { } func render(width: Int, height: Int) -> Buffer { - let menu = TerminalMenu.render( - title: HomeMenu.title, - subtitle: HomeMenu.subtitle, - options: HomeMenu.options, - selection: HomeMenu.exploreIndex, - width: width, - height: height - ) - return StatusScreen.overlay(dialog, on: menu, tooSmallExitHint: "Esc back") + StatusScreen.overlay(dialog, on: HomeMenu.screen(selection: menuSelection, width: width, height: height), tooSmallExitHint: "Esc back") } - static func ask() throws -> Bool { + func ask() throws -> Bool { let session = try TerminalSession() defer { session.close() } - var model = ExploreConfirmation() + var model = self while true { session.draw(model.render(width: session.width, height: session.height)) if let choice = model.handle(session.readKey()) { return choice == .start } @@ -52,8 +62,8 @@ struct ExploreConfirmation { private var dialog: Dialog { Dialog( - title: "Explore your home folder?", - message: [Span("Measuring every folder can take a few minutes.")], + title: title, + message: [Span(message)], buttons: Self.buttons, focusedButton: focus.index, hints: StatusScreen.choiceHints diff --git a/cli/Sources/puremac/Core/StatusScreen.swift b/cli/Sources/puremac/Core/StatusScreen.swift index af341d4..3d820aa 100644 --- a/cli/Sources/puremac/Core/StatusScreen.swift +++ b/cli/Sources/puremac/Core/StatusScreen.swift @@ -1,19 +1,24 @@ import TerminalUI +struct StatusRow { + let text: String + let style: TextStyle + let truncatesInMiddle: Bool + + init(_ text: String, style: TextStyle = .plain, truncatesInMiddle: Bool = false) { + self.text = text + self.style = style + self.truncatesInMiddle = truncatesInMiddle + } +} + enum StatusScreen { static let warningTitle = TextStyle(color: .yellow, bold: true) - static let cancelHint = KeyHint("Ctrl+C", "cancel") + static let scanHint = KeyHint("Esc/q", "cancel") static let warningBorder = TextStyle(color: .yellow) static let choiceHints = KeyHints([KeyHint("Enter", "select"), KeyHint("Esc", "back")]) - static func render( - title: String, - message: String, - detail: String?, - hint: KeyHint, - width: Int, - height: Int - ) -> Buffer { + static func render(title: String, rows: [StatusRow], hint: KeyHint, width: Int, height: Int) -> Buffer { let hints = KeyHints([hint]) guard TooSmallScreen.fits(width: width, height: height) else { return TooSmallScreen.render(title: title, exitHint: "\(hint.key) \(hint.action)", width: width, height: height) @@ -21,12 +26,14 @@ enum StatusScreen { var buffer = Buffer(width: width, height: height) let window = Window(title: title) let content = window.render(in: buffer.area, buffer: &buffer) - let areas = content.splitRows([.length(2), .fill, .length(1), .length(hints.rows(width: content.width).count)]) + let areas = content.splitRows([.length(rows.count), .fill, .length(1), .length(hints.rows(width: content.width).count)]) let (header, divider, footer) = (areas[0], areas[2], areas[3]) - buffer.write(Term.truncate(message, to: header.width), x: header.x, y: header.y, style: TextStyle(dim: true)) - if let detail { - buffer.write(Term.truncate(detail, to: header.width, middle: true), x: header.x, y: header.y + 1) + for (offset, row) in rows.enumerated() { + buffer.write( + Term.truncate(row.text, to: header.width, middle: row.truncatesInMiddle), + x: header.x, y: header.y + offset, style: row.style + ) } window.renderDivider(atRow: divider.y, in: buffer.area, buffer: &buffer) hints.render(in: footer, buffer: &buffer) diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index 4b042c0..4b8d711 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -32,6 +32,7 @@ struct PureMac: ParsableCommand { enum HomeMenu { static let title = "PureMac" static let subtitle = "Your Mac, with room to work. / \(puremacVersion)" + static let projectCleanupIndex = 1 static let exploreIndex = 2 static let statusIndex = 3 static let preferencesIndex = 4 @@ -45,6 +46,30 @@ enum HomeMenu { ("Protected paths", "Choose paths excluded from cleanup") ] + static func screen(selection: Int, width: Int, height: Int) -> Buffer { + TerminalMenu.render( + title: title, subtitle: subtitle, options: options, selection: selection, width: width, height: height + ) + } + + static func projectCleanupConfirmation(folderCount: Int) -> StartConfirmation? { + folderCount > 0 ? .projectCleanup(folderCount: folderCount) : nil + } + + static func noFoldersNotice(width: Int, height: Int) -> Buffer { + CleanupFlow.infoScreen( + title: options[projectCleanupIndex].title, + message: Purge.noFoldersMessage, + on: screen(selection: projectCleanupIndex, width: width, height: height) + ) + } + + private static func showNoFoldersNotice() throws { + let session = try TerminalSession() + defer { session.close() } + CleanupFlow.showInfo(on: session) { noFoldersNotice(width: session.width, height: session.height) } + } + static func run(setupError: Error?) throws { var focus = 0 while let choice = try TerminalMenu.choose(title: title, subtitle: subtitle, options: options, initialSelection: focus) { @@ -64,9 +89,16 @@ enum HomeMenu { ) else { continue } let arguments = [[], ["dev"], ["junk"], ["ai"], ["trash"]] try Clean.parse(arguments[category]).run() - case 1: try Purge.parse([]).run() + case projectCleanupIndex: + let folderCount = try ConfigStore(fileURL: AppPaths.configFile).projectRoots.count + guard let confirmation = projectCleanupConfirmation(folderCount: folderCount) else { + try showNoFoldersNotice() + continue + } + guard try confirmation.ask() else { continue } + try Purge.parse([]).run() case exploreIndex: - guard try ExploreConfirmation.ask() else { continue } + guard try StartConfirmation.explore.ask() else { continue } try Analyze.parse([]).run() case statusIndex: let session = try TerminalSession() diff --git a/cli/Tests/puremacTests/CleanScanTests.swift b/cli/Tests/puremacTests/CleanScanTests.swift new file mode 100644 index 0000000..5d10d49 --- /dev/null +++ b/cli/Tests/puremacTests/CleanScanTests.swift @@ -0,0 +1,47 @@ +import XCTest +import TerminalUI +@testable import puremac + +final class CleanScanTests: XCTestCase { + private func ignore() -> IgnoreStore { + try! IgnoreStore(fileURL: FileManager.default.temporaryDirectory.appendingPathComponent("clean-scan-\(UUID().uuidString)")) + } + + func testDefaultScanFiltersEmptyCategories() { + XCTAssertTrue(Clean.scan(ids: ["none"], ignore: ignore(), progress: .silent).isEmpty) + } + + func testStatusNamesEachCategoryWithItsPosition() { + let status = WorkProgress(ScanStatus(headline: "Scanning")) + _ = Clean.scan(ids: ["none", "other"], ignore: ignore(), progress: .silent, status: status) + XCTAssertEqual(status.value.headline, "Scanning Other, 2 of 2") + } + + func testCancelledScanStopsBeforeTheNextCategory() { + let status = WorkProgress(ScanStatus(headline: "Scanning")) + let cancel = CancelFlag() + cancel.cancel() + let result = Clean.scan(ids: ["none", "other"], ignore: ignore(), progress: .silent, status: status, cancel: cancel) + XCTAssertTrue(result.isEmpty) + XCTAssertEqual(status.value.headline, "Scanning") + } + + func testScanCountsFoundItemsAndPassesCancelStateToTheCategoryScan() { + let status = WorkProgress(ScanStatus(headline: "Scanning")) + let cancel = CancelFlag() + var cancelledSeenByScan: Bool? + let item = ScanItem(path: "/x", sizeBytes: 500, modified: nil, identity: nil) + let result = Clean.scan( + ids: ["a"], ignore: ignore(), progress: .silent, status: status, cancel: cancel, + scanCategory: { id, title, _, _, isCancelled in + cancel.cancel() + cancelledSeenByScan = isCancelled() + return CategoryScan(id: id, title: title, groups: [ToolGroup(tool: "T", items: [item])]) + } + ) + XCTAssertEqual(result.count, 1) + XCTAssertEqual(status.value.foundCount, 1) + XCTAssertEqual(status.value.foundBytes, 500) + XCTAssertEqual(cancelledSeenByScan, true) + } +} diff --git a/cli/Tests/puremacTests/CleanupFlowTests.swift b/cli/Tests/puremacTests/CleanupFlowTests.swift index 866b620..cd48f57 100644 --- a/cli/Tests/puremacTests/CleanupFlowTests.swift +++ b/cli/Tests/puremacTests/CleanupFlowTests.swift @@ -5,17 +5,75 @@ import TerminalUI final class CleanupFlowTests: XCTestCase { private let labels = CleanupFlow.Labels( - scanning: "Scanning Developer caches …", + scanning: "Scanning Developer caches", empty: "No cleanup candidates found in readable locations.", reviewTitle: "Choose items to clean", noun: "item" ) - func testScanningScreenUsesPureMacTitleMessageAndCancelHint() { - let lines = CleanupFlow.scanningScreen(labels: labels, width: 60, height: 14).plainLines() + func testScanningScreenUsesPureMacTitleHeadlineWithSpinnerAndCancelHint() { + let status = ScanStatus(headline: "Scanning Developer caches, 2 of 4") + let lines = CleanupFlow.scanningScreen(status: status, tick: 0, width: 60, height: 14).plainLines() XCTAssertTrue(lines[0].hasPrefix("╭─ PureMac ")) - XCTAssertTrue(lines[1].contains("Scanning Developer caches …")) - XCTAssertTrue(lines.contains { $0.contains("Ctrl+C cancel") }) + XCTAssertTrue(lines[1].contains("⠋ Scanning Developer caches, 2 of 4")) + XCTAssertTrue(lines.contains { $0.contains("Esc/q cancel") }) + } + + func testScanningScreenSpinnerFollowsTheTick() { + let status = ScanStatus(headline: "Scanning") + let lines = CleanupFlow.scanningScreen(status: status, tick: 3, width: 60, height: 14).plainLines() + XCTAssertTrue(lines[1].contains("\(Spinner.frame(tick: 3)) Scanning")) + } + + func testScanningScreenShowsTheFolderBeingWalkedDimAndTheFoundSoFar() { + let status = ScanStatus(headline: "Scanning ~/Projects", folder: "/tmp/a/b", foundCount: 3, foundBytes: 2_000_000) + let buffer = CleanupFlow.scanningScreen(status: status, tick: 0, width: 60, height: 14) + let lines = buffer.plainLines() + XCTAssertTrue(lines[2].contains("/tmp/a/b")) + XCTAssertTrue(buffer[2, 2].style.dim) + XCTAssertTrue(lines[3].contains("Found 3 items · \(ByteCount.human(2_000_000))"), lines[3]) + XCTAssertFalse(buffer[2, 3].style.dim) + } + + func testScanningScreenFoundRowUsesTheSingularAndStartsAtZero() { + let none = CleanupFlow.scanningScreen(status: ScanStatus(headline: "Scanning"), tick: 0, width: 60, height: 14).plainLines() + XCTAssertTrue(none[3].contains("Found 0 items · \(ByteCount.human(0))"), none[3]) + let one = CleanupFlow.scanningScreen( + status: ScanStatus(headline: "Scanning", foundCount: 1, foundBytes: 10), tick: 0, width: 60, height: 14 + ).plainLines() + XCTAssertTrue(one[3].contains("Found 1 item · "), one[3]) + } + + func testScanningScreenLongFolderIsMiddleTruncated() { + let folder = "/Users/example/" + String(repeating: "a", count: 80) + "/src" + let lines = CleanupFlow.scanningScreen( + status: ScanStatus(headline: "Scanning", folder: folder), tick: 0, width: 40, height: 12 + ).plainLines() + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines[2].contains("…")) + XCTAssertTrue(lines[2].contains("/src")) + } + + func testScanningScreenLongHeadlineKeepsTheLastFolderName() { + let headline = "Scanning /Users/example/" + String(repeating: "a", count: 80) + "/ProjectX" + let lines = CleanupFlow.scanningScreen(status: ScanStatus(headline: headline), tick: 0, width: 40, height: 12).plainLines() + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines[1].contains("…")) + XCTAssertTrue(lines[1].contains("ProjectX"), lines[1]) + } + + func testInitialStatusUsesTheScanningLabelAsIs() { + XCTAssertEqual(labels.initialStatus.headline, "Scanning Developer caches") + XCTAssertEqual(labels.initialStatus.foundCount, 0) + } + + func testEscapeAndQCancelTheScanAndNothingElseDoes() { + XCTAssertTrue(CleanupFlow.cancelsScan(.escape)) + XCTAssertTrue(CleanupFlow.cancelsScan(.character("q"))) + XCTAssertTrue(CleanupFlow.cancelsScan(.character("Q"))) + XCTAssertFalse(CleanupFlow.cancelsScan(.enter)) + XCTAssertFalse(CleanupFlow.cancelsScan(.character("n"))) + XCTAssertFalse(CleanupFlow.cancelsScan(.up)) } func testEmptyScreenShowsInfoDialogOverFadedScanningScreen() { @@ -24,7 +82,7 @@ final class CleanupFlowTests: XCTestCase { XCTAssertTrue(lines.contains { $0.contains("Nothing to clean") }) XCTAssertTrue(lines.contains { $0.contains("No cleanup candidates found in readable locations.") }) XCTAssertTrue(lines.contains { $0.contains("› OK ‹") }) - XCTAssertTrue(lines.contains { $0.contains("Scanning Developer caches …") }) + XCTAssertTrue(lines.contains { $0.contains("⠋ Scanning Developer caches") && !$0.contains("…") }) XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) XCTAssertTrue(buffer.lines(colors: true).joined().contains("\u{1B}[7m› OK ‹")) } diff --git a/cli/Tests/puremacTests/ExploreConfirmationTests.swift b/cli/Tests/puremacTests/ExploreConfirmationTests.swift deleted file mode 100644 index f9a2a0d..0000000 --- a/cli/Tests/puremacTests/ExploreConfirmationTests.swift +++ /dev/null @@ -1,79 +0,0 @@ -import XCTest -import TerminalUI -@testable import puremac - -final class ExploreConfirmationTests: XCTestCase { - func testEnterActivatesTheFocusedButton() { - var model = ExploreConfirmation() - XCTAssertEqual(model.handle(.enter), .start) - XCTAssertNil(model.handle(.left)) - XCTAssertEqual(model.handle(.enter), .back) - } - - func testLeftRightClampAndTabCycles() { - var model = ExploreConfirmation() - XCTAssertNil(model.handle(.right)) - XCTAssertEqual(model.handle(.enter), .start) - XCTAssertNil(model.handle(.left)) - XCTAssertNil(model.handle(.left)) - XCTAssertEqual(model.handle(.enter), .back) - XCTAssertNil(model.handle(.tab)) - XCTAssertEqual(model.handle(.enter), .start) - XCTAssertNil(model.handle(.tab)) - XCTAssertEqual(model.handle(.enter), .back) - } - - func testEscapeQAndNGoBackFromAnyFocus() { - for key in [TerminalKey.escape, .character("q"), .character("Q"), .character("n"), .character("N")] { - var model = ExploreConfirmation() - XCTAssertEqual(model.handle(key), .back) - } - } - - func testSStartsFromAnyFocus() { - var model = ExploreConfirmation() - _ = model.handle(.left) - XCTAssertEqual(model.handle(.character("s")), .start) - XCTAssertEqual(model.handle(.character("S")), .start) - } - - func testOtherKeysDoNothing() { - var model = ExploreConfirmation() - for key in [TerminalKey.up, .down, .space, .character("x"), .character("y")] { - XCTAssertNil(model.handle(key)) - } - XCTAssertEqual(model.handle(.enter), .start) - } - - func testRendersTheDialogOverTheFadedMenu() { - let buffer = ExploreConfirmation().render(width: 80, height: 24) - let lines = buffer.plainLines() - XCTAssertEqual(lines.count, 24) - XCTAssertTrue(lines.contains { $0.contains("Explore your home folder?") }) - XCTAssertTrue(lines.contains { $0.contains("Measuring every folder can take a few minutes.") }) - XCTAssertTrue(lines.contains { $0.contains("[ Cancel ] › Start ‹") }) - XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) - let menuRow = lines.firstIndex { $0.contains("Clean caches") } - XCTAssertNotNil(menuRow) - XCTAssertEqual(buffer[2, menuRow ?? 0].style, TextStyle(dim: true)) - } - - func testFocusFollowsTheModel() { - var model = ExploreConfirmation() - _ = model.handle(.left) - let lines = model.render(width: 80, height: 24).plainLines() - XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Start ]") }) - } - - func testFitsTheMinimumSize() { - let lines = ExploreConfirmation().render(width: 40, height: 12).plainLines() - XCTAssertEqual(lines.count, 12) - XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) - XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) - } - - func testBelowTheMinimumSizeShowsWhatEscDoes() { - let lines = ExploreConfirmation().render(width: 39, height: 11).plainLines() - XCTAssertTrue(lines.contains { $0.contains("Esc back") }) - } -} diff --git a/cli/Tests/puremacTests/PurgerScanTests.swift b/cli/Tests/puremacTests/PurgerScanTests.swift new file mode 100644 index 0000000..184c80e --- /dev/null +++ b/cli/Tests/puremacTests/PurgerScanTests.swift @@ -0,0 +1,119 @@ +import XCTest +@testable import puremac + +final class PurgerScanTests: XCTestCase { + private var root: URL! + private let fileManager = FileManager.default + + override func setUpWithError() throws { + try super.setUpWithError() + let provisional = fileManager.temporaryDirectory + .appendingPathComponent("puremac-purger-tests-\(UUID().uuidString)", isDirectory: true) + try fileManager.createDirectory(at: provisional, withIntermediateDirectories: true) + root = provisional.resolvingSymlinksInPath() + } + + override func tearDownWithError() throws { + if let root { try? fileManager.removeItem(at: root) } + try super.tearDownWithError() + } + + func testDefaultScanGroupsByProjectAndSortsBySize() throws { + let large = try artifact("alpha/node_modules", bytes: 16_384) + let medium = try artifact("beta/target", bytes: 8192) + let small = try artifact("beta/src/.build", bytes: 4096) + try fileManager.createDirectory(at: root.appendingPathComponent("beta/plain"), withIntermediateDirectories: true) + + let scan = Purger.scan(roots: [root.path], olderThanDays: 0, ignore: try ignoreStore()) + + XCTAssertEqual(scan.id, "purge") + XCTAssertEqual(scan.title, "Project Artifacts") + XCTAssertEqual(scan.groups.map(\.tool), ["alpha", "beta"]) + XCTAssertEqual(scan.groups.map { $0.items.map { canonical($0.path) } }, [[canonical(large.path)], [canonical(medium.path), canonical(small.path)]]) + XCTAssertEqual(scan.groups.flatMap(\.items).map(\.sizeBytes), [16_384, 8192, 4096]) + XCTAssertTrue(scan.groups.flatMap(\.items).allSatisfy(\.selected)) + } + + func testRecentArtifactsStayUnselectedAndEmptyOnesAreSkipped() throws { + try artifact("alpha/node_modules", bytes: 8192) + try fileManager.createDirectory(at: root.appendingPathComponent("alpha/venv"), withIntermediateDirectories: true) + + let scan = Purger.scan(roots: [root.path], olderThanDays: 7, ignore: try ignoreStore()) + + XCTAssertEqual(scan.groups.flatMap(\.items).map(\.selected), [false]) + } + + func testProgressReportsRootsWalkedFoldersAndFoundArtifacts() throws { + try artifact("alpha/node_modules", bytes: 8192) + var events: [PurgeScanEvent] = [] + + _ = Purger.scan(roots: [root.path], olderThanDays: 0, ignore: try ignoreStore(), progress: { events.append($0) }) + + XCTAssertEqual(events.first, .root(canonical(root.path))) + let canonicalEvents = events.map { event -> PurgeScanEvent in + switch event { + case .root(let path): .root(canonical(path)) + case .walking(let path): .walking(canonical(path)) + case .found(let bytes): .found(bytes: bytes) + } + } + XCTAssertTrue(canonicalEvents.contains(.walking(canonical(root.appendingPathComponent("alpha").path)))) + XCTAssertTrue(canonicalEvents.contains(.found(bytes: 8192))) + } + + func testProgressDoesNotChangeTheResult() throws { + try artifact("alpha/node_modules", bytes: 16_384) + try artifact("beta/target", bytes: 8192) + let ignore = try ignoreStore() + + let plain = Purger.scan(roots: [root.path], olderThanDays: 3, ignore: ignore) + let reported = Purger.scan(roots: [root.path], olderThanDays: 3, ignore: ignore, progress: { _ in }, isCancelled: { false }) + + XCTAssertEqual(plain.groups.map(\.tool), reported.groups.map(\.tool)) + XCTAssertEqual(plain.groups.flatMap(\.items).map(\.path), reported.groups.flatMap(\.items).map(\.path)) + XCTAssertEqual(plain.groups.flatMap(\.items).map(\.selected), reported.groups.flatMap(\.items).map(\.selected)) + } + + func testCancelledBeforeStartingFindsNothing() throws { + try artifact("alpha/node_modules", bytes: 8192) + var events: [PurgeScanEvent] = [] + + let scan = Purger.scan( + roots: [root.path], olderThanDays: 0, ignore: try ignoreStore(), + progress: { events.append($0) }, isCancelled: { true } + ) + + XCTAssertTrue(scan.groups.isEmpty) + XCTAssertFalse(events.contains { if case .found = $0 { true } else { false } }) + } + + func testCancelStopsTheWalkAfterTheFirstFind() throws { + try artifact("alpha/node_modules", bytes: 8192) + try artifact("beta/target", bytes: 8192) + var found = 0 + + let scan = Purger.scan( + roots: [root.path], olderThanDays: 0, ignore: try ignoreStore(), + progress: { if case .found = $0 { found += 1 } }, isCancelled: { found >= 1 } + ) + + XCTAssertEqual(found, 1) + XCTAssertEqual(scan.groups.flatMap(\.items).count, 1) + } + + private func canonical(_ path: String) -> String { + URL(fileURLWithPath: path).resolvingSymlinksInPath().path + } + + @discardableResult + private func artifact(_ relative: String, bytes: Int) throws -> URL { + let url = root.appendingPathComponent(relative, isDirectory: true) + try fileManager.createDirectory(at: url, withIntermediateDirectories: true) + try Data(repeating: 1, count: bytes).write(to: url.appendingPathComponent("file.bin")) + return url + } + + private func ignoreStore() throws -> IgnoreStore { + try IgnoreStore(fileURL: root.appendingPathComponent("config/ignore")) + } +} diff --git a/cli/Tests/puremacTests/ScanProgressTests.swift b/cli/Tests/puremacTests/ScanProgressTests.swift index 4e0a7c2..6badf00 100644 --- a/cli/Tests/puremacTests/ScanProgressTests.swift +++ b/cli/Tests/puremacTests/ScanProgressTests.swift @@ -17,7 +17,84 @@ final class ScanProgressTests: XCTestCase { XCTAssertTrue(verbose.hasPrefix(" scanning None…\r")) } + func testCatalogScanReturnsGroupsSizesAndSelection() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/cache-a/data", bytes: 8192) + try FileManager.default.createDirectory(atPath: "\(dir)/cache-b", withIntermediateDirectories: true) + let targets = [ + Target(tool: "Tool A", paths: ["\(dir)/cache-a"], selectedByDefault: false), + Target(tool: "Tool B", paths: ["\(dir)/cache-b"]), + Target(tool: "Tool C", paths: ["\(dir)/missing"]) + ] + let groups = CategoryScanner.scanCatalog(targets: targets, ignore: ignore(), isCancelled: { false }) + XCTAssertEqual(groups.map(\.tool), ["Tool A"]) + let item = try XCTUnwrap(groups.first?.items.first) + XCTAssertEqual(item.path, "\(dir)/cache-a") + XCTAssertGreaterThanOrEqual(item.sizeBytes, 8192) + XCTAssertFalse(item.selected) + } + + func testCatalogScanOfContentsTargetListsChildren() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/logs/one/data", bytes: 8192) + _ = try makeFile("\(dir)/logs/two/data", bytes: 8192) + let groups = CategoryScanner.scanCatalog( + targets: [Target(tool: "Logs", paths: ["\(dir)/logs"], contents: true)], ignore: ignore(), isCancelled: { false } + ) + XCTAssertEqual(groups.first?.items.map(\.path).sorted(), ["\(dir)/logs/one", "\(dir)/logs/two"]) + XCTAssertTrue(groups.first?.items.allSatisfy(\.selected) ?? false) + } + + func testCancelledCatalogScanReturnsNoGroups() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/cache/data", bytes: 8192) + let groups = CategoryScanner.scanCatalog( + targets: [Target(tool: "Tool", paths: ["\(dir)/cache"])], ignore: ignore(), isCancelled: { true } + ) + XCTAssertTrue(groups.isEmpty) + } + + func testTrashScanReturnsOneGroupPerRootWithItems() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/trash/old/data", bytes: 8192) + let groups = CategoryScanner.scanTrash( + roots: ["\(dir)/trash", "\(dir)/no-trash"], ignore: ignore(), isCancelled: { false } + ) + XCTAssertEqual(groups.map(\.tool), ["Trash"]) + XCTAssertEqual(groups.first?.items.map(\.path), ["\(dir)/trash/old"]) + XCTAssertTrue(groups.first?.items.allSatisfy(\.selected) ?? false) + } + + func testCancelledTrashScanReturnsNoGroups() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/trash/old/data", bytes: 8192) + XCTAssertTrue(CategoryScanner.scanTrash(roots: ["\(dir)/trash"], ignore: ignore(), isCancelled: { true }).isEmpty) + } + + func testDefaultScanOfAnUnknownCategoryIsEmpty() { + let scan = CategoryScanner.scan(categoryID: "none", title: "None", ignore: ignore(), progress: .silent) + XCTAssertEqual(scan.id, "none") + XCTAssertEqual(scan.title, "None") + XCTAssertTrue(scan.groups.isEmpty) + } + private func ignore() -> IgnoreStore { try! IgnoreStore(fileURL: FileManager.default.temporaryDirectory.appendingPathComponent("scan-progress-\(UUID().uuidString)")) } + + private func tempDir() throws -> String { + let url = FileManager.default.temporaryDirectory + .appendingPathComponent("scan-progress-dir-\(UUID().uuidString)").resolvingSymlinksInPath() + try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) + addTeardownBlock { try? FileManager.default.removeItem(at: url) } + return url.path + } + + private func makeFile(_ path: String, bytes: Int) throws -> String { + try FileManager.default.createDirectory( + atPath: (path as NSString).deletingLastPathComponent, withIntermediateDirectories: true + ) + try Data(repeating: 1, count: bytes).write(to: URL(fileURLWithPath: path)) + return path + } } diff --git a/cli/Tests/puremacTests/ScanStatusTests.swift b/cli/Tests/puremacTests/ScanStatusTests.swift new file mode 100644 index 0000000..896a161 --- /dev/null +++ b/cli/Tests/puremacTests/ScanStatusTests.swift @@ -0,0 +1,48 @@ +import XCTest +import TerminalUI +@testable import puremac + +final class ScanStatusTests: XCTestCase { + func testStartsWithTheHeadlineAndNothingFound() { + let status = ScanStatus(headline: "Scanning ~/Projects") + XCTAssertEqual(status.headline, "Scanning ~/Projects") + XCTAssertNil(status.folder) + XCTAssertEqual(status.foundCount, 0) + XCTAssertEqual(status.foundBytes, 0) + } + + func testRootEventSetsTheHeadlineAndClearsTheFolder() { + var status = ScanStatus(headline: "Scanning …", folder: "/old") + status.apply(.root("/Users/example/Projects")) + XCTAssertEqual(status.headline, "Scanning " + Render.shorten("/Users/example/Projects")) + XCTAssertNil(status.folder) + } + + func testWalkingEventSetsTheFolder() { + var status = ScanStatus(headline: "Scanning") + status.apply(.walking("/tmp/a/b")) + XCTAssertEqual(status.folder, "/tmp/a/b") + } + + func testFoundEventsAddUp() { + var status = ScanStatus(headline: "Scanning") + status.apply(.found(bytes: 100)) + status.apply(.found(bytes: 50)) + XCTAssertEqual(status.foundCount, 2) + XCTAssertEqual(status.foundBytes, 150) + } + + func testBeginCategoryNamesTheCategoryAndItsPosition() { + var status = ScanStatus(headline: "Scanning", folder: "/old") + status.beginCategory(title: "Developer caches", position: 2, count: 4) + XCTAssertEqual(status.headline, "Scanning Developer caches, 2 of 4") + } + + func testFinishedCategoryAddsItsItemsAndSize() { + var status = ScanStatus(headline: "Scanning") + let items = [ScanItem(path: "/tmp/a", sizeBytes: 10, modified: nil), ScanItem(path: "/tmp/b", sizeBytes: 5, modified: nil)] + status.addFound(in: CategoryScan(id: "dev", title: "Dev", groups: [ToolGroup(tool: "npm", items: items)])) + XCTAssertEqual(status.foundCount, 2) + XCTAssertEqual(status.foundBytes, 15) + } +} diff --git a/cli/Tests/puremacTests/StartConfirmationTests.swift b/cli/Tests/puremacTests/StartConfirmationTests.swift new file mode 100644 index 0000000..eeac363 --- /dev/null +++ b/cli/Tests/puremacTests/StartConfirmationTests.swift @@ -0,0 +1,126 @@ +import XCTest +import TerminalUI +@testable import puremac + +final class StartConfirmationTests: XCTestCase { + func testEnterActivatesTheFocusedButton() { + var model = StartConfirmation.explore + XCTAssertEqual(model.handle(.enter), .start) + XCTAssertNil(model.handle(.left)) + XCTAssertEqual(model.handle(.enter), .back) + } + + func testLeftRightClampAndTabCycles() { + var model = StartConfirmation.explore + XCTAssertNil(model.handle(.right)) + XCTAssertEqual(model.handle(.enter), .start) + XCTAssertNil(model.handle(.left)) + XCTAssertNil(model.handle(.left)) + XCTAssertEqual(model.handle(.enter), .back) + XCTAssertNil(model.handle(.tab)) + XCTAssertEqual(model.handle(.enter), .start) + XCTAssertNil(model.handle(.tab)) + XCTAssertEqual(model.handle(.enter), .back) + } + + func testEscapeQAndNGoBackFromAnyFocus() { + for key in [TerminalKey.escape, .character("q"), .character("Q"), .character("n"), .character("N")] { + var model = StartConfirmation.explore + XCTAssertEqual(model.handle(key), .back) + } + } + + func testSStartsFromAnyFocus() { + var model = StartConfirmation.explore + _ = model.handle(.left) + XCTAssertEqual(model.handle(.character("s")), .start) + XCTAssertEqual(model.handle(.character("S")), .start) + } + + func testOtherKeysDoNothing() { + var model = StartConfirmation.explore + for key in [TerminalKey.up, .down, .space, .character("x"), .character("y")] { + XCTAssertNil(model.handle(key)) + } + XCTAssertEqual(model.handle(.enter), .start) + } + + func testRendersTheDialogOverTheFadedMenu() { + let buffer = StartConfirmation.explore.render(width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertEqual(lines.count, 24) + XCTAssertTrue(lines.contains { $0.contains("Explore your home folder?") }) + XCTAssertTrue(lines.contains { $0.contains("Measuring every folder can take a few minutes.") }) + XCTAssertTrue(lines.contains { $0.contains("[ Cancel ] › Start ‹") }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + let menuRow = lines.firstIndex { $0.contains("Clean caches") } + XCTAssertNotNil(menuRow) + XCTAssertEqual(buffer[2, menuRow ?? 0].style, TextStyle(dim: true)) + } + + func testFocusFollowsTheModel() { + var model = StartConfirmation.explore + _ = model.handle(.left) + let lines = model.render(width: 80, height: 24).plainLines() + XCTAssertTrue(lines.contains { $0.contains("› Cancel ‹ [ Start ]") }) + } + + func testFitsTheMinimumSize() { + let lines = StartConfirmation.explore.render(width: 40, height: 12).plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + } + + func testBelowTheMinimumSizeShowsWhatEscDoes() { + let lines = StartConfirmation.explore.render(width: 39, height: 11).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Esc back") }) + } + + func testProjectCleanupDialogTitleMessageAndFocus() { + let lines = StartConfirmation.projectCleanup(folderCount: 3).render(width: 80, height: 24).plainLines() + XCTAssertTrue(lines.contains { $0.contains("Scan your project folders?") }) + XCTAssertTrue(lines.contains { $0.contains("Searching 3 folders for build artifacts can take a few") }) + XCTAssertTrue(lines.contains { $0.contains("[ Cancel ] › Start ‹") }) + XCTAssertTrue(lines.contains { $0.contains("Enter select Esc back") }) + XCTAssertTrue(lines.contains { $0.contains("Project cleanup") }) + } + + func testProjectCleanupMessageUsesTheSingularForOneFolder() { + let message = StartConfirmation.projectCleanup(folderCount: 1).message + XCTAssertEqual(message, "Searching 1 folder for build artifacts can take a few minutes.") + XCTAssertEqual( + StartConfirmation.projectCleanup(folderCount: 5).message, + "Searching 5 folders for build artifacts can take a few minutes." + ) + } + + func testProjectCleanupKeysMatchTheExplorerDialog() { + var model = StartConfirmation.projectCleanup(folderCount: 2) + XCTAssertEqual(model.handle(.character("s")), .start) + XCTAssertEqual(model.handle(.escape), .back) + XCTAssertNil(model.handle(.left)) + XCTAssertEqual(model.handle(.enter), .back) + } + + func testBackgroundMenuFocusFollowsTheEntry() { + let explore = StartConfirmation.explore.render(width: 80, height: 24).plainLines() + let project = StartConfirmation.projectCleanup(folderCount: 2).render(width: 80, height: 24).plainLines() + XCTAssertTrue(explore.contains { $0.contains("› 3. Explor") }) + XCTAssertTrue(project.contains { $0.contains("› 2. Project cleanup") }) + } + + func testNoConfirmationWithoutProjectFolders() { + XCTAssertNil(HomeMenu.projectCleanupConfirmation(folderCount: 0)) + XCTAssertNotNil(HomeMenu.projectCleanupConfirmation(folderCount: 1)) + } + + func testNoFoldersNoticeShowsAnInfoDialogOverTheFadedMenu() { + let buffer = HomeMenu.noFoldersNotice(width: 80, height: 24) + let lines = buffer.plainLines() + XCTAssertTrue(lines.contains { $0.contains("No project folders configured. Add one in Preferences.") }) + XCTAssertTrue(lines.contains { $0.contains("› OK ‹") }) + XCTAssertTrue(lines.contains { $0.contains("Project cleanup") }) + XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) + } +} diff --git a/cli/Tests/puremacTests/StatusScreenTests.swift b/cli/Tests/puremacTests/StatusScreenTests.swift index 05e9fdd..e8c2fb2 100644 --- a/cli/Tests/puremacTests/StatusScreenTests.swift +++ b/cli/Tests/puremacTests/StatusScreenTests.swift @@ -5,11 +5,13 @@ import TerminalUI final class StatusScreenTests: XCTestCase { private let hint = KeyHint("Ctrl+C", "cancel") - func testRendersWindowMessageDetailDividerAndHint() { + func testRendersWindowRowsDividerAndHint() { let buffer = StatusScreen.render( title: "PureMac", - message: "Working...", - detail: "/Users/example/" + String(repeating: "a", count: 60), + rows: [ + StatusRow("Working...", style: TextStyle(dim: true)), + StatusRow("/Users/example/" + String(repeating: "a", count: 60), truncatesInMiddle: true) + ], hint: hint, width: 40, height: 12 @@ -28,29 +30,29 @@ final class StatusScreenTests: XCTestCase { func testLongMessageEndsWithEllipsis() { let message = "Scanning ~/Projects, ~/Code, ~/dev, ~/GitHub, ~/Workspace …" let lines = StatusScreen.render( - title: "PureMac", message: message, detail: nil, hint: hint, width: 40, height: 12 + title: "PureMac", rows: [StatusRow(message, style: TextStyle(dim: true)), StatusRow("")], hint: hint, width: 40, height: 12 ).plainLines() XCTAssertTrue(lines[1].contains("… │"), lines[1]) XCTAssertFalse(lines[1].contains("Workspace")) } - func testDetailRowIsEmptyWithoutDetail() { + func testRowsAfterTheLastOneStayBlank() { let lines = StatusScreen.render( - title: "PureMac", message: "Working...", detail: nil, hint: hint, width: 40, height: 12 + title: "PureMac", rows: [StatusRow("Working...", style: TextStyle(dim: true))], hint: hint, width: 40, height: 12 ).plainLines() XCTAssertEqual(lines[2], "│" + String(repeating: " ", count: 38) + "│") } func testBelowMinimumUsesTooSmallScreenWithHintAsExit() { XCTAssertEqual( - StatusScreen.render(title: "PureMac", message: "x", detail: nil, hint: hint, width: 39, height: 11), + StatusScreen.render(title: "PureMac", rows: [StatusRow("x", style: TextStyle(dim: true)), StatusRow("")], hint: hint, width: 39, height: 11), TooSmallScreen.render(title: "PureMac", exitHint: "Ctrl+C cancel", width: 39, height: 11) ) } func testOverlayFadesBackgroundAndCentersDialog() { let background = StatusScreen.render( - title: "PureMac", message: "Working...", detail: nil, hint: hint, width: 60, height: 14 + title: "PureMac", rows: [StatusRow("Working...", style: TextStyle(dim: true)), StatusRow("")], hint: hint, width: 60, height: 14 ) let dialog = Dialog(title: "Done", message: [Span("All good.")]) let result = StatusScreen.overlay(dialog, on: background) @@ -64,4 +66,28 @@ final class StatusScreenTests: XCTestCase { let result = StatusScreen.overlay(Dialog(title: "Done", message: [Span("All good.")]), on: background) XCTAssertEqual(result, background) } + + func testRowsRenderWithTheirOwnStyleAndTruncation() { + let long = "/Users/example/" + String(repeating: "a", count: 60) + "/end" + let buffer = StatusScreen.render( + title: "PureMac", + rows: [ + StatusRow("First", style: TextStyle(dim: true)), + StatusRow(long, truncatesInMiddle: true), + StatusRow("Third") + ], + hint: hint, + width: 40, + height: 12 + ) + let lines = buffer.plainLines() + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines[1].contains("First")) + XCTAssertTrue(buffer[2, 1].style.dim) + XCTAssertTrue(lines[2].contains("…") && lines[2].contains("/end")) + XCTAssertFalse(buffer[2, 2].style.dim) + XCTAssertTrue(lines[3].contains("Third")) + XCTAssertTrue(lines.contains { $0.hasPrefix("├") }) + XCTAssertTrue(lines.contains { $0.contains("Ctrl+C cancel") }) + } } From db874bd95386ee28fae2469124bd5e450a917ad7 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 15:57:03 +0000 Subject: [PATCH 19/21] fix(cli): keep config.json readable by older releases by storing project folders separately --- cli/README.md | 2 +- cli/Sources/puremac/Commands/Config.swift | 9 +- cli/Sources/puremac/Commands/Purge.swift | 2 +- cli/Sources/puremac/Core/PathListEditor.swift | 13 +- .../puremac/Core/PreferencesScreen.swift | 8 +- cli/Sources/puremac/Core/Stores.swift | 260 ++++++++++-------- cli/Sources/puremac/PureMac.swift | 2 +- .../puremacTests/ConfigSettingsTests.swift | 155 ++++------- .../puremacTests/PathListEditorTests.swift | 4 +- .../puremacTests/PreferencesScreenTests.swift | 19 +- .../puremacTests/PreferencesSheetTests.swift | 9 +- .../ProjectFoldersStoreTests.swift | 114 ++++++++ 12 files changed, 356 insertions(+), 241 deletions(-) create mode 100644 cli/Tests/puremacTests/ProjectFoldersStoreTests.swift diff --git a/cli/README.md b/cli/README.md index bb364c5..3176485 100644 --- a/cli/README.md +++ b/cli/README.md @@ -36,7 +36,7 @@ puremac purge ~/Projects puremac analyze ~/Projects ``` -`puremac purge` with no path scans the project folders from Preferences, by default ~/Projects, ~/Code, ~/dev, ~/GitHub and ~/Workspace. The first interactive start creates `~/.config/puremac/config.json` and an empty `~/.config/puremac/ignore`; existing files are never overwritten. +`puremac purge` with no path scans the project folders from Preferences, by default ~/Projects, ~/Code, ~/dev, ~/GitHub and ~/Workspace. The first interactive start creates `~/.config/puremac/config.json` (the age setting only), an empty `~/.config/puremac/ignore` and `~/.config/puremac/projects` (one project folder per line, filled with those defaults); existing files are never overwritten. Project folders live in their own file so older puremac releases, which reject unknown keys in `config.json`, keep working. Cleanup opens a selection screen. Nothing is selected when the interactive review begins. Move through the list, choose individual paths, and check the running size total. Press Return to remove the selection; a confirmation dialog opens first. diff --git a/cli/Sources/puremac/Commands/Config.swift b/cli/Sources/puremac/Commands/Config.swift index d1c9b94..10eb8e2 100644 --- a/cli/Sources/puremac/Commands/Config.swift +++ b/cli/Sources/puremac/Commands/Config.swift @@ -50,16 +50,17 @@ struct Config: ParsableCommand { return } - for line in Self.sheet(store: store).plainLines() { print(line) } + let folders = try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots + for line in Self.sheet(store: store, projectFolders: folders).plainLines() { print(line) } } static let sheetTitle = "PureMac CLI settings" - static func sheet(store: ConfigStore) -> InfoSheet { + static func sheet(store: ConfigStore, projectFolders: [String]) -> InfoSheet { let days = store.olderThanDays let note = days == ConfigStore.defaultDays ? Span("default", TextStyle(dim: true)) : Span("saved", TextStyle(color: .cyan)) let keys = [InfoRow.metric(label: ConfigStore.daysKey, value: [Span("\(days) days")], note: note)] - let files = [("Settings", AppPaths.configFile), ("Protected", AppPaths.ignoreFile)].map { label, url in + let files = [("Settings", AppPaths.configFile), ("Protected", AppPaths.ignoreFile), ("Projects", AppPaths.projectsFile)].map { label, url in InfoRow.metric(label: label, value: [Span(Render.shorten(url.path))], note: nil) } return InfoSheet( @@ -68,7 +69,7 @@ struct Config: ParsableCommand { sections: [ InfoSection(title: nil, labelWidth: 26, rows: keys), InfoSection(title: "Files", labelWidth: 12, rows: files), - InfoSection(title: "Project folders", rows: store.projectRoots.map { .path(Render.shorten($0)) }), + InfoSection(title: "Project folders", rows: projectFolders.map { .path(Render.shorten($0)) }), ], footnote: nil ) diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 6c5f81e..89b248a 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -140,7 +140,7 @@ struct Purge: ParsableCommand { func resolvedRoots() throws -> [String] { guard paths.isEmpty else { return paths.map { Safety.absolutePath($0) } } - return try ConfigStore(fileURL: AppPaths.configFile).projectRoots + return try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots } func renderScan(_ cat: CategoryScan, days: Int, colors: Bool = Term.colorEnabled) { diff --git a/cli/Sources/puremac/Core/PathListEditor.swift b/cli/Sources/puremac/Core/PathListEditor.swift index 3c3fedb..173ad1c 100644 --- a/cli/Sources/puremac/Core/PathListEditor.swift +++ b/cli/Sources/puremac/Core/PathListEditor.swift @@ -37,22 +37,19 @@ extension PathListConfig { PathListConfig( title: "Project folders", emptyText: "No project folders. Press A to add one.", - load: { try ConfigStore(fileURL: AppPaths.configFile).projectRoots }, + load: { try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots }, add: { input in let typed = input.trimmingCharacters(in: .whitespaces) guard !typed.isEmpty else { throw PathListError("Enter a folder path") } let verdict = Safety.isValidScanRoot(typed) guard verdict.ok else { throw PathListError(verdict.reason ?? "Not a valid project folder") } - var store = try ConfigStore(fileURL: AppPaths.configFile) + var store = try ProjectFoldersStore(fileURL: AppPaths.projectsFile) let root = standardized(typed) - guard !store.projectRoots.contains(root) else { - throw PathListError.duplicate(root) - } - try store.setProjectRoots(store.projectRoots + [root]) + guard try store.add(root) else { throw PathListError.duplicate(root) } }, remove: { path in - var store = try ConfigStore(fileURL: AppPaths.configFile) - try store.setProjectRoots(store.projectRoots.filter { $0 != path }) + var store = try ProjectFoldersStore(fileURL: AppPaths.projectsFile) + _ = try store.remove(path) }, removalPrompt: nil ) diff --git a/cli/Sources/puremac/Core/PreferencesScreen.swift b/cli/Sources/puremac/Core/PreferencesScreen.swift index eb9eb74..f93e025 100644 --- a/cli/Sources/puremac/Core/PreferencesScreen.swift +++ b/cli/Sources/puremac/Core/PreferencesScreen.swift @@ -45,13 +45,17 @@ struct PreferencesScreen { do { let store = try ConfigStore(fileURL: AppPaths.configFile) days = store.olderThanDays - folderCount = store.projectRoots.count } catch { days = ConfigStore.defaultDays - folderCount = Purger.defaultRoots.count loadError = error.localizedDescription configUnreadable = true } + do { + folderCount = try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots.count + } catch { + folderCount = Purger.defaultRoots.count + loadError = loadError ?? error.localizedDescription + } do { pathCount = try IgnoreStore(fileURL: AppPaths.ignoreFile).roots.count } catch { diff --git a/cli/Sources/puremac/Core/Stores.swift b/cli/Sources/puremac/Core/Stores.swift index 792ee29..c64e677 100644 --- a/cli/Sources/puremac/Core/Stores.swift +++ b/cli/Sources/puremac/Core/Stores.swift @@ -16,11 +16,17 @@ enum AppPaths { static var ignoreFile: URL { configDir.appendingPathComponent("ignore") } static var configFile: URL { configDir.appendingPathComponent("config.json") } + static var projectsFile: URL { configDir.appendingPathComponent("projects") } - static func ensureDefaults(configFile: URL = configFile, ignoreFile: URL = ignoreFile) throws { + static func ensureDefaults( + configFile: URL = configFile, + ignoreFile: URL = ignoreFile, + projectsFile: URL = projectsFile + ) throws { let results = [ Result { try createIfMissing(configFile, try ConfigStore.defaultFileData()) }, Result { try createIfMissing(ignoreFile, Data()) }, + Result { try createIfMissing(projectsFile, PathListFile.contents(Purger.defaultRoots)) }, ] for case .failure(let error) in results { throw error } } @@ -40,6 +46,7 @@ enum StoreError: LocalizedError { case unknownConfigKey(String) case invalidConfigValue(key: String, value: String) case invalidProjectRoot(String) + case invalidProjectsFile(String) case invalidIgnorePath case invalidIgnoreFile(String) @@ -53,6 +60,8 @@ enum StoreError: LocalizedError { return "Invalid value '\(value)' for \(key). Use a whole number from 1 to 3650." case .invalidProjectRoot(let path): return "Project folders must be absolute paths: \(path)" + case .invalidProjectsFile(let path): + return "Project folders file contains an invalid or relative path: \(path)" case .invalidIgnorePath: return "Protected paths cannot be empty, the filesystem root, or contain newline or NUL characters." case .invalidIgnoreFile(let path): @@ -61,6 +70,112 @@ enum StoreError: LocalizedError { } } +enum PathListFile { + static func standardized(_ path: String, relativeTo currentDirectoryPath: String, allowRelative: Bool) -> String? { + guard !path.isEmpty, !containsControl(path) else { return nil } + let expanded = (path as NSString).expandingTildeInPath + let absolute: String + if expanded.hasPrefix("/") { + absolute = expanded + } else { + guard allowRelative else { return nil } + absolute = currentDirectoryPath + "/" + expanded + } + let standardized = lexicalStandardizedAbsolutePath(absolute) + guard standardized != "/", !containsControl(standardized) else { return nil } + return standardized + } + + static func load(from fileURL: URL, invalid: Error) throws -> [String]? { + guard FileManager.default.fileExists(atPath: fileURL.path) else { return nil } + let contents = try String(contentsOf: fileURL, encoding: .utf8) + var seen = Set() + var roots: [String] = [] + for line in contents.split(separator: "\n") { + guard let root = standardized(String(line), relativeTo: "/", allowRelative: false) else { throw invalid } + if seen.insert(root).inserted { roots.append(root) } + } + return roots + } + + static func adding(_ root: String, to roots: [String], save: ([String]) throws -> Void) throws -> [String]? { + guard !roots.contains(root) else { return nil } + let updated = roots + [root] + try save(updated) + return updated + } + + static func removing(_ root: String, from roots: [String], save: ([String]) throws -> Void) throws -> [String]? { + guard roots.contains(root) else { return nil } + let updated = roots.filter { $0 != root } + try save(updated) + return updated + } + + static func contents(_ roots: [String]) -> Data { + Data((roots.isEmpty ? "" : roots.joined(separator: "\n") + "\n").utf8) + } + + static func save(_ roots: [String], to fileURL: URL) throws { + try FileManager.default.createDirectory( + at: fileURL.deletingLastPathComponent(), + withIntermediateDirectories: true + ) + try contents(roots).write(to: fileURL, options: .atomic) + } + + private static func containsControl(_ text: String) -> Bool { + text.unicodeScalars.contains { $0.value == 0 || CharacterSet.newlines.contains($0) } + } + + private static func lexicalStandardizedAbsolutePath(_ path: String) -> String { + var components: [Substring] = [] + for component in path.split(separator: "/") { + if component == "." { continue } + if component == ".." { + if !components.isEmpty { components.removeLast() } + continue + } + components.append(component) + } + return "/" + components.joined(separator: "/") + } +} + +struct ProjectFoldersStore { + private(set) var roots: [String] + private let fileURL: URL + + init(fileURL: URL) throws { + self.fileURL = fileURL + roots = try PathListFile.load(from: fileURL, invalid: StoreError.invalidProjectsFile(fileURL.path)) + ?? Purger.defaultRoots + } + + mutating func add(_ path: String) throws -> Bool { + let standardized = try Self.standardized(path) + guard let updated = try PathListFile.adding(standardized, to: roots, save: { try PathListFile.save($0, to: fileURL) }) + else { return false } + roots = updated + return true + } + + mutating func remove(_ path: String) throws -> Bool { + let standardized = try Self.standardized(path) + guard let updated = try PathListFile.removing(standardized, from: roots, save: { try PathListFile.save($0, to: fileURL) }) + else { return false } + roots = updated + return true + } + + private static func standardized(_ path: String) throws -> String { + guard let standardized = PathListFile.standardized(path, relativeTo: "/", allowRelative: false) else { + throw StoreError.invalidProjectRoot(path) + } + return standardized + } +} + struct IgnoreStore { private(set) var roots: [String] private let fileURL: URL @@ -99,9 +214,7 @@ struct IgnoreStore { relativeTo: currentDirectoryPath, allowRelative: true ) - guard !roots.contains(standardized) else { return false } - let updated = roots + [standardized] - try save(updated) + guard let updated = try PathListFile.adding(standardized, to: roots, save: save) else { return false } roots = updated return true } @@ -112,9 +225,7 @@ struct IgnoreStore { relativeTo: currentDirectoryPath, allowRelative: true ) - guard roots.contains(standardized) else { return false } - let updated = roots.filter { $0 != standardized } - try save(updated) + guard let updated = try PathListFile.removing(standardized, from: roots, save: save) else { return false } roots = updated return true } @@ -124,113 +235,53 @@ struct IgnoreStore { relativeTo currentDirectoryPath: String, allowRelative: Bool ) throws -> String { - guard !path.isEmpty, - !path.unicodeScalars.contains(where: { - $0.value == 0 || CharacterSet.newlines.contains($0) - }) - else { - throw StoreError.invalidIgnorePath - } - let expanded = (path as NSString).expandingTildeInPath - let absolute: String - if expanded.hasPrefix("/") { - absolute = expanded - } else { - guard allowRelative else { - throw StoreError.invalidIgnorePath - } - absolute = currentDirectoryPath + "/" + expanded - } - let standardized = try lexicalStandardizedAbsolutePath(absolute) - guard standardized.hasPrefix("/"), standardized != "/", - !standardized.unicodeScalars.contains(where: { - $0.value == 0 || CharacterSet.newlines.contains($0) - }) - else { + guard let standardized = PathListFile.standardized( + path, + relativeTo: currentDirectoryPath, + allowRelative: allowRelative + ) else { throw StoreError.invalidIgnorePath } return standardized } - private static func lexicalStandardizedAbsolutePath(_ path: String) throws -> String { - guard path.hasPrefix("/") else { - throw StoreError.invalidIgnorePath - } - var components: [Substring] = [] - for component in path.split(separator: "/") { - if component == "." { continue } - if component == ".." { - if !components.isEmpty { components.removeLast() } - continue - } - components.append(component) - } - return "/" + components.joined(separator: "/") - } - private static func load(from fileURL: URL) throws -> [String] { - guard FileManager.default.fileExists(atPath: fileURL.path) else { return [] } - let contents = try String(contentsOf: fileURL, encoding: .utf8) - var seen = Set() - var roots: [String] = [] - for line in contents.split(separator: "\n").map(String.init) { - do { - let root = try standardized(line, relativeTo: "/", allowRelative: false) - if seen.insert(root).inserted { roots.append(root) } - } catch { - throw StoreError.invalidIgnoreFile(fileURL.path) - } - } - return roots + try PathListFile.load(from: fileURL, invalid: StoreError.invalidIgnoreFile(fileURL.path)) ?? [] } private func save(_ roots: [String]) throws { - try FileManager.default.createDirectory( - at: fileURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - let contents = roots.isEmpty ? "" : roots.sorted().joined(separator: "\n") + "\n" - try contents.write(to: fileURL, atomically: true, encoding: .utf8) + try PathListFile.save(roots.sorted(), to: fileURL) } } struct ConfigStore { private(set) var values: [String: String] - private var savedRoots: [String]? private let fileURL: URL static let daysKey = "purge.older_than_days" - static let rootsKey = "purge.roots" static let knownKeys = [daysKey] static let defaultDays = 7 var olderThanDays: Int { values[Self.daysKey].flatMap { Int($0) } ?? Self.defaultDays } - var projectRoots: [String] { savedRoots ?? Purger.defaultRoots } init(fileURL: URL) throws { self.fileURL = fileURL - (values, savedRoots) = try Self.load(from: fileURL) + values = try Self.load(from: fileURL) } mutating func set(_ key: String, _ value: String) throws { let normalized = try Self.normalizedValue(value, for: key) var updated = values updated[key] = normalized - try save(values: updated, roots: savedRoots) + let data = try Self.encode(updated) + try FileManager.default.createDirectory( + at: fileURL.deletingLastPathComponent(), + withIntermediateDirectories: true + ) + try data.write(to: fileURL, options: .atomic) values = updated } - mutating func setProjectRoots(_ roots: [String]) throws { - let standardized = try roots.map { root -> String in - guard let path = Self.standardizedRoot(root) else { - throw StoreError.invalidProjectRoot(root) - } - return path - } - try save(values: values, roots: standardized) - savedRoots = standardized - } - static func normalizedValue(_ value: String, for key: String) throws -> String { guard knownKeys.contains(key) else { throw StoreError.unknownConfigKey(key) @@ -243,48 +294,23 @@ struct ConfigStore { } static func defaultFileData() throws -> Data { - try encode(values: [daysKey: String(defaultDays)], roots: Purger.defaultRoots) - } - - private static func standardizedRoot(_ path: String) -> String? { - path.hasPrefix("/") ? (path as NSString).standardizingPath : nil - } - - private static func encode(values: [String: String], roots: [String]?) throws -> Data { - var object: [String: Any] = values - if let roots { object[rootsKey] = roots } - return try JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]) + try encode([daysKey: String(defaultDays)]) } - private func save(values: [String: String], roots: [String]?) throws { - let data = try Self.encode(values: values, roots: roots) - try FileManager.default.createDirectory( - at: fileURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try data.write(to: fileURL, options: .atomic) + private static func encode(_ values: [String: String]) throws -> Data { + try JSONSerialization.data(withJSONObject: values, options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]) } - private static func load(from fileURL: URL) throws -> ([String: String], [String]?) { - guard FileManager.default.fileExists(atPath: fileURL.path) else { return ([:], nil) } + private static func load(from fileURL: URL) throws -> [String: String] { + guard FileManager.default.fileExists(atPath: fileURL.path) else { return [:] } let data = try Data(contentsOf: fileURL) - guard let object = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] else { + guard let object = try? JSONSerialization.jsonObject(with: data), + let values = object as? [String: String] + else { throw StoreError.invalidConfigFile(fileURL.path) } - var values: [String: String] = [:] - var roots: [String]? - for (key, raw) in object { - if key == rootsKey { - guard let list = raw as? [String] else { throw StoreError.invalidConfigFile(fileURL.path) } - roots = try list.map { root in - guard let path = standardizedRoot(root) else { throw StoreError.invalidConfigFile(fileURL.path) } - return path - } - } else { - guard let text = raw as? String else { throw StoreError.invalidConfigFile(fileURL.path) } - values[key] = try normalizedValue(text, for: key) - } - } - return (values, roots) + var normalized: [String: String] = [:] + for (key, value) in values { normalized[key] = try normalizedValue(value, for: key) } + return normalized } } diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index 4b8d711..ff3df6e 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -90,7 +90,7 @@ enum HomeMenu { let arguments = [[], ["dev"], ["junk"], ["ai"], ["trash"]] try Clean.parse(arguments[category]).run() case projectCleanupIndex: - let folderCount = try ConfigStore(fileURL: AppPaths.configFile).projectRoots.count + let folderCount = try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots.count guard let confirmation = projectCleanupConfirmation(folderCount: folderCount) else { try showNoFoldersNotice() continue diff --git a/cli/Tests/puremacTests/ConfigSettingsTests.swift b/cli/Tests/puremacTests/ConfigSettingsTests.swift index d599a23..f2da5a8 100644 --- a/cli/Tests/puremacTests/ConfigSettingsTests.swift +++ b/cli/Tests/puremacTests/ConfigSettingsTests.swift @@ -22,32 +22,18 @@ final class ConfigSettingsTests: XCTestCase { try? FileManager.default.removeItem(at: directory) } - func testMissingFileGivesTheDefaults() throws { - let store = try ConfigStore(fileURL: file) - XCTAssertEqual(store.olderThanDays, 7) - XCTAssertEqual(store.projectRoots, Purger.defaultRoots) + func testMissingFileGivesTheDefaultDays() throws { + XCTAssertEqual(try ConfigStore(fileURL: file).olderThanDays, 7) } - func testOldFileWithOnlyTheDaysKeyStillLoads() throws { + func testFileWithTheDaysKeyLoads() throws { try write(#"{"purge.older_than_days": "14"}"#, to: file) - let store = try ConfigStore(fileURL: file) - XCTAssertEqual(store.olderThanDays, 14) - XCTAssertEqual(store.projectRoots, Purger.defaultRoots) - } - - func testNewFileLoadsTheRootsInOrder() throws { - try write(#"{"purge.older_than_days": "30", "purge.roots": ["/tmp/b", "/tmp/a"]}"#, to: file) - let store = try ConfigStore(fileURL: file) - XCTAssertEqual(store.olderThanDays, 30) - XCTAssertEqual(store.projectRoots, ["/tmp/b", "/tmp/a"]) + XCTAssertEqual(try ConfigStore(fileURL: file).olderThanDays, 14) } - func testWrongTypesAndRootsAreInvalidConfigFiles() throws { + func testWrongTypesAreInvalidConfigFiles() throws { let bad = [ - #"{"purge.roots": "/tmp/a"}"#, - #"{"purge.roots": ["/tmp/a", 3]}"#, - #"{"purge.roots": ["relative/path"]}"#, - #"{"purge.roots": [""]}"#, + #"{"purge.roots": ["/tmp/a"]}"#, #"{"purge.older_than_days": 14}"#, "[]", ] @@ -62,7 +48,7 @@ final class ConfigSettingsTests: XCTestCase { func testBadDaysValuesAndUnknownKeysKeepTheirValueErrors() throws { let bad = [ (#"{"purge.older_than_days": "0"}"#, "invalidConfigValue"), - (#"{"purge.older_than_days": "x", "purge.roots": []}"#, "invalidConfigValue"), + (#"{"purge.older_than_days": "7", "purge.roots": "/tmp/a"}"#, "unknownConfigKey"), (#"{"other": "1"}"#, "unknownConfigKey"), ] for (text, name) in bad { @@ -78,97 +64,81 @@ final class ConfigSettingsTests: XCTestCase { XCTAssertEqual(try ConfigStore(fileURL: file).olderThanDays, 14) } - func testEmptyRootsListIsKeptAndNotReplacedByDefaults() throws { - try write(#"{"purge.roots": []}"#, to: file) - XCTAssertEqual(try ConfigStore(fileURL: file).projectRoots, []) - } - - func testRootsRoundTripKeepOrderAndSurviveASetOfTheDays() throws { - var store = try ConfigStore(fileURL: file) - try store.setProjectRoots(["/tmp/z", "/tmp/a/../a", "/tmp/m/"]) - XCTAssertEqual(store.projectRoots, ["/tmp/z", "/tmp/a", "/tmp/m"]) - - var reloaded = try ConfigStore(fileURL: file) - XCTAssertEqual(reloaded.projectRoots, ["/tmp/z", "/tmp/a", "/tmp/m"]) - try reloaded.set("purge.older_than_days", "90") - - let again = try ConfigStore(fileURL: file) - XCTAssertEqual(again.olderThanDays, 90) - XCTAssertEqual(again.projectRoots, ["/tmp/z", "/tmp/a", "/tmp/m"]) - } - - func testSavedFileHasSortedKeysAndIsPrettyPrinted() throws { + func testSavedFileHasOnlyTheDaysKeyPrettyPrinted() throws { var store = try ConfigStore(fileURL: file) try store.set("purge.older_than_days", "14") - try store.setProjectRoots(["/tmp/a"]) - let text = try String(contentsOf: file, encoding: .utf8) - let days = try XCTUnwrap(text.range(of: "purge.older_than_days")) - let roots = try XCTUnwrap(text.range(of: "purge.roots")) - XCTAssertLessThan(days.lowerBound, roots.lowerBound) - XCTAssertTrue(text.contains("\n \""), text) + XCTAssertEqual(try String(contentsOf: file, encoding: .utf8), "{\n \"purge.older_than_days\" : \"14\"\n}") } - func testRelativeRootsAreRejectedAndNothingIsSaved() throws { - var store = try ConfigStore(fileURL: file) - XCTAssertThrowsError(try store.setProjectRoots(["relative"])) { error in - guard case StoreError.invalidProjectRoot("relative") = error else { return XCTFail("\(error)") } - } - XCTAssertEqual(store.projectRoots, Purger.defaultRoots) - XCTAssertFalse(FileManager.default.fileExists(atPath: file.path)) + func testRootsAreNotSettableThroughConfigSet() { + XCTAssertThrowsError(try Config.parse(["set", "purge.roots", "/tmp/a"])) } - func testInvalidProjectRootMessageNamesTheFolder() { + func testEnsureDefaultsCreatesAllThreeFilesWithDefaults() throws { + let config = directory.appendingPathComponent("puremac/config.json") + let ignore = directory.appendingPathComponent("puremac/ignore") + let projects = directory.appendingPathComponent("puremac/projects") + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects) + XCTAssertEqual( - StoreError.invalidProjectRoot("relative").errorDescription, - "Project folders must be absolute paths: relative" + try String(contentsOf: config, encoding: .utf8), + "{\n \"purge.older_than_days\" : \"7\"\n}" ) + XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "") + XCTAssertEqual( + try String(contentsOf: projects, encoding: .utf8), + Purger.defaultRoots.joined(separator: "\n") + "\n" + ) + XCTAssertEqual(try ProjectFoldersStore(fileURL: projects).roots, Purger.defaultRoots) } - func testRootsAreNotSettableThroughConfigSet() { - XCTAssertThrowsError(try Config.parse(["set", "purge.roots", "/tmp/a"])) - } - - func testEnsureDefaultsCreatesBothFilesWithDefaults() throws { + func testDefaultConfigFilePassesTheRulesOfPureMac111() throws { let config = directory.appendingPathComponent("puremac/config.json") let ignore = directory.appendingPathComponent("puremac/ignore") - try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + let projects = directory.appendingPathComponent("puremac/projects") + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects) + var store = try ConfigStore(fileURL: config) + try store.set("purge.older_than_days", "30") - let store = try ConfigStore(fileURL: config) - XCTAssertEqual(store.olderThanDays, 7) - XCTAssertEqual(store.projectRoots, Purger.defaultRoots) - let saved = try String(contentsOf: config, encoding: .utf8) - XCTAssertTrue(saved.contains("purge.roots") && saved.contains("purge.older_than_days"), saved) - XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "") - XCTAssertEqual(try IgnoreStore(fileURL: ignore).roots, []) + let object = try JSONSerialization.jsonObject(with: Data(contentsOf: config)) + let values = try XCTUnwrap(object as? [String: String]) + XCTAssertEqual(Set(values.keys), ["purge.older_than_days"]) + XCTAssertEqual(values["purge.older_than_days"], "30") } func testEnsureDefaultsNeverOverwritesExistingFiles() throws { let config = directory.appendingPathComponent("puremac/config.json") let ignore = directory.appendingPathComponent("puremac/ignore") + let projects = directory.appendingPathComponent("puremac/projects") try write(#"{"purge.older_than_days": "14"}"#, to: config) try write("/tmp/keep\n", to: ignore) + try write("/tmp/mine\n", to: projects) - try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) - try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects) XCTAssertEqual(try String(contentsOf: config, encoding: .utf8), #"{"purge.older_than_days": "14"}"#) XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "/tmp/keep\n") + XCTAssertEqual(try String(contentsOf: projects, encoding: .utf8), "/tmp/mine\n") } func testEnsureDefaultsFillsOnlyTheMissingFile() throws { let config = directory.appendingPathComponent("puremac/config.json") let ignore = directory.appendingPathComponent("puremac/ignore") + let projects = directory.appendingPathComponent("puremac/projects") try write("/tmp/keep\n", to: ignore) - try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects) XCTAssertTrue(FileManager.default.fileExists(atPath: config.path)) XCTAssertEqual(try String(contentsOf: ignore, encoding: .utf8), "/tmp/keep\n") + XCTAssertTrue(FileManager.default.fileExists(atPath: projects.path)) } func testEnsureDefaultsLeavesAnInvalidConfigFileAlone() throws { let config = directory.appendingPathComponent("puremac/config.json") let ignore = directory.appendingPathComponent("puremac/ignore") + let projects = directory.appendingPathComponent("puremac/projects") try write("[]", to: config) - try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore) + try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects) XCTAssertEqual(try String(contentsOf: config, encoding: .utf8), "[]") } @@ -177,8 +147,10 @@ final class ConfigSettingsTests: XCTestCase { try write("x", to: blocker) let config = blocker.appendingPathComponent("config.json") let ignore = directory.appendingPathComponent("puremac/ignore") - XCTAssertThrowsError(try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore)) + let projects = directory.appendingPathComponent("puremac/projects") + XCTAssertThrowsError(try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects)) XCTAssertTrue(FileManager.default.fileExists(atPath: ignore.path)) + XCTAssertTrue(FileManager.default.fileExists(atPath: projects.path)) } func testEnsureDefaultsCreatesTheConfigFileEvenWhenTheIgnoreFileFails() throws { @@ -186,8 +158,10 @@ final class ConfigSettingsTests: XCTestCase { try write("x", to: blocker) let config = directory.appendingPathComponent("puremac/config.json") let ignore = blocker.appendingPathComponent("ignore") - XCTAssertThrowsError(try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore)) + let projects = directory.appendingPathComponent("puremac/projects") + XCTAssertThrowsError(try AppPaths.ensureDefaults(configFile: config, ignoreFile: ignore, projectsFile: projects)) XCTAssertTrue(FileManager.default.fileExists(atPath: config.path)) + XCTAssertTrue(FileManager.default.fileExists(atPath: projects.path)) } func testTheWorkspaceEntryPointCreatesNothingWithoutATerminal() throws { @@ -199,8 +173,7 @@ final class ConfigSettingsTests: XCTestCase { func testPurgeWithAnEmptyFolderListSaysSoAndDoesNotScan() throws { try withConfigHome { _ in - var store = try ConfigStore(fileURL: AppPaths.configFile) - try store.setProjectRoots([]) + try write("", to: AppPaths.projectsFile) let output = try captureStdout { try Purge.parse(["--dry-run"]).run() } XCTAssertEqual(output, Term.dim(Purge.noFoldersMessage) + "\n") } @@ -220,8 +193,7 @@ final class ConfigSettingsTests: XCTestCase { func testPurgeWithoutPathsScansTheConfiguredRoots() throws { try withConfigHome { _ in - var store = try ConfigStore(fileURL: AppPaths.configFile) - try store.setProjectRoots(["/tmp/one", "/tmp/two"]) + try write("/tmp/one\n/tmp/two\n", to: AppPaths.projectsFile) XCTAssertEqual(try Purge.parse([]).resolvedRoots(), ["/tmp/one", "/tmp/two"]) } } @@ -232,9 +204,9 @@ final class ConfigSettingsTests: XCTestCase { } } - func testPurgeWithExplicitPathsIgnoresTheConfigFile() throws { + func testPurgeWithExplicitPathsIgnoresTheProjectsFile() throws { try withConfigHome { _ in - try write("[]", to: AppPaths.configFile) + try write("[]", to: AppPaths.projectsFile) let explicit = directory.appendingPathComponent("explicit") try FileManager.default.createDirectory(at: explicit, withIntermediateDirectories: true) let roots = try Purge.parse([explicit.path + "/../explicit"]).resolvedRoots() @@ -244,8 +216,7 @@ final class ConfigSettingsTests: XCTestCase { func testConfigPlainOutputListsProjectFoldersAfterTheFiles() throws { try withConfigHome { dir in - var store = try ConfigStore(fileURL: AppPaths.configFile) - try store.setProjectRoots(["\(Safety.home)/Work", "/tmp/other"]) + try write("\(Safety.home)/Work\n/tmp/other\n", to: AppPaths.projectsFile) let output = try captureStdout { try Config.parse([]).run() } XCTAssertEqual(output, """ PureMac CLI settings @@ -256,6 +227,7 @@ final class ConfigSettingsTests: XCTestCase { Files Settings \(dir.path)/config.json Protected \(dir.path)/ignore + Projects \(dir.path)/projects Project folders ~/Work @@ -276,19 +248,4 @@ final class ConfigSettingsTests: XCTestCase { XCTAssertTrue(changed.contains("8 days saved"), changed) } } - - func testSavedFileKeepsSlashesUnescaped() throws { - var store = try ConfigStore(fileURL: file) - try store.setProjectRoots(["/Users/me/Projects"]) - let text = try String(contentsOf: file, encoding: .utf8) - XCTAssertTrue(text.contains("\"/Users/me/Projects\""), text) - XCTAssertFalse(text.contains("\\/"), text) - XCTAssertEqual(try ConfigStore(fileURL: file).projectRoots, ["/Users/me/Projects"]) - } - - func testDefaultFileKeepsSlashesUnescaped() throws { - let text = String(decoding: try ConfigStore.defaultFileData(), as: UTF8.self) - XCTAssertTrue(text.contains("\"\(Safety.home)/Projects\""), text) - XCTAssertFalse(text.contains("\\/"), text) - } } diff --git a/cli/Tests/puremacTests/PathListEditorTests.swift b/cli/Tests/puremacTests/PathListEditorTests.swift index ebf58f4..4f68871 100644 --- a/cli/Tests/puremacTests/PathListEditorTests.swift +++ b/cli/Tests/puremacTests/PathListEditorTests.swift @@ -488,11 +488,11 @@ final class ProjectFoldersTests: XCTestCase { try? FileManager.default.removeItem(at: root) } - func testAddSavesTheStandardizedFolderThroughTheConfigFile() throws { + func testAddSavesTheStandardizedFolderThroughTheProjectsFile() throws { try withConfigHome { _ in let config = PathListConfig.projectFolders try config.add(folder.path + "/") - XCTAssertEqual(try ConfigStore(fileURL: AppPaths.configFile).projectRoots, Purger.defaultRoots + [folder.path]) + XCTAssertEqual(try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots, Purger.defaultRoots + [folder.path]) XCTAssertEqual(try config.load(), Purger.defaultRoots + [folder.path]) } } diff --git a/cli/Tests/puremacTests/PreferencesScreenTests.swift b/cli/Tests/puremacTests/PreferencesScreenTests.swift index 455ad08..03cbd9e 100644 --- a/cli/Tests/puremacTests/PreferencesScreenTests.swift +++ b/cli/Tests/puremacTests/PreferencesScreenTests.swift @@ -126,8 +126,7 @@ final class PreferencesScreenTests: XCTestCase { var screen = PreferencesScreen() var ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) _ = try ignore.add("/tmp/puremac-a") - var store = try ConfigStore(fileURL: AppPaths.configFile) - try store.setProjectRoots(["/tmp/puremac-x"]) + try Data("/tmp/puremac-x\n".utf8).write(to: AppPaths.projectsFile) screen.reload() XCTAssertEqual(screen.pathCount, 1) XCTAssertEqual(screen.folderCount, 1) @@ -156,7 +155,7 @@ final class PreferencesScreenTests: XCTestCase { var ignore = try IgnoreStore(fileURL: AppPaths.ignoreFile) _ = try ignore.add("/tmp/puremac-a") var store = try ConfigStore(fileURL: AppPaths.configFile) - try store.setProjectRoots(["/tmp/puremac-x"]) + try Data("/tmp/puremac-x\n".utf8).write(to: AppPaths.projectsFile) try store.set(ConfigStore.daysKey, "1") let text = lines(PreferencesScreen()).joined(separator: "\n") XCTAssertTrue(text.contains("‹ 1 day ›"), text) @@ -217,6 +216,20 @@ final class PreferencesScreenTests: XCTestCase { } } + func testUnreadableProjectsFileShowsARedRowAndKeepsTheDefaultCount() throws { + try withConfigHome { dir in + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + try Data("relative\n".utf8).write(to: AppPaths.projectsFile) + let screen = PreferencesScreen() + let buffer = screen.render(width: 160, height: 24) + let rows = buffer.plainLines() + let index = try XCTUnwrap(rows.firstIndex { $0.contains("Project folders file contains an invalid or relative path") }) + XCTAssertEqual(buffer[2, index].style, TextStyle(color: .red)) + XCTAssertEqual(screen.folderCount, Purger.defaultRoots.count) + XCTAssertEqual(screen.days, 7) + } + } + func testFailedSaveShowsAYellowRowUntilTheNextKey() throws { try withConfigHome { dir in try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) diff --git a/cli/Tests/puremacTests/PreferencesSheetTests.swift b/cli/Tests/puremacTests/PreferencesSheetTests.swift index f883877..c3ef8c3 100644 --- a/cli/Tests/puremacTests/PreferencesSheetTests.swift +++ b/cli/Tests/puremacTests/PreferencesSheetTests.swift @@ -16,6 +16,7 @@ final class PlainCommandOutputTests: XCTestCase { Files Settings \(dir.path)/config.json Protected \(dir.path)/ignore + Projects \(dir.path)/projects Project folders \(Purger.defaultRoots.map { " " + Render.shorten($0) + "\n" }.joined()) @@ -70,7 +71,7 @@ final class PreferencesSheetTests: XCTestCase { func testPreferencesSheetListsKeysWithValueAndNote() throws { try withConfigHome { dir in var store = try ConfigStore(fileURL: AppPaths.configFile) - var sheet = Config.sheet(store: store) + var sheet = Config.sheet(store: store, projectFolders: Purger.defaultRoots) XCTAssertEqual(sheet.title, "PureMac CLI settings") XCTAssertEqual(sheet.subtitle, "Values used when a command-line option is omitted") XCTAssertEqual(sheet.sections.map(\.title), [nil, "Files", "Project folders"]) @@ -79,14 +80,16 @@ final class PreferencesSheetTests: XCTestCase { XCTAssertEqual(note, Span("default", dim)) try store.set("purge.older_than_days", "14") - sheet = Config.sheet(store: store) + sheet = Config.sheet(store: store, projectFolders: Purger.defaultRoots) guard case .metric(_, let saved, let savedNote) = sheet.sections[0].rows[0] else { return XCTFail("key row") } XCTAssertEqual(saved, [Span("14 days")]) XCTAssertEqual(savedNote, Span("saved", TextStyle(color: .cyan))) - XCTAssertEqual(sheet.sections[1].rows.count, 2) + XCTAssertEqual(sheet.sections[1].rows.count, 3) guard case .metric("Settings", let settings, nil) = sheet.sections[1].rows[0] else { return XCTFail("settings row") } XCTAssertEqual(settings, [Span("\(dir.path)/config.json")]) + guard case .metric("Projects", let projects, nil) = sheet.sections[1].rows[2] else { return XCTFail("projects row") } + XCTAssertEqual(projects, [Span("\(dir.path)/projects")]) } } diff --git a/cli/Tests/puremacTests/ProjectFoldersStoreTests.swift b/cli/Tests/puremacTests/ProjectFoldersStoreTests.swift new file mode 100644 index 0000000..b08df90 --- /dev/null +++ b/cli/Tests/puremacTests/ProjectFoldersStoreTests.swift @@ -0,0 +1,114 @@ +import Foundation +import XCTest +@testable import puremac + +final class ProjectFoldersStoreTests: XCTestCase { + private var directory: URL! + private var file: URL { directory.appendingPathComponent("puremac/projects") } + + override func setUpWithError() throws { + directory = FileManager.default.temporaryDirectory + .appendingPathComponent("puremac-projects-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + } + + override func tearDown() { + try? FileManager.default.removeItem(at: directory) + } + + private func write(_ text: String) throws { + try FileManager.default.createDirectory(at: file.deletingLastPathComponent(), withIntermediateDirectories: true) + try Data(text.utf8).write(to: file) + } + + func testMissingFileMeansTheDefaultFolders() throws { + XCTAssertEqual(try ProjectFoldersStore(fileURL: file).roots, Purger.defaultRoots) + } + + func testEmptyFileMeansNoFolders() throws { + try write("") + XCTAssertEqual(try ProjectFoldersStore(fileURL: file).roots, []) + } + + func testLoadKeepsFileOrderAndDropsDuplicates() throws { + try write("/tmp/b\n/tmp/a/../a\n/tmp/b/\n") + XCTAssertEqual(try ProjectFoldersStore(fileURL: file).roots, ["/tmp/b", "/tmp/a"]) + } + + func testInvalidLinesAreAnInvalidProjectsFile() throws { + for text in ["relative/path\n", "/\n", "/tmp/a\n\u{0}\n"] { + try write(text) + XCTAssertThrowsError(try ProjectFoldersStore(fileURL: file), text) { error in + guard case StoreError.invalidProjectsFile(file.path) = error else { return XCTFail("\(text): \(error)") } + } + } + } + + func testInvalidFileMessageNamesTheProjectsFile() { + XCTAssertEqual( + StoreError.invalidProjectsFile("/x/projects").errorDescription, + "Project folders file contains an invalid or relative path: /x/projects" + ) + } + + func testAddAppendsInOrderAndRoundTrips() throws { + try write("/tmp/z\n") + var store = try ProjectFoldersStore(fileURL: file) + XCTAssertTrue(try store.add("/tmp/m/")) + XCTAssertEqual(store.roots, ["/tmp/z", "/tmp/m"]) + XCTAssertEqual(try String(contentsOf: file, encoding: .utf8), "/tmp/z\n/tmp/m\n") + XCTAssertEqual(try ProjectFoldersStore(fileURL: file).roots, ["/tmp/z", "/tmp/m"]) + } + + func testAddToAMissingFileKeepsTheDefaultsAndWritesThem() throws { + var store = try ProjectFoldersStore(fileURL: file) + XCTAssertTrue(try store.add("/tmp/new")) + XCTAssertEqual(try ProjectFoldersStore(fileURL: file).roots, Purger.defaultRoots + ["/tmp/new"]) + } + + func testAddingADuplicateChangesNothing() throws { + try write("/tmp/a\n") + var store = try ProjectFoldersStore(fileURL: file) + XCTAssertFalse(try store.add("/tmp/b/../a")) + XCTAssertEqual(try String(contentsOf: file, encoding: .utf8), "/tmp/a\n") + } + + func testRelativeFoldersAreRejectedAndNothingIsSaved() throws { + var store = try ProjectFoldersStore(fileURL: file) + XCTAssertThrowsError(try store.add("relative")) { error in + guard case StoreError.invalidProjectRoot("relative") = error else { return XCTFail("\(error)") } + } + XCTAssertEqual(store.roots, Purger.defaultRoots) + XCTAssertFalse(FileManager.default.fileExists(atPath: file.path)) + } + + func testInvalidProjectRootMessageNamesTheFolder() { + XCTAssertEqual( + StoreError.invalidProjectRoot("relative").errorDescription, + "Project folders must be absolute paths: relative" + ) + } + + func testRemoveDropsTheFolderAndTheLastRemovalLeavesAnEmptyFile() throws { + try write("/tmp/a\n/tmp/b\n") + var store = try ProjectFoldersStore(fileURL: file) + XCTAssertTrue(try store.remove("/tmp/a")) + XCTAssertFalse(try store.remove("/tmp/a")) + XCTAssertTrue(try store.remove("/tmp/b")) + XCTAssertEqual(try String(contentsOf: file, encoding: .utf8), "") + XCTAssertEqual(try ProjectFoldersStore(fileURL: file).roots, []) + } + + func testFailedSaveKeepsTheFoldersInMemory() throws { + let blocker = directory.appendingPathComponent("blocker") + try Data("x".utf8).write(to: blocker) + var store = try ProjectFoldersStore(fileURL: blocker.appendingPathComponent("projects")) + XCTAssertThrowsError(try store.add("/tmp/a")) + XCTAssertEqual(store.roots, Purger.defaultRoots) + } + + func testProjectsFileLivesNextToConfigJson() { + XCTAssertEqual(AppPaths.projectsFile.lastPathComponent, "projects") + XCTAssertEqual(AppPaths.projectsFile.deletingLastPathComponent(), AppPaths.configDir) + } +} From 4e86f07a2ac6ffbc3e24f8943c3c93e11d9b945e Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 16:25:09 +0000 Subject: [PATCH 20/21] fix(cli): apply final review fixes for cancel, input, help text and dialog wrapping --- cli/Sources/TerminalUI/Dialog.swift | 6 +- cli/Sources/TerminalUI/KeyInput.swift | 34 ++++++ cli/Sources/TerminalUI/Term.swift | 9 +- cli/Sources/TerminalUI/TerminalSession.swift | 30 ++--- cli/Sources/TerminalUI/TextInput.swift | 6 +- cli/Sources/puremac/Commands/Analyze.swift | 28 +++-- cli/Sources/puremac/Commands/Clean.swift | 2 +- cli/Sources/puremac/Commands/Ignore.swift | 8 +- cli/Sources/puremac/Commands/Purge.swift | 2 +- .../puremac/Core/CategoryScanner.swift | 8 +- cli/Sources/puremac/Core/CleanupFlow.swift | 16 ++- cli/Sources/puremac/Core/InfoSheet.swift | 24 ---- .../puremac/Core/InteractiveReview.swift | 2 +- cli/Sources/puremac/Core/PathListEditor.swift | 4 +- .../puremac/Core/PreferencesScreen.swift | 6 +- cli/Sources/puremac/Core/Purger.swift | 2 +- cli/Sources/puremac/Core/Render.swift | 7 +- cli/Sources/puremac/Core/Scanner.swift | 9 +- .../puremac/Core/StartConfirmation.swift | 14 ++- cli/Sources/puremac/Core/StatusScreen.swift | 1 + cli/Sources/puremac/Core/SystemInfo.swift | 4 +- .../puremac/Core/SystemStatusScreen.swift | 26 +++++ cli/Sources/puremac/PureMac.swift | 34 ++++-- cli/Tests/TerminalUITests/DialogTests.swift | 14 +++ cli/Tests/TerminalUITests/KeyInputTests.swift | 68 +++++++++++ cli/Tests/TerminalUITests/TermTests.swift | 17 +++ cli/Tests/puremacTests/AnalyzeTests.swift | 48 ++++++-- .../puremacTests/CategoryScannerTests.swift | 109 ++++++++++++++++++ cli/Tests/puremacTests/CleanupFlowTests.swift | 7 ++ .../puremacTests/CommandReviewTests.swift | 9 ++ cli/Tests/puremacTests/CoreSafetyTests.swift | 35 ++++++ cli/Tests/puremacTests/InfoSheetTests.swift | 36 ------ .../puremacTests/PathListEditorTests.swift | 29 ++++- ...ts.swift => PlainCommandOutputTests.swift} | 10 -- cli/Tests/puremacTests/PurgerScanTests.swift | 14 +++ .../puremacTests/ScanProgressTests.swift | 70 ----------- .../puremacTests/StartConfirmationTests.swift | 60 +++++++++- .../puremacTests/StatusScreenTests.swift | 13 ++- .../SystemStatusScreenTests.swift | 36 ++++++ cli/Tests/puremacTests/puremacTests.swift | 6 + 40 files changed, 619 insertions(+), 244 deletions(-) create mode 100644 cli/Sources/TerminalUI/KeyInput.swift create mode 100644 cli/Tests/TerminalUITests/KeyInputTests.swift create mode 100644 cli/Tests/puremacTests/CategoryScannerTests.swift rename cli/Tests/puremacTests/{PreferencesSheetTests.swift => PlainCommandOutputTests.swift} (90%) diff --git a/cli/Sources/TerminalUI/Dialog.swift b/cli/Sources/TerminalUI/Dialog.swift index fabddfc..87f7b65 100644 --- a/cli/Sources/TerminalUI/Dialog.swift +++ b/cli/Sources/TerminalUI/Dialog.swift @@ -134,7 +134,7 @@ public struct Dialog { let buttonRows = self.buttonRows(width: contentWidth).count let tailRows = buttonRows + hintRows let wrapped = message.flatMap { paragraph in - Term.wordWrap(paragraph.text, width: contentWidth).map { Span($0, paragraph.style) } + wrap(paragraph.text, width: contentWidth).map { Span($0, paragraph.style) } } var layout = Layout(messageRows: wrapped, hintRows: hintRows, buttonRows: buttonRows) let hasGroups = !wrapped.isEmpty || tailRows > 0 @@ -150,6 +150,10 @@ public struct Dialog { return layout } + private func wrap(_ text: String, width: Int) -> [String] { + messageAlignment == .center ? Term.balancedWrap(text, width: width) : Term.wordWrap(text, width: width) + } + private func renderCentered(_ spans: [Span], in content: Rect, row: Int, buffer: inout Buffer) { let width = Term.displayWidth(spans) let column = content.x + max(0, content.width - width) / 2 diff --git a/cli/Sources/TerminalUI/KeyInput.swift b/cli/Sources/TerminalUI/KeyInput.swift new file mode 100644 index 0000000..96784f4 --- /dev/null +++ b/cli/Sources/TerminalUI/KeyInput.swift @@ -0,0 +1,34 @@ +import Darwin + +final class KeyInput { + private let descriptor: Int32 + private(set) var isClosed = false + + init(descriptor: Int32 = STDIN_FILENO) { + self.descriptor = descriptor + } + + func readByte() -> UInt8? { + var byte: UInt8 = 0 + while true { + let result = Darwin.read(descriptor, &byte, 1) + if result == 1 { return byte } + if result == -1 && errno == EINTR { continue } + isClosed = true + return nil + } + } + + func wait(milliseconds: Int32) -> Bool { + guard !isClosed else { + _ = poll(nil, 0, milliseconds) + return true + } + return available(milliseconds: milliseconds) + } + + func available(milliseconds: Int32) -> Bool { + var pollDescriptor = pollfd(fd: descriptor, events: Int16(POLLIN), revents: 0) + return poll(&pollDescriptor, 1, milliseconds) > 0 + } +} diff --git a/cli/Sources/TerminalUI/Term.swift b/cli/Sources/TerminalUI/Term.swift index 5c1e547..3dc9e1d 100644 --- a/cli/Sources/TerminalUI/Term.swift +++ b/cli/Sources/TerminalUI/Term.swift @@ -144,10 +144,17 @@ extension Term { return (lines + [last]).map { String($0.map(\.character)) } } - public static func wordWrap(_ string: String, width: Int) -> [String] { + static func wordWrap(_ string: String, width: Int) -> [String] { wordWrap([Span(string)], width: width).map { $0.map(\.text).joined() } } + static func balancedWrap(_ string: String, width: Int) -> [String] { + let lineCount = wordWrap(string, width: width).count + let widestWord = string.split(whereSeparator: \.isWhitespace).map { displayWidth(String($0)) }.max() ?? 1 + let narrowest = (min(max(1, width), widestWord)...max(1, width)).first { wordWrap(string, width: $0).count == lineCount } ?? width + return wordWrap(string, width: narrowest) + } + public static func wordWrap(_ spans: [Span], width: Int) -> [[Span]] { var lines: [[StyledCharacter]] = [] var current: [StyledCharacter] = [] diff --git a/cli/Sources/TerminalUI/TerminalSession.swift b/cli/Sources/TerminalUI/TerminalSession.swift index 5c73f28..487fad8 100644 --- a/cli/Sources/TerminalUI/TerminalSession.swift +++ b/cli/Sources/TerminalUI/TerminalSession.swift @@ -84,6 +84,7 @@ public final class TerminalSession { } private var isClosed = false + private let input = KeyInput() public var width: Int { terminalDimensions().width @@ -151,14 +152,16 @@ public final class TerminalSession { } public func readKey() -> TerminalKey { - guard !isClosed, let first = readByte() else { return .escape } + guard !isClosed, let first = input.readByte() else { return .escape } if let key = Self.key(forSimpleByte: first) { return key } return first == 0x1B ? readEscapeSequence() : decodeCharacter(firstByte: first) } public func readKey(timeoutMilliseconds: Int) -> TerminalKey? { - guard !isClosed, inputAvailable(milliseconds: Int32(clamping: timeoutMilliseconds)) else { return nil } + guard !isClosed else { return nil } + let milliseconds = Int32(clamping: timeoutMilliseconds) + guard input.wait(milliseconds: milliseconds) else { return nil } return readKey() } @@ -188,13 +191,13 @@ public final class TerminalSession { } private func readEscapeSequence() -> TerminalKey { - guard inputAvailable(milliseconds: 24), let second = readByte() else { + guard input.available(milliseconds: 24), let second = input.readByte() else { return .escape } guard second == 0x5B || second == 0x4F else { return .escape } - guard inputAvailable(milliseconds: 24), let third = readByte() else { + guard input.available(milliseconds: 24), let third = input.readByte() else { return .escape } @@ -206,7 +209,7 @@ public final class TerminalSession { case 0x48: return .home case 0x46: return .end case 0x31, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38: - guard inputAvailable(milliseconds: 24), let fourth = readByte(), fourth == 0x7E else { + guard input.available(milliseconds: 24), let fourth = input.readByte(), fourth == 0x7E else { return .unknown } switch third { @@ -234,7 +237,7 @@ public final class TerminalSession { var bytes = [firstByte] while bytes.count < expectedCount { - guard inputAvailable(milliseconds: 24), let byte = readByte() else { + guard input.available(milliseconds: 24), let byte = input.readByte() else { return .unknown } bytes.append(byte) @@ -246,21 +249,6 @@ public final class TerminalSession { return .character(character) } - private func readByte() -> UInt8? { - var byte: UInt8 = 0 - while true { - let result = Darwin.read(STDIN_FILENO, &byte, 1) - if result == 1 { return byte } - if result == -1 && errno == EINTR { continue } - return nil - } - } - - private func inputAvailable(milliseconds: Int32) -> Bool { - var descriptor = pollfd(fd: STDIN_FILENO, events: Int16(POLLIN), revents: 0) - return poll(&descriptor, 1, milliseconds) > 0 - } - private func terminalDimensions() -> (width: Int, height: Int) { var window = winsize() guard ioctl(STDOUT_FILENO, TIOCGWINSZ, &window) == 0 else { diff --git a/cli/Sources/TerminalUI/TextInput.swift b/cli/Sources/TerminalUI/TextInput.swift index 95348ee..3b7f6c0 100644 --- a/cli/Sources/TerminalUI/TextInput.swift +++ b/cli/Sources/TerminalUI/TextInput.swift @@ -5,13 +5,13 @@ public struct TextInput: Equatable { self.text = text } - public var isEmpty: Bool { text.isEmpty } + var isEmpty: Bool { text.isEmpty } - public mutating func insert(_ character: Character) { + mutating func insert(_ character: Character) { text.append(character) } - public mutating func backspace() { + mutating func backspace() { text = String(text.dropLast()) } diff --git a/cli/Sources/puremac/Commands/Analyze.swift b/cli/Sources/puremac/Commands/Analyze.swift index 9b8c823..3964595 100644 --- a/cli/Sources/puremac/Commands/Analyze.swift +++ b/cli/Sources/puremac/Commands/Analyze.swift @@ -102,7 +102,7 @@ struct Analyze: ParsableCommand { case measured(Child) } - struct ScanProgress { + struct MeasureProgress { let path: String var position = 0 var count = 0 @@ -163,7 +163,9 @@ struct Analyze: ParsableCommand { isDirectory: kind.isDirectory, isPackage: kind.isPackage )) } - if let child = measureChild(url, ignore: ignore, context: &context) { + let measured = measureChild(url, ignore: ignore, context: &context, isCancelled: isCancelled) + if isCancelled() { break } + if let child = measured { children.append(child) progress?(.measured(child)) } @@ -200,13 +202,15 @@ struct Analyze: ParsableCommand { return (isDirectory, isDirectory && values?.isPackage == true) } - private func measureChild(_ topURL: URL, ignore: IgnoreStore, context: inout MeasureContext) -> Child? { + private func measureChild( + _ topURL: URL, ignore: IgnoreStore, context: inout MeasureContext, isCancelled: () -> Bool + ) -> Child? { let path = topURL.path if Safety.ignoredPathProtectsCandidate(path, ignore: ignore) { context.skippedCount += 1 return nil } - let measurement = DirSizer.measure(of: path) + let measurement = DirSizer.measure(of: path, isCancelled: isCancelled) switch measurement.status { case .symlink, .cloudOrDataless: context.skippedCount += max(1, measurement.skippedEntries) @@ -355,17 +359,19 @@ struct Analyze: ParsableCommand { private func measure(_ path: String, ignore: IgnoreStore, session: TerminalSession, drillingDown: Bool) -> MeasureResult { var exitRequested = false + var isCancelling = false let snapshot = session.runWithSpinner( - progress: ScanProgress(path: (path as NSString).standardizingPath), + progress: MeasureProgress(path: (path as NSString).standardizingPath), render: { tick, progress in Self.renderMeasuringBrowser( - progress: progress, tick: tick, drillingDown: drillingDown, + progress: progress, tick: tick, drillingDown: drillingDown, isCancelling: isCancelling, width: session.width, height: session.height ) }, onKey: { key, cancel in guard let action = Self.measuringKeyAction(key, drillingDown: drillingDown) else { return } if action == .exit { exitRequested = true } + isCancelling = true cancel.cancel() }, work: { progress, cancel in @@ -458,14 +464,16 @@ struct Analyze: ParsableCommand { private struct Measuring { let tick: Int - let progress: ScanProgress + let progress: MeasureProgress let drillingDown: Bool + let isCancelling: Bool var hints: KeyHints { drillingDown ? drillDownHints : firstScanHints } var exitHint: String { drillingDown ? "Esc back q exit" : exitText } var statusSpans: [Span] { - let status = progress.position == 0 ? "Measuring…" : "Measuring \(progress.position) of \(progress.count)" + let status = isCancelling ? StatusScreen.cancellingText + : progress.position == 0 ? "Measuring…" : "Measuring \(progress.position) of \(progress.count)" return [Span(Spinner.frame(tick: tick) + " " + status, TextStyle(dim: true))] } @@ -478,7 +486,7 @@ struct Analyze: ParsableCommand { } static func renderMeasuringBrowser( - progress: ScanProgress, tick: Int, drillingDown: Bool, width: Int, height: Int + progress: MeasureProgress, tick: Int, drillingDown: Bool, isCancelling: Bool = false, width: Int, height: Int ) -> Buffer { let children = ranked(progress.measured) let snapshot = FolderSnapshot( @@ -491,7 +499,7 @@ struct Analyze: ParsableCommand { ) return render( level: BrowserLevel(snapshot: snapshot, selected: -1), - measuring: Measuring(tick: tick, progress: progress, drillingDown: drillingDown), + measuring: Measuring(tick: tick, progress: progress, drillingDown: drillingDown, isCancelling: isCancelling), width: width, height: height ) diff --git a/cli/Sources/puremac/Commands/Clean.swift b/cli/Sources/puremac/Commands/Clean.swift index d96560c..a6166f6 100644 --- a/cli/Sources/puremac/Commands/Clean.swift +++ b/cli/Sources/puremac/Commands/Clean.swift @@ -13,7 +13,7 @@ struct Clean: ParsableCommand { puremac clean ai AI-tool caches & logs only puremac clean trash Empty user + mounted-volume Trash - Interactive review starts with every item unselected. Finishing the selector only opens an exact deletion review; a separate confirmation defaults to No. --plain uses a numbered selector with ranges, all, and none. --force removes the scanner's standard preselection without either prompt. --dry-run and --json never delete or open a selector. + Interactive review starts with every item unselected. \(Render.reviewHelp) --force removes the scanner's standard preselection without either prompt. --dry-run and --json never delete or open a selector. """ ) diff --git a/cli/Sources/puremac/Commands/Ignore.swift b/cli/Sources/puremac/Commands/Ignore.swift index d66f0f9..c161135 100644 --- a/cli/Sources/puremac/Commands/Ignore.swift +++ b/cli/Sources/puremac/Commands/Ignore.swift @@ -33,7 +33,6 @@ struct Ignore: ParsableCommand { struct List: ParsableCommand { static let configuration = CommandConfiguration(abstract: "Show protected paths.") - static let sheetTitle = "Protected paths" func run() throws { let store = try IgnoreStore(fileURL: AppPaths.ignoreFile) @@ -42,7 +41,7 @@ struct Ignore: ParsableCommand { return } print(Term.bold("Protected paths:")) - for line in Self.sheet(roots: store.roots).plainLines(withHeader: false) { print(line) } + for root in store.roots.sorted() { print(" " + Render.shorten(root)) } } static func emptyHint() -> [Span] { @@ -52,10 +51,5 @@ struct Ignore: ParsableCommand { Span("`.", TextStyle(dim: true)), ] } - - static func sheet(roots: [String]) -> InfoSheet { - let rows: [InfoRow] = roots.sorted().map { .path(Render.shorten($0)) } - return InfoSheet(title: sheetTitle, subtitle: nil, sections: [InfoSection(title: nil, rows: rows)], footnote: nil) - } } } diff --git a/cli/Sources/puremac/Commands/Purge.swift b/cli/Sources/puremac/Commands/Purge.swift index 89b248a..821367a 100644 --- a/cli/Sources/puremac/Commands/Purge.swift +++ b/cli/Sources/puremac/Commands/Purge.swift @@ -11,7 +11,7 @@ struct Purge: ParsableCommand { puremac purge Scan the configured project folders puremac purge ~/Work/app Scan a specific folder - Finishing the selector only opens an exact deletion review; a separate confirmation defaults to No. --plain uses a numbered selector with ranges, all, and none. --force removes only artifacts older than the configured threshold without either prompt. --dry-run and --json never delete or open a selector. + \(Render.reviewHelp) --force removes only artifacts older than the configured threshold without either prompt. --dry-run and --json never delete or open a selector. """ ) diff --git a/cli/Sources/puremac/Core/CategoryScanner.swift b/cli/Sources/puremac/Core/CategoryScanner.swift index 184f4d6..485b559 100644 --- a/cli/Sources/puremac/Core/CategoryScanner.swift +++ b/cli/Sources/puremac/Core/CategoryScanner.swift @@ -47,7 +47,7 @@ enum CategoryScanner { } candidates = uniqueCandidates(candidates) if isCancelled() { return [] } - let measurements = concurrentMeasurements(candidates.map { $0.path }) + let measurements = concurrentMeasurements(candidates.map { $0.path }, isCancelled: isCancelled) var itemsByTarget = [Int: [ScanItem]](minimumCapacity: targets.count) for (i, c) in candidates.enumerated() @@ -81,7 +81,7 @@ enum CategoryScanner { concurrentMeasurements(paths).map(\.bytes) } - static func concurrentMeasurements(_ paths: [String]) -> [DirSizer.Measurement] { + static func concurrentMeasurements(_ paths: [String], isCancelled: () -> Bool = { false }) -> [DirSizer.Measurement] { guard !paths.isEmpty else { return [] } var out = [DirSizer.Measurement]( repeating: DirSizer.Measurement(bytes: 0, status: .unavailable, skippedEntries: 1), @@ -89,7 +89,7 @@ enum CategoryScanner { ) out.withUnsafeMutableBufferPointer { buf in DispatchQueue.concurrentPerform(iterations: paths.count) { i in - buf[i] = DirSizer.measure(of: paths[i]) + buf[i] = DirSizer.measure(of: paths[i], isCancelled: isCancelled) } } return out @@ -136,7 +136,7 @@ enum CategoryScanner { guard let children = try? fm.contentsOfDirectory(atPath: root), !children.isEmpty else { continue } let paths = children.map { "\(root)/\($0)" }.filter { passesPreFilter($0, ignore: ignore) } let unique = uniqueCandidates(paths.map { (target: 0, path: $0) }) - let measurements = concurrentMeasurements(unique.map(\.path)) + let measurements = concurrentMeasurements(unique.map(\.path), isCancelled: isCancelled) let items = zip(unique.map(\.path), measurements).compactMap { (path, measurement) -> ScanItem? in measurement.status == .complete && measurement.bytes >= minSize ? ScanItem(path: path, sizeBytes: measurement.bytes, modified: DirSizer.modified(of: path)) diff --git a/cli/Sources/puremac/Core/CleanupFlow.swift b/cli/Sources/puremac/Core/CleanupFlow.swift index 9858d95..c0a610b 100644 --- a/cli/Sources/puremac/Core/CleanupFlow.swift +++ b/cli/Sources/puremac/Core/CleanupFlow.swift @@ -45,7 +45,9 @@ enum CleanupFlow { let categories = session.runWithSpinner( progress: labels.initialStatus, render: { tick, status in - scanningScreen(status: status, tick: tick, width: session.width, height: session.height) + scanningScreen( + status: status, tick: tick, isCancelling: scanCancelled, width: session.width, height: session.height + ) }, onKey: { key, cancel in if cancelsScan(key) { @@ -120,13 +122,13 @@ enum CleanupFlow { } } - static func scanningScreen(status: ScanStatus, tick: Int, width: Int, height: Int) -> Buffer { + static func scanningScreen(status: ScanStatus, tick: Int, isCancelling: Bool = false, width: Int, height: Int) -> Buffer { StatusScreen.render( title: "PureMac", rows: [ - StatusRow(Spinner.frame(tick: tick) + " " + status.headline, truncatesInMiddle: true), + StatusRow(Spinner.frame(tick: tick) + " " + (isCancelling ? StatusScreen.cancellingText : status.headline), truncatesInMiddle: true), StatusRow(status.folder.map(Render.shorten) ?? "", style: TextStyle(dim: true), truncatesInMiddle: true), - StatusRow("Found \(counted(status.foundCount, "item")) · \(ByteCount.human(status.foundBytes))") + StatusRow("Found \(Render.counted(status.foundCount, "item")) · \(ByteCount.human(status.foundBytes))") ], hint: StatusScreen.scanHint, width: width, @@ -169,17 +171,13 @@ enum CleanupFlow { ) } - static func counted(_ count: Int, _ noun: String) -> String { - "\(count) \(noun)\(count == 1 ? "" : "s")" - } - static func removingDialog(noun: String, progress: RemovalProgress, tick: Int, area: Rect) -> Dialog { let rowWidth = min(removingMaxContentWidth, Dialog.maxContentWidth(in: area)) let current = Term.truncate( Spinner.frame(tick: tick) + " " + Render.shorten(progress.path), to: rowWidth, middle: true ) return Dialog( - title: "Removing \(counted(progress.count, noun))…", + title: "Removing \(Render.counted(progress.count, noun))…", titleStyle: StatusScreen.warningTitle, borderStyle: StatusScreen.warningBorder, message: [ diff --git a/cli/Sources/puremac/Core/InfoSheet.swift b/cli/Sources/puremac/Core/InfoSheet.swift index 0a59ad7..c7bd1bf 100644 --- a/cli/Sources/puremac/Core/InfoSheet.swift +++ b/cli/Sources/puremac/Core/InfoSheet.swift @@ -61,15 +61,6 @@ struct InfoSheet { private static func wrapped(_ spans: [Span], indent: String, width: Int) -> [[Span]] { Term.wordWrap(spans, width: max(1, width - indent.count)).map { [Span(indent)] + $0 } } - - static func write(_ spans: [Span], in rect: Rect, buffer: inout Buffer) { - guard Term.displayWidth(spans) > rect.width else { - buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width) - return - } - let used = buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width - 1) - buffer.write("…", x: rect.x + used, y: rect.y) - } } struct InfoSection { @@ -84,18 +75,3 @@ enum InfoRow { case message([Span]) case path(String) } - -struct InfoSheetScroll { - private(set) var offset = 0 - - mutating func handle(_ key: TerminalKey, maxOffset: Int) -> Bool { - switch key { - case .up: offset = max(0, min(offset, maxOffset) - 1) - case .down: offset = min(maxOffset, offset + 1) - case .escape, .enter, .left, .backspace: return true - case .character(let character): return character.lowercased() == "q" - default: break - } - return false - } -} diff --git a/cli/Sources/puremac/Core/InteractiveReview.swift b/cli/Sources/puremac/Core/InteractiveReview.swift index 44fdf80..214e61f 100644 --- a/cli/Sources/puremac/Core/InteractiveReview.swift +++ b/cli/Sources/puremac/Core/InteractiveReview.swift @@ -396,7 +396,7 @@ enum InteractiveReview { var message = [Span("\(ByteCount.human(total)) will be deleted")] if hidden > 0 { message.append(Span("\(hidden) hidden by search", TextStyle(dim: true))) } return Dialog( - title: "Remove \(CleanupFlow.counted(count, noun))?", + title: "Remove \(Render.counted(count, noun))?", titleStyle: StatusScreen.warningTitle, borderStyle: StatusScreen.warningBorder, message: message, diff --git a/cli/Sources/puremac/Core/PathListEditor.swift b/cli/Sources/puremac/Core/PathListEditor.swift index 173ad1c..f9c2152 100644 --- a/cli/Sources/puremac/Core/PathListEditor.swift +++ b/cli/Sources/puremac/Core/PathListEditor.swift @@ -118,6 +118,7 @@ struct PathListEditor { func acceptsKey(_ key: TerminalKey, tooSmall: Bool) -> Bool { guard tooSmall else { return true } if let confirmation { + if case .character(let character) = key, ["n", "q"].contains(character.lowercased()) { return true } return key == .escape || (key == .enter && confirmation.index == Self.cancelIndex) } return key == .escape @@ -127,7 +128,7 @@ struct PathListEditor { switch key { case .up: move(-1) case .down: move(1) - case .escape, .left, .backspace, .delete: return true + case .escape, .left, .backspace: return true case .character(let character): switch character.lowercased() { case "q": return true @@ -165,6 +166,7 @@ struct PathListEditor { confirmation = nil if buttons.index == Self.removeIndex { removeFocused() } case .escape: confirmation = nil + case .character(let character) where ["n", "q"].contains(character.lowercased()): confirmation = nil default: break } } diff --git a/cli/Sources/puremac/Core/PreferencesScreen.swift b/cli/Sources/puremac/Core/PreferencesScreen.swift index f93e025..72563e4 100644 --- a/cli/Sources/puremac/Core/PreferencesScreen.swift +++ b/cli/Sources/puremac/Core/PreferencesScreen.swift @@ -36,7 +36,7 @@ struct PreferencesScreen { } private static func ageValue(_ days: Int) -> String { - "‹ \(CleanupFlow.counted(days, "day")) ›" + "‹ \(Render.counted(days, "day")) ›" } mutating func reload() { @@ -148,8 +148,8 @@ struct PreferencesScreen { private func listLines(width: Int) -> [[Span]] { let rows: [(row: Row, label: String, value: String)] = [ (.age, Self.ageLabel, Self.ageValue(days)), - (.projectFolders, Self.foldersLabel, "\(CleanupFlow.counted(folderCount, "folder")) ›"), - (.protectedPaths, Self.pathsLabel, "\(CleanupFlow.counted(pathCount, "path")) ›"), + (.projectFolders, Self.foldersLabel, "\(Render.counted(folderCount, "folder")) ›"), + (.protectedPaths, Self.pathsLabel, "\(Render.counted(pathCount, "path")) ›"), ] let valueWidth = rows.map { Term.displayWidth($0.value) }.reduce(Self.widestValue, max) let widestLabel = rows.map { Term.displayWidth($0.label) }.max() ?? 1 diff --git a/cli/Sources/puremac/Core/Purger.swift b/cli/Sources/puremac/Core/Purger.swift index 5f4ebb2..91d3272 100644 --- a/cli/Sources/puremac/Core/Purger.swift +++ b/cli/Sources/puremac/Core/Purger.swift @@ -54,7 +54,7 @@ enum Purger { if isArtifact(name) { en.skipDescendants() if Safety.ignoredPathProtectsCandidate(url.path, ignore: ignore) { continue } - let measurement = DirSizer.measure(of: url.path) + let measurement = DirSizer.measure(of: url.path, isCancelled: isCancelled) guard measurement.status == .complete, measurement.bytes >= CategoryScanner.minSize else { continue } let mod = DirSizer.modified(of: url.path) diff --git a/cli/Sources/puremac/Core/Render.swift b/cli/Sources/puremac/Core/Render.swift index aac7364..9bf4512 100644 --- a/cli/Sources/puremac/Core/Render.swift +++ b/cli/Sources/puremac/Core/Render.swift @@ -5,6 +5,7 @@ import TerminalUI enum Render { static let rule = String(repeating: "─", count: 60) static let sizeColumnWidth = 10 + static let reviewHelp = "Return on the selection screen opens a confirmation with Cancel focused. --plain uses a numbered selector with ranges, all, and none, then prints the exact deletion review and asks (default No)." static func scanResults(_ categories: [CategoryScan], colors: Bool = Term.colorEnabled) { let total = categories.reduce(Int64(0)) { $0 + $1.allBytes } @@ -108,8 +109,12 @@ enum Render { static let cleanupCompleteTitle = "Cleanup complete" + static func counted(_ count: Int, _ noun: String) -> String { + "\(count) \(noun)\(count == 1 ? "" : "s")" + } + static func itemCount(_ count: Int) -> String { - CleanupFlow.counted(count, "item") + counted(count, "item") } static func removedDetail(_ outcome: CleanOutcome) -> String { diff --git a/cli/Sources/puremac/Core/Scanner.swift b/cli/Sources/puremac/Core/Scanner.swift index 3960411..d0dfeb0 100644 --- a/cli/Sources/puremac/Core/Scanner.swift +++ b/cli/Sources/puremac/Core/Scanner.swift @@ -89,7 +89,7 @@ enum DirSizer { measure(of: path).bytes } - static func measure(of path: String) -> Measurement { + static func measure(of path: String, isCancelled: () -> Bool = { false }) -> Measurement { let fm = FileManager.default if Safety.hasSymlinkComponent(path) { return Measurement(bytes: 0, status: .symlink, skippedEntries: 1) @@ -107,10 +107,10 @@ enum DirSizer { } return Measurement(bytes: bytes, status: .complete, skippedEntries: 0) } - return foundationSize(URL(fileURLWithPath: path)) + return foundationSize(URL(fileURLWithPath: path), isCancelled: isCancelled) } - private static func foundationSize(_ url: URL) -> Measurement { + private static func foundationSize(_ url: URL, isCancelled: () -> Bool) -> Measurement { var total: Int64 = 0 var skipped = 0 let keys: [URLResourceKey] = [ @@ -131,6 +131,9 @@ enum DirSizer { return Measurement(bytes: 0, status: .unavailable, skippedEntries: 1) } for case let item as URL in en { + if isCancelled() { + return Measurement(bytes: total, status: .partial, skippedEntries: skipped + 1) + } let values = try? item.resourceValues(forKeys: Set(keys)) if values?.isSymbolicLink == true { en.skipDescendants() diff --git a/cli/Sources/puremac/Core/StartConfirmation.swift b/cli/Sources/puremac/Core/StartConfirmation.swift index bfa3b13..6b59cce 100644 --- a/cli/Sources/puremac/Core/StartConfirmation.swift +++ b/cli/Sources/puremac/Core/StartConfirmation.swift @@ -18,7 +18,7 @@ struct StartConfirmation { static func projectCleanup(folderCount: Int) -> StartConfirmation { StartConfirmation( title: "Scan your project folders?", - message: "Searching \(CleanupFlow.counted(folderCount, "folder")) for build artifacts can take a few minutes.", + message: "Searching \(Render.counted(folderCount, "folder")) for build artifacts can take a few minutes.", menuSelection: HomeMenu.projectCleanupIndex ) } @@ -46,6 +46,13 @@ struct StartConfirmation { } } + func acceptsKey(_ key: TerminalKey, tooSmall: Bool) -> Bool { + guard tooSmall else { return true } + if key == .escape { return true } + guard case .character(let character) = key else { return false } + return ["q", "n"].contains(String(character).lowercased()) + } + func render(width: Int, height: Int) -> Buffer { StatusScreen.overlay(dialog, on: HomeMenu.screen(selection: menuSelection, width: width, height: height), tooSmallExitHint: "Esc back") } @@ -56,7 +63,10 @@ struct StartConfirmation { var model = self while true { session.draw(model.render(width: session.width, height: session.height)) - if let choice = model.handle(session.readKey()) { return choice == .start } + let key = session.readKey() + let tooSmall = !TooSmallScreen.fits(width: session.width, height: session.height) + guard model.acceptsKey(key, tooSmall: tooSmall) else { continue } + if let choice = model.handle(key) { return choice == .start } } } diff --git a/cli/Sources/puremac/Core/StatusScreen.swift b/cli/Sources/puremac/Core/StatusScreen.swift index 3d820aa..a1b27ec 100644 --- a/cli/Sources/puremac/Core/StatusScreen.swift +++ b/cli/Sources/puremac/Core/StatusScreen.swift @@ -14,6 +14,7 @@ struct StatusRow { enum StatusScreen { static let warningTitle = TextStyle(color: .yellow, bold: true) + static let cancellingText = "Cancelling…" static let scanHint = KeyHint("Esc/q", "cancel") static let warningBorder = TextStyle(color: .yellow) static let choiceHints = KeyHints([KeyHint("Enter", "select"), KeyHint("Esc", "back")]) diff --git a/cli/Sources/puremac/Core/SystemInfo.swift b/cli/Sources/puremac/Core/SystemInfo.swift index abbeeb2..f5d9fd2 100644 --- a/cli/Sources/puremac/Core/SystemInfo.swift +++ b/cli/Sources/puremac/Core/SystemInfo.swift @@ -193,8 +193,8 @@ enum SystemInfo { private static func coreSummary(_ sysctl: Sysctl) -> String? { if let performance = sysctl.int("hw.perflevel0.physicalcpu"), let efficiency = sysctl.int("hw.perflevel1.physicalcpu") { - return "\(CleanupFlow.counted(Int(performance + efficiency), "core")) (\(performance) performance, \(efficiency) efficiency)" + return "\(Render.counted(Int(performance + efficiency), "core")) (\(performance) performance, \(efficiency) efficiency)" } - return sysctl.int("hw.ncpu").map { CleanupFlow.counted(Int($0), "core") } + return sysctl.int("hw.ncpu").map { Render.counted(Int($0), "core") } } } diff --git a/cli/Sources/puremac/Core/SystemStatusScreen.swift b/cli/Sources/puremac/Core/SystemStatusScreen.swift index 3671537..e4fa9f0 100644 --- a/cli/Sources/puremac/Core/SystemStatusScreen.swift +++ b/cli/Sources/puremac/Core/SystemStatusScreen.swift @@ -160,3 +160,29 @@ struct SystemStatusScreen { } } } + +extension InfoSheet { + static func write(_ spans: [Span], in rect: Rect, buffer: inout Buffer) { + guard Term.displayWidth(spans) > rect.width else { + buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width) + return + } + let used = buffer.write(spans, x: rect.x, y: rect.y, maxWidth: rect.width - 1) + buffer.write("…", x: rect.x + used, y: rect.y) + } +} + +struct InfoSheetScroll { + private(set) var offset = 0 + + mutating func handle(_ key: TerminalKey, maxOffset: Int) -> Bool { + switch key { + case .up: offset = max(0, min(offset, maxOffset) - 1) + case .down: offset = min(maxOffset, offset + 1) + case .escape, .enter, .left, .backspace: return true + case .character(let character): return character.lowercased() == "q" + default: break + } + return false + } +} diff --git a/cli/Sources/puremac/PureMac.swift b/cli/Sources/puremac/PureMac.swift index ff3df6e..d7c10a5 100644 --- a/cli/Sources/puremac/PureMac.swift +++ b/cli/Sources/puremac/PureMac.swift @@ -52,22 +52,34 @@ enum HomeMenu { ) } - static func projectCleanupConfirmation(folderCount: Int) -> StartConfirmation? { - folderCount > 0 ? .projectCleanup(folderCount: folderCount) : nil + enum ProjectCleanupEntry { + case confirm(StartConfirmation) + case notice(String) } - static func noFoldersNotice(width: Int, height: Int) -> Buffer { + static func projectCleanupEntry(folderCount: () throws -> Int) -> ProjectCleanupEntry { + do { + let count = try folderCount() + return count > 0 ? .confirm(.projectCleanup(folderCount: count)) : .notice(Purge.noFoldersMessage) + } catch { + return .notice(error.localizedDescription) + } + } + + static func projectCleanupNotice(message: String, width: Int, height: Int) -> Buffer { CleanupFlow.infoScreen( title: options[projectCleanupIndex].title, - message: Purge.noFoldersMessage, + message: message, on: screen(selection: projectCleanupIndex, width: width, height: height) ) } - private static func showNoFoldersNotice() throws { + private static func showProjectCleanupNotice(_ message: String) throws { let session = try TerminalSession() defer { session.close() } - CleanupFlow.showInfo(on: session) { noFoldersNotice(width: session.width, height: session.height) } + CleanupFlow.showInfo(on: session) { + projectCleanupNotice(message: message, width: session.width, height: session.height) + } } static func run(setupError: Error?) throws { @@ -90,12 +102,14 @@ enum HomeMenu { let arguments = [[], ["dev"], ["junk"], ["ai"], ["trash"]] try Clean.parse(arguments[category]).run() case projectCleanupIndex: - let folderCount = try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots.count - guard let confirmation = projectCleanupConfirmation(folderCount: folderCount) else { - try showNoFoldersNotice() + let entry = projectCleanupEntry { try ProjectFoldersStore(fileURL: AppPaths.projectsFile).roots.count } + switch entry { + case .notice(let message): + try showProjectCleanupNotice(message) continue + case .confirm(let confirmation): + guard try confirmation.ask() else { continue } } - guard try confirmation.ask() else { continue } try Purge.parse([]).run() case exploreIndex: guard try StartConfirmation.explore.ask() else { continue } diff --git a/cli/Tests/TerminalUITests/DialogTests.swift b/cli/Tests/TerminalUITests/DialogTests.swift index 824d9a7..558dffb 100644 --- a/cli/Tests/TerminalUITests/DialogTests.swift +++ b/cli/Tests/TerminalUITests/DialogTests.swift @@ -297,6 +297,20 @@ final class DialogTests: XCTestCase { ]) } + func testCenteredMessageWrapsBalancedAndLeadingKeepsGreedyWrap() { + let text = "Searching 1 folder for build artifacts can take a few minutes." + let wide = Rect(x: 0, y: 0, width: 64, height: 18) + var dialog = Dialog(title: "T", message: [Span(text)], buttons: []) + let centered = render(dialog, in: wide).rows.map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "│ ")) } + XCTAssertTrue(centered.contains("Searching 1 folder for build")) + XCTAssertTrue(centered.contains("artifacts can take a few minutes.")) + + dialog.messageAlignment = .leading + let leading = render(dialog, in: wide).rows.map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "│ ")) } + XCTAssertTrue(leading.contains("Searching 1 folder for build artifacts can take a few")) + XCTAssertTrue(leading.contains("minutes.")) + } + func testCenterMessageAlignmentIsTheDefault() { let dialog = Dialog(title: "T", message: [Span("a"), Span("longer text")]) XCTAssertEqual(render(dialog, in: area).rows[2], "│ a │") diff --git a/cli/Tests/TerminalUITests/KeyInputTests.swift b/cli/Tests/TerminalUITests/KeyInputTests.swift new file mode 100644 index 0000000..13cdaa2 --- /dev/null +++ b/cli/Tests/TerminalUITests/KeyInputTests.swift @@ -0,0 +1,68 @@ +import Darwin +import XCTest +@testable import TerminalUI + +final class KeyInputTests: XCTestCase { + private func makePipe() -> (read: Int32, write: Int32) { + var descriptors: [Int32] = [0, 0] + XCTAssertEqual(pipe(&descriptors), 0) + return (descriptors[0], descriptors[1]) + } + + func testReadsByteWhileOpen() { + let (read, write) = makePipe() + defer { close(read); close(write) } + _ = Darwin.write(write, "a", 1) + let input = KeyInput(descriptor: read) + + XCTAssertEqual(input.readByte(), 0x61) + XCTAssertFalse(input.isClosed) + } + + func testEndOfFileMarksInputClosed() { + let (read, write) = makePipe() + defer { close(read) } + close(write) + let input = KeyInput(descriptor: read) + + XCTAssertNil(input.readByte()) + XCTAssertTrue(input.isClosed) + } + + func testReadErrorMarksInputClosed() { + let input = KeyInput(descriptor: -1) + + XCTAssertNil(input.readByte()) + XCTAssertTrue(input.isClosed) + } + + private func elapsedMilliseconds(_ body: () -> Void) -> UInt64 { + let start = DispatchTime.now().uptimeNanoseconds + body() + return (DispatchTime.now().uptimeNanoseconds - start) / 1_000_000 + } + + func testClosedInputWaitsOutTheTimeoutAndReportsReady() { + let (read, write) = makePipe() + defer { close(read) } + close(write) + let input = KeyInput(descriptor: read) + _ = input.readByte() + var ready = false + + let elapsed = elapsedMilliseconds { ready = input.wait(milliseconds: 60) } + + XCTAssertTrue(ready) + XCTAssertGreaterThanOrEqual(elapsed, 50) + } + + func testOpenInputWaitReportsPendingByteOnly() { + let (read, write) = makePipe() + defer { close(read); close(write) } + let input = KeyInput(descriptor: read) + + XCTAssertFalse(input.wait(milliseconds: 0)) + _ = Darwin.write(write, "a", 1) + XCTAssertTrue(input.wait(milliseconds: 0)) + } +} diff --git a/cli/Tests/TerminalUITests/TermTests.swift b/cli/Tests/TerminalUITests/TermTests.swift index 6e7a6b2..9f613cd 100644 --- a/cli/Tests/TerminalUITests/TermTests.swift +++ b/cli/Tests/TerminalUITests/TermTests.swift @@ -45,6 +45,23 @@ final class TermTests: XCTestCase { XCTAssertEqual(Term.wordWrap("one two three", width: 7), ["one", "two", "three"]) } + func testBalancedWrapKeepsLineCountAndEvensTheLines() { + let text = "Searching 1 folder for build artifacts can take a few minutes." + XCTAssertEqual(Term.wordWrap(text, width: 54), ["Searching 1 folder for build artifacts can take a few", "minutes."]) + XCTAssertEqual(Term.balancedWrap(text, width: 54), ["Searching 1 folder for build", "artifacts can take a few minutes."]) + XCTAssertEqual(Term.balancedWrap(text, width: 30), ["Searching 1 folder for", "build artifacts can", "take a few minutes."]) + } + + func testBalancedWrapLeavesShortTextAndHardBreaksAlone() { + XCTAssertEqual(Term.balancedWrap("one two", width: 20), ["one two"]) + XCTAssertEqual(Term.balancedWrap("", width: 10), [""]) + XCTAssertEqual(Term.balancedWrap("ab abcdefg", width: 3), ["ab", "abc", "def", "g"]) + } + + func testBalancedWrapNeverBreaksAWordThatGreedyWrapKeptWhole() { + XCTAssertEqual(Term.balancedWrap("aaaa b", width: 5), ["aaaa", "b"]) + } + func testWordWrapEmptyParagraphIsOneEmptyRow() { XCTAssertEqual(Term.wordWrap("", width: 10), [""]) } diff --git a/cli/Tests/puremacTests/AnalyzeTests.swift b/cli/Tests/puremacTests/AnalyzeTests.swift index e352588..76399dc 100644 --- a/cli/Tests/puremacTests/AnalyzeTests.swift +++ b/cli/Tests/puremacTests/AnalyzeTests.swift @@ -17,6 +17,10 @@ final class AnalyzeTests: XCTestCase { root = nil } + private func emptyIgnore() throws -> IgnoreStore { + try IgnoreStore(fileURL: FileManager.default.temporaryDirectory.appendingPathComponent("analyze-ignore-\(UUID().uuidString)")) + } + func testDepthValidationUsesDocumentedBounds() throws { var analyze = Analyze() analyze.depth = 1 @@ -44,7 +48,7 @@ final class AnalyzeTests: XCTestCase { try Data(repeating: 0x41, count: 8_192).write(to: small) try Data(repeating: 0x42, count: 1_000_000).write(to: contents.appendingPathComponent("payload.bin")) - let snapshot = Analyze().scanFolder(root.path) + let snapshot = Analyze().scanFolder(root.path, ignore: try emptyIgnore()) XCTAssertEqual(snapshot.children.map { URL(fileURLWithPath: $0.path).lastPathComponent }, ["Example.app", "small.bin"]) let packageChild = try XCTUnwrap(snapshot.children.first) @@ -78,7 +82,7 @@ final class AnalyzeTests: XCTestCase { XCTAssertEqual(chmod(locked.path, 0), 0) defer { _ = chmod(locked.path, S_IRWXU) } - let snapshot = Analyze().scanFolder(root.path) + let snapshot = Analyze().scanFolder(root.path, ignore: try emptyIgnore()) XCTAssertTrue(snapshot.isPartial) XCTAssertGreaterThan(snapshot.skippedCount + snapshot.inaccessibleCount, 0) @@ -341,8 +345,8 @@ final class AnalyzeTests: XCTestCase { private func measuringProgress( position: Int = 3, count: Int = 5, name: String = "Library", isPackage: Bool = false, measured: [Analyze.Child]? = nil - ) -> Analyze.ScanProgress { - Analyze.ScanProgress( + ) -> Analyze.MeasureProgress { + Analyze.MeasureProgress( path: "/tmp", position: position, count: count, name: name, nameIsDirectory: true, nameIsPackage: isPackage, measured: measured ?? [child("/tmp/small", size: 1_000), child("/tmp/big", size: 5_000)] @@ -350,7 +354,7 @@ final class AnalyzeTests: XCTestCase { } private func measuringLines( - _ progress: Analyze.ScanProgress, drillingDown: Bool = false, width: Int = 60, height: Int = 14 + _ progress: Analyze.MeasureProgress, drillingDown: Bool = false, width: Int = 60, height: Int = 14 ) -> [String] { Analyze.renderMeasuringBrowser( progress: progress, tick: 2, drillingDown: drillingDown, width: width, height: height @@ -363,14 +367,14 @@ final class AnalyzeTests: XCTestCase { try Data(repeating: 0x42, count: 8_192).write(to: root.appendingPathComponent("b-dir/x.bin")) var events: [Analyze.ScanEvent] = [] - let snapshot = Analyze().scanFolder(root.path, progress: { events.append($0) }) + let snapshot = Analyze().scanFolder(root.path, ignore: try emptyIgnore(), progress: { events.append($0) }) XCTAssertEqual(events.count, 4) XCTAssertEqual(events[0], .measuring(position: 1, count: 2, name: "a.bin", isDirectory: false, isPackage: false)) guard case .measured(let first) = events[1] else { return XCTFail("expected measured") } XCTAssertEqual(URL(fileURLWithPath: first.path).lastPathComponent, "a.bin") XCTAssertEqual(events[2], .measuring(position: 2, count: 2, name: "b-dir", isDirectory: true, isPackage: false)) - XCTAssertEqual(snapshot, Analyze().scanFolder(root.path)) + XCTAssertEqual(snapshot, Analyze().scanFolder(root.path, ignore: try emptyIgnore())) } func testScanStopsBetweenChildrenWhenCancelled() throws { @@ -380,6 +384,7 @@ final class AnalyzeTests: XCTestCase { var measured = 0 let snapshot = Analyze().scanFolder( root.path, + ignore: try emptyIgnore(), progress: { if case .measured = $0 { measured += 1 } }, isCancelled: { measured >= 1 } ) @@ -388,8 +393,31 @@ final class AnalyzeTests: XCTestCase { XCTAssertEqual(snapshot.children.count, 1) } - func testScanProgressCollectsEvents() { - var progress = Analyze.ScanProgress(path: "/tmp") + func testScanStopsInsideALargeChildWhenCancelled() throws { + let big = root.appendingPathComponent("big", isDirectory: true) + try FileManager.default.createDirectory(at: big, withIntermediateDirectories: true) + for index in 0..<60 { + try Data(repeating: 0x41, count: 4_096).write(to: big.appendingPathComponent("file-\(index).bin")) + } + var checks = 0 + let snapshot = Analyze().scanFolder(root.path, ignore: try emptyIgnore(), isCancelled: { + checks += 1 + return checks > 3 + }) + + XCTAssertTrue(snapshot.children.isEmpty) + XCTAssertLessThan(checks, 20) + } + + func testMeasuringBrowserStatusReadsCancellingOnceCancelRequested() { + let lines = Analyze.renderMeasuringBrowser( + progress: measuringProgress(), tick: 2, drillingDown: true, isCancelling: true, width: 60, height: 14 + ).plainLines() + XCTAssertEqual(lines[2], "│ ⠹ Cancelling… │") + } + + func testMeasureProgressCollectsEvents() { + var progress = Analyze.MeasureProgress(path: "/tmp") progress.apply(.measuring(position: 2, count: 4, name: "Docs", isDirectory: true, isPackage: true)) XCTAssertEqual(progress.position, 2) XCTAssertEqual(progress.count, 4) @@ -418,7 +446,7 @@ final class AnalyzeTests: XCTestCase { func testMeasuringBrowserBeforeFirstChildAndForFiles() { let start = Analyze.renderMeasuringBrowser( - progress: Analyze.ScanProgress(path: "/tmp"), tick: 0, drillingDown: false, width: 60, height: 14 + progress: Analyze.MeasureProgress(path: "/tmp"), tick: 0, drillingDown: false, width: 60, height: 14 ).plainLines() XCTAssertEqual(start[2], "│ ⠋ Measuring… │") XCTAssertEqual(start[3], "│ │") diff --git a/cli/Tests/puremacTests/CategoryScannerTests.swift b/cli/Tests/puremacTests/CategoryScannerTests.swift new file mode 100644 index 0000000..383192b --- /dev/null +++ b/cli/Tests/puremacTests/CategoryScannerTests.swift @@ -0,0 +1,109 @@ +import Foundation +import XCTest +@testable import puremac + +final class CategoryScannerTests: XCTestCase { + func testCatalogScanReturnsGroupsSizesAndSelection() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/cache-a/data", bytes: 8192) + try FileManager.default.createDirectory(atPath: "\(dir)/cache-b", withIntermediateDirectories: true) + let targets = [ + Target(tool: "Tool A", paths: ["\(dir)/cache-a"], selectedByDefault: false), + Target(tool: "Tool B", paths: ["\(dir)/cache-b"]), + Target(tool: "Tool C", paths: ["\(dir)/missing"]) + ] + let groups = CategoryScanner.scanCatalog(targets: targets, ignore: ignore(), isCancelled: { false }) + XCTAssertEqual(groups.map(\.tool), ["Tool A"]) + let item = try XCTUnwrap(groups.first?.items.first) + XCTAssertEqual(item.path, "\(dir)/cache-a") + XCTAssertGreaterThanOrEqual(item.sizeBytes, 8192) + XCTAssertFalse(item.selected) + } + + func testCatalogScanOfContentsTargetListsChildren() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/logs/one/data", bytes: 8192) + _ = try makeFile("\(dir)/logs/two/data", bytes: 8192) + let groups = CategoryScanner.scanCatalog( + targets: [Target(tool: "Logs", paths: ["\(dir)/logs"], contents: true)], ignore: ignore(), isCancelled: { false } + ) + XCTAssertEqual(groups.first?.items.map(\.path).sorted(), ["\(dir)/logs/one", "\(dir)/logs/two"]) + XCTAssertTrue(groups.first?.items.allSatisfy(\.selected) ?? false) + } + + func testCancelledCatalogScanReturnsNoGroups() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/cache/data", bytes: 8192) + let groups = CategoryScanner.scanCatalog( + targets: [Target(tool: "Tool", paths: ["\(dir)/cache"])], ignore: ignore(), isCancelled: { true } + ) + XCTAssertTrue(groups.isEmpty) + } + + func testTrashScanReturnsOneGroupPerRootWithItems() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/trash/old/data", bytes: 8192) + let groups = CategoryScanner.scanTrash( + roots: ["\(dir)/trash", "\(dir)/no-trash"], ignore: ignore(), isCancelled: { false } + ) + XCTAssertEqual(groups.map(\.tool), ["Trash"]) + XCTAssertEqual(groups.first?.items.map(\.path), ["\(dir)/trash/old"]) + XCTAssertTrue(groups.first?.items.allSatisfy(\.selected) ?? false) + } + + func testCancelledTrashScanReturnsNoGroups() throws { + let dir = try tempDir() + _ = try makeFile("\(dir)/trash/old/data", bytes: 8192) + XCTAssertTrue(CategoryScanner.scanTrash(roots: ["\(dir)/trash"], ignore: ignore(), isCancelled: { true }).isEmpty) + } + + func testCancelledCatalogMeasurementIsNotReportedAsAGroup() throws { + let dir = try tempDir() + for index in 0..<60 { _ = try makeFile("\(dir)/cache/file-\(index).bin", bytes: 4096) } + var checks = 0 + let groups = CategoryScanner.scanCatalog( + targets: [Target(tool: "Tool", paths: ["\(dir)/cache"])], + ignore: ignore(), + isCancelled: { + checks += 1 + return checks > 1 + } + ) + + XCTAssertTrue(groups.isEmpty) + XCTAssertLessThan(checks, 20) + } + + func testCancelledTrashMeasurementIsNotReportedAsAGroup() throws { + let dir = try tempDir() + for index in 0..<60 { _ = try makeFile("\(dir)/trash/old/file-\(index).bin", bytes: 4096) } + var checks = 0 + let groups = CategoryScanner.scanTrash(roots: ["\(dir)/trash"], ignore: ignore(), isCancelled: { + checks += 1 + return checks > 1 + }) + + XCTAssertTrue(groups.isEmpty) + XCTAssertLessThan(checks, 20) + } + + private func ignore() -> IgnoreStore { + try! IgnoreStore(fileURL: FileManager.default.temporaryDirectory.appendingPathComponent("category-scanner-\(UUID().uuidString)")) + } + + private func tempDir() throws -> String { + let url = FileManager.default.temporaryDirectory + .appendingPathComponent("category-scanner-dir-\(UUID().uuidString)").resolvingSymlinksInPath() + try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) + addTeardownBlock { try? FileManager.default.removeItem(at: url) } + return url.path + } + + private func makeFile(_ path: String, bytes: Int) throws -> String { + try FileManager.default.createDirectory( + atPath: (path as NSString).deletingLastPathComponent, withIntermediateDirectories: true + ) + try Data(repeating: 1, count: bytes).write(to: URL(fileURLWithPath: path)) + return path + } +} diff --git a/cli/Tests/puremacTests/CleanupFlowTests.swift b/cli/Tests/puremacTests/CleanupFlowTests.swift index cd48f57..3ed7e74 100644 --- a/cli/Tests/puremacTests/CleanupFlowTests.swift +++ b/cli/Tests/puremacTests/CleanupFlowTests.swift @@ -19,6 +19,13 @@ final class CleanupFlowTests: XCTestCase { XCTAssertTrue(lines.contains { $0.contains("Esc/q cancel") }) } + func testScanningScreenHeadlineReadsCancellingOnceCancelRequested() { + let status = ScanStatus(headline: "Scanning Developer caches, 2 of 4") + let lines = CleanupFlow.scanningScreen(status: status, tick: 0, isCancelling: true, width: 60, height: 14).plainLines() + XCTAssertTrue(lines[1].contains("⠋ Cancelling…"), lines[1]) + XCTAssertFalse(lines[1].contains("Developer")) + } + func testScanningScreenSpinnerFollowsTheTick() { let status = ScanStatus(headline: "Scanning") let lines = CleanupFlow.scanningScreen(status: status, tick: 3, width: 60, height: 14).plainLines() diff --git a/cli/Tests/puremacTests/CommandReviewTests.swift b/cli/Tests/puremacTests/CommandReviewTests.swift index 627c465..19a028b 100644 --- a/cli/Tests/puremacTests/CommandReviewTests.swift +++ b/cli/Tests/puremacTests/CommandReviewTests.swift @@ -111,4 +111,13 @@ final class CommandReviewTests: XCTestCase { XCTAssertEqual(reviewed.flatMap(\.selectedItems).map(\.path), [recent.path]) XCTAssertEqual(category.selectedItems.map(\.path), [old.path]) } + + func testCleanAndPurgeHelpDescribeTheConfirmationDialogAndPlainReview() throws { + for discussion in [Clean.configuration.discussion, Purge.configuration.discussion] { + XCTAssertTrue(discussion.contains(Render.reviewHelp), discussion) + XCTAssertTrue(discussion.contains("Return on the selection screen opens a confirmation with Cancel focused")) + XCTAssertTrue(discussion.contains("--plain uses a numbered selector with ranges, all, and none, then prints the exact deletion review and asks (default No)")) + XCTAssertFalse(discussion.contains("only opens an exact deletion review")) + } + } } diff --git a/cli/Tests/puremacTests/CoreSafetyTests.swift b/cli/Tests/puremacTests/CoreSafetyTests.swift index e1a59aa..20e80f4 100644 --- a/cli/Tests/puremacTests/CoreSafetyTests.swift +++ b/cli/Tests/puremacTests/CoreSafetyTests.swift @@ -78,6 +78,41 @@ final class CoreSafetyTests: XCTestCase { XCTAssertTrue(fileManager.fileExists(atPath: artifact.appendingPathComponent("replacement.bin").path)) } + private func makeFolder(files: Int) throws -> URL { + let folder = root.appendingPathComponent("folder-\(UUID().uuidString)", isDirectory: true) + try fileManager.createDirectory(at: folder, withIntermediateDirectories: true) + for index in 0.. 5 + }) + + XCTAssertEqual(measured.status, .partial) + XCTAssertGreaterThan(measured.skippedEntries, 0) + XCTAssertLessThan(measured.bytes, 60 * 4096) + XCTAssertLessThan(checks, 20) + } + func testCleanerAccountsFreshMeasuredBytes() throws { let file = root.appendingPathComponent("cache.bin") try Data(repeating: 5, count: 8192).write(to: file) diff --git a/cli/Tests/puremacTests/InfoSheetTests.swift b/cli/Tests/puremacTests/InfoSheetTests.swift index 80c0c0a..25cf8cf 100644 --- a/cli/Tests/puremacTests/InfoSheetTests.swift +++ b/cli/Tests/puremacTests/InfoSheetTests.swift @@ -130,40 +130,4 @@ final class InfoSheetTests: XCTestCase { XCTAssertEqual(styled, "`puremac ignore add `") XCTAssertFalse(plain(rows).joined().contains("…")) } - - func testWriteCutsAnOverlongRowWithAnEllipsis() { - var buffer = Buffer(width: 10, height: 1) - InfoSheet.write([Span(String(repeating: "a", count: 30))], in: Rect(x: 0, y: 0, width: 10, height: 1), buffer: &buffer) - XCTAssertEqual(buffer.plainLines(), ["aaaaaaaaa…"]) - var fits = Buffer(width: 10, height: 1) - InfoSheet.write([Span("short")], in: Rect(x: 0, y: 0, width: 10, height: 1), buffer: &fits) - XCTAssertEqual(fits.plainLines()[0].trimmingCharacters(in: .whitespaces), "short") - } - - func testScrollMovesByOneAndStaysInRange() { - var scroll = InfoSheetScroll() - XCTAssertFalse(scroll.handle(.up, maxOffset: 3)) - XCTAssertEqual(scroll.offset, 0) - for _ in 0..<5 { XCTAssertFalse(scroll.handle(.down, maxOffset: 3)) } - XCTAssertEqual(scroll.offset, 3) - XCTAssertFalse(scroll.handle(.up, maxOffset: 3)) - XCTAssertEqual(scroll.offset, 2) - XCTAssertFalse(scroll.handle(.down, maxOffset: 0)) - XCTAssertEqual(scroll.offset, 0) - } - - func testScrollClosesOnEscQEnterLeftAndBackspace() { - for key in [TerminalKey.escape, .enter, .left, .backspace, .character("q"), .character("Q")] { - var scroll = InfoSheetScroll() - XCTAssertTrue(scroll.handle(key, maxOffset: 3), "\(key)") - } - } - - func testScrollIgnoresOtherKeys() { - for key in [TerminalKey.right, .tab, .space, .pageDown, .character("x"), .unknown] { - var scroll = InfoSheetScroll() - XCTAssertFalse(scroll.handle(key, maxOffset: 3), "\(key)") - XCTAssertEqual(scroll.offset, 0) - } - } } diff --git a/cli/Tests/puremacTests/PathListEditorTests.swift b/cli/Tests/puremacTests/PathListEditorTests.swift index 4f68871..af05dc9 100644 --- a/cli/Tests/puremacTests/PathListEditorTests.swift +++ b/cli/Tests/puremacTests/PathListEditorTests.swift @@ -262,6 +262,26 @@ final class PathListEditorTests: XCTestCase { XCTAssertTrue(list.removed.isEmpty) } + func testRemovalPromptNAndQCancelWithoutRemovingOrLeaving() { + for key in [TerminalKey.character("n"), .character("N"), .character("q"), .character("Q")] { + let list = FakeList(["/a"]) + var editor = editor(list, confirmsRemoval: true) + _ = editor.handle(.character("d")) + XCTAssertFalse(editor.handle(key), "\(key)") + XCTAssertNil(editor.confirmation, "\(key)") + XCTAssertTrue(list.removed.isEmpty, "\(key)") + } + } + + func testRemovalPromptRemoveButtonIsNotTriggeredByForwardDelete() { + let list = FakeList(["/a"]) + var editor = editor(list, confirmsRemoval: true) + _ = editor.handle(.character("d")) + XCTAssertFalse(editor.handle(.delete)) + XCTAssertNotNil(editor.confirmation) + XCTAssertTrue(list.removed.isEmpty) + } + func testRemovalPromptEnterOnRemoveDeletesThePath() { let list = FakeList(["/a", "/b"]) var editor = editor(list, confirmsRemoval: true) @@ -433,13 +453,20 @@ final class PathListEditorTests: XCTestCase { XCTAssertTrue(editor.acceptsKey(.escape, tooSmall: true)) XCTAssertTrue(editor.acceptsKey(.enter, tooSmall: true)) XCTAssertFalse(editor.acceptsKey(.right, tooSmall: true)) + for key in ["n", "N", "q", "Q"] { XCTAssertTrue(editor.acceptsKey(.character(Character(key)), tooSmall: true), key) } + XCTAssertFalse(editor.acceptsKey(.character("y"), tooSmall: true)) _ = editor.handle(.right) XCTAssertFalse(editor.acceptsKey(.enter, tooSmall: true)) XCTAssertTrue(editor.acceptsKey(.enter, tooSmall: false)) } + func testForwardDeleteDoesNotLeaveTheList() { + var editor = editor(FakeList(["/a"])) + XCTAssertFalse(editor.handle(.delete)) + } + func testLeavesOnQLeftAndBackspaceToo() { - for key in [TerminalKey.character("q"), .character("Q"), .left, .backspace, .delete] { + for key in [TerminalKey.character("q"), .character("Q"), .left, .backspace] { var editor = editor(FakeList(["/a"])) XCTAssertTrue(editor.handle(key), "\(key)") } diff --git a/cli/Tests/puremacTests/PreferencesSheetTests.swift b/cli/Tests/puremacTests/PlainCommandOutputTests.swift similarity index 90% rename from cli/Tests/puremacTests/PreferencesSheetTests.swift rename to cli/Tests/puremacTests/PlainCommandOutputTests.swift index c3ef8c3..b4089f0 100644 --- a/cli/Tests/puremacTests/PreferencesSheetTests.swift +++ b/cli/Tests/puremacTests/PlainCommandOutputTests.swift @@ -92,14 +92,4 @@ final class PreferencesSheetTests: XCTestCase { XCTAssertEqual(projects, [Span("\(dir.path)/projects")]) } } - - func testProtectedPathsSheetListsSortedPaths() { - let sheet = Ignore.List.sheet(roots: ["/tmp/b", "/tmp/a"]) - XCTAssertEqual(sheet.title, "Protected paths") - XCTAssertNil(sheet.subtitle) - XCTAssertEqual(sheet.sections.count, 1) - XCTAssertEqual(sheet.sections[0].rows.count, 2) - guard case .path(let first) = sheet.sections[0].rows[0] else { return XCTFail("path row") } - XCTAssertEqual(first, "/tmp/a") - } } diff --git a/cli/Tests/puremacTests/PurgerScanTests.swift b/cli/Tests/puremacTests/PurgerScanTests.swift index 184c80e..f46b023 100644 --- a/cli/Tests/puremacTests/PurgerScanTests.swift +++ b/cli/Tests/puremacTests/PurgerScanTests.swift @@ -34,6 +34,20 @@ final class PurgerScanTests: XCTestCase { XCTAssertTrue(scan.groups.flatMap(\.items).allSatisfy(\.selected)) } + func testCancelledArtifactMeasurementIsNotReportedAsAGroup() throws { + let modules = try artifact("alpha/node_modules", bytes: 4096) + for index in 0..<60 { try Data(repeating: 1, count: 4096).write(to: modules.appendingPathComponent("file-\(index).bin")) } + var checks = 0 + + let scan = Purger.scan(roots: [root.path], olderThanDays: 0, ignore: try ignoreStore(), isCancelled: { + checks += 1 + return checks > 2 + }) + + XCTAssertTrue(scan.groups.isEmpty) + XCTAssertLessThan(checks, 20) + } + func testRecentArtifactsStayUnselectedAndEmptyOnesAreSkipped() throws { try artifact("alpha/node_modules", bytes: 8192) try fileManager.createDirectory(at: root.appendingPathComponent("alpha/venv"), withIntermediateDirectories: true) diff --git a/cli/Tests/puremacTests/ScanProgressTests.swift b/cli/Tests/puremacTests/ScanProgressTests.swift index 6badf00..d84ac52 100644 --- a/cli/Tests/puremacTests/ScanProgressTests.swift +++ b/cli/Tests/puremacTests/ScanProgressTests.swift @@ -17,60 +17,6 @@ final class ScanProgressTests: XCTestCase { XCTAssertTrue(verbose.hasPrefix(" scanning None…\r")) } - func testCatalogScanReturnsGroupsSizesAndSelection() throws { - let dir = try tempDir() - _ = try makeFile("\(dir)/cache-a/data", bytes: 8192) - try FileManager.default.createDirectory(atPath: "\(dir)/cache-b", withIntermediateDirectories: true) - let targets = [ - Target(tool: "Tool A", paths: ["\(dir)/cache-a"], selectedByDefault: false), - Target(tool: "Tool B", paths: ["\(dir)/cache-b"]), - Target(tool: "Tool C", paths: ["\(dir)/missing"]) - ] - let groups = CategoryScanner.scanCatalog(targets: targets, ignore: ignore(), isCancelled: { false }) - XCTAssertEqual(groups.map(\.tool), ["Tool A"]) - let item = try XCTUnwrap(groups.first?.items.first) - XCTAssertEqual(item.path, "\(dir)/cache-a") - XCTAssertGreaterThanOrEqual(item.sizeBytes, 8192) - XCTAssertFalse(item.selected) - } - - func testCatalogScanOfContentsTargetListsChildren() throws { - let dir = try tempDir() - _ = try makeFile("\(dir)/logs/one/data", bytes: 8192) - _ = try makeFile("\(dir)/logs/two/data", bytes: 8192) - let groups = CategoryScanner.scanCatalog( - targets: [Target(tool: "Logs", paths: ["\(dir)/logs"], contents: true)], ignore: ignore(), isCancelled: { false } - ) - XCTAssertEqual(groups.first?.items.map(\.path).sorted(), ["\(dir)/logs/one", "\(dir)/logs/two"]) - XCTAssertTrue(groups.first?.items.allSatisfy(\.selected) ?? false) - } - - func testCancelledCatalogScanReturnsNoGroups() throws { - let dir = try tempDir() - _ = try makeFile("\(dir)/cache/data", bytes: 8192) - let groups = CategoryScanner.scanCatalog( - targets: [Target(tool: "Tool", paths: ["\(dir)/cache"])], ignore: ignore(), isCancelled: { true } - ) - XCTAssertTrue(groups.isEmpty) - } - - func testTrashScanReturnsOneGroupPerRootWithItems() throws { - let dir = try tempDir() - _ = try makeFile("\(dir)/trash/old/data", bytes: 8192) - let groups = CategoryScanner.scanTrash( - roots: ["\(dir)/trash", "\(dir)/no-trash"], ignore: ignore(), isCancelled: { false } - ) - XCTAssertEqual(groups.map(\.tool), ["Trash"]) - XCTAssertEqual(groups.first?.items.map(\.path), ["\(dir)/trash/old"]) - XCTAssertTrue(groups.first?.items.allSatisfy(\.selected) ?? false) - } - - func testCancelledTrashScanReturnsNoGroups() throws { - let dir = try tempDir() - _ = try makeFile("\(dir)/trash/old/data", bytes: 8192) - XCTAssertTrue(CategoryScanner.scanTrash(roots: ["\(dir)/trash"], ignore: ignore(), isCancelled: { true }).isEmpty) - } - func testDefaultScanOfAnUnknownCategoryIsEmpty() { let scan = CategoryScanner.scan(categoryID: "none", title: "None", ignore: ignore(), progress: .silent) XCTAssertEqual(scan.id, "none") @@ -81,20 +27,4 @@ final class ScanProgressTests: XCTestCase { private func ignore() -> IgnoreStore { try! IgnoreStore(fileURL: FileManager.default.temporaryDirectory.appendingPathComponent("scan-progress-\(UUID().uuidString)")) } - - private func tempDir() throws -> String { - let url = FileManager.default.temporaryDirectory - .appendingPathComponent("scan-progress-dir-\(UUID().uuidString)").resolvingSymlinksInPath() - try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) - addTeardownBlock { try? FileManager.default.removeItem(at: url) } - return url.path - } - - private func makeFile(_ path: String, bytes: Int) throws -> String { - try FileManager.default.createDirectory( - atPath: (path as NSString).deletingLastPathComponent, withIntermediateDirectories: true - ) - try Data(repeating: 1, count: bytes).write(to: URL(fileURLWithPath: path)) - return path - } } diff --git a/cli/Tests/puremacTests/StartConfirmationTests.swift b/cli/Tests/puremacTests/StartConfirmationTests.swift index eeac363..8a4880c 100644 --- a/cli/Tests/puremacTests/StartConfirmationTests.swift +++ b/cli/Tests/puremacTests/StartConfirmationTests.swift @@ -37,6 +37,17 @@ final class StartConfirmationTests: XCTestCase { XCTAssertEqual(model.handle(.character("S")), .start) } + func testTooSmallScreenAcceptsOnlyEscapeQAndN() { + let model = StartConfirmation.explore + for key in [TerminalKey.escape, .character("q"), .character("Q"), .character("n"), .character("N")] { + XCTAssertTrue(model.acceptsKey(key, tooSmall: true)) + } + for key in [TerminalKey.enter, .character("s"), .character("S"), .left, .right, .tab, .space] { + XCTAssertFalse(model.acceptsKey(key, tooSmall: true)) + XCTAssertTrue(model.acceptsKey(key, tooSmall: false)) + } + } + func testOtherKeysDoNothing() { var model = StartConfirmation.explore for key in [TerminalKey.up, .down, .space, .character("x"), .character("y")] { @@ -86,6 +97,20 @@ final class StartConfirmationTests: XCTestCase { XCTAssertTrue(lines.contains { $0.contains("Project cleanup") }) } + func testProjectCleanupMessageWrapsWithoutAnOrphanWord() { + let model = StartConfirmation.projectCleanup(folderCount: 1) + for (width, height) in [(64, 18), (40, 12)] { + let lines = model.render(width: width, height: height).plainLines() + let rows = lines.map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "│╭╮╰╯─ ")) } + XCTAssertFalse(rows.contains("minutes."), "\(width)x\(height)") + } + let wide = model.render(width: 64, height: 18).plainLines().map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "│╭╮╰╯─ ")) } + XCTAssertTrue(wide.contains("Searching 1 folder for build")) + XCTAssertTrue(wide.contains("artifacts can take a few minutes.")) + let narrow = model.render(width: 40, height: 12).plainLines().map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "│╭╮╰╯─ ")) } + XCTAssertTrue(narrow.contains("take a few minutes.")) + } + func testProjectCleanupMessageUsesTheSingularForOneFolder() { let message = StartConfirmation.projectCleanup(folderCount: 1).message XCTAssertEqual(message, "Searching 1 folder for build artifacts can take a few minutes.") @@ -110,17 +135,42 @@ final class StartConfirmationTests: XCTestCase { XCTAssertTrue(project.contains { $0.contains("› 2. Project cleanup") }) } - func testNoConfirmationWithoutProjectFolders() { - XCTAssertNil(HomeMenu.projectCleanupConfirmation(folderCount: 0)) - XCTAssertNotNil(HomeMenu.projectCleanupConfirmation(folderCount: 1)) + func testProjectCleanupEntryAsksWhenFoldersExist() { + guard case .confirm(let confirmation) = HomeMenu.projectCleanupEntry(folderCount: { 2 }) else { + return XCTFail("expected a confirmation") + } + XCTAssertTrue(confirmation.message.contains("2 folders")) + } + + func testProjectCleanupEntryShowsTheNoFoldersNoticeWithoutFolders() { + guard case .notice(let message) = HomeMenu.projectCleanupEntry(folderCount: { 0 }) else { + return XCTFail("expected a notice") + } + XCTAssertEqual(message, Purge.noFoldersMessage) + } + + func testProjectCleanupEntryTurnsAnInvalidProjectsFileIntoANotice() { + let error = StoreError.invalidProjectsFile("/tmp/projects") + guard case .notice(let message) = HomeMenu.projectCleanupEntry(folderCount: { throw error }) else { + return XCTFail("expected a notice") + } + XCTAssertEqual(message, error.localizedDescription) } - func testNoFoldersNoticeShowsAnInfoDialogOverTheFadedMenu() { - let buffer = HomeMenu.noFoldersNotice(width: 80, height: 24) + func testNoticeShowsTheMessageInAnInfoDialogOverTheFadedMenu() { + let buffer = HomeMenu.projectCleanupNotice(message: Purge.noFoldersMessage, width: 80, height: 24) let lines = buffer.plainLines() XCTAssertTrue(lines.contains { $0.contains("No project folders configured. Add one in Preferences.") }) XCTAssertTrue(lines.contains { $0.contains("› OK ‹") }) XCTAssertTrue(lines.contains { $0.contains("Project cleanup") }) XCTAssertEqual(buffer[0, 0].style, TextStyle(dim: true)) } + + func testNoticeWithALongErrorWrapsInsideTheDialog() { + let message = StoreError.invalidProjectsFile("/Users/example/.config/puremac/projects").localizedDescription + let lines = HomeMenu.projectCleanupNotice(message: message, width: 40, height: 12).plainLines() + XCTAssertEqual(lines.count, 12) + XCTAssertTrue(lines.allSatisfy { Term.displayWidth($0) == 40 }) + XCTAssertTrue(lines.contains { $0.contains("› OK ‹") }) + } } diff --git a/cli/Tests/puremacTests/StatusScreenTests.swift b/cli/Tests/puremacTests/StatusScreenTests.swift index e8c2fb2..905ed3e 100644 --- a/cli/Tests/puremacTests/StatusScreenTests.swift +++ b/cli/Tests/puremacTests/StatusScreenTests.swift @@ -3,7 +3,8 @@ import XCTest import TerminalUI final class StatusScreenTests: XCTestCase { - private let hint = KeyHint("Ctrl+C", "cancel") + private let hint = StatusScreen.scanHint + private let hintText = "\(StatusScreen.scanHint.key) \(StatusScreen.scanHint.action)" func testRendersWindowRowsDividerAndHint() { let buffer = StatusScreen.render( @@ -23,7 +24,7 @@ final class StatusScreenTests: XCTestCase { XCTAssertTrue(lines[1].contains("Working...")) XCTAssertTrue(lines[2].contains("…")) XCTAssertTrue(lines.contains { $0.hasPrefix("├") && $0.hasSuffix("┤") }) - XCTAssertTrue(lines.contains { $0.contains("Ctrl+C cancel") }) + XCTAssertTrue(lines.contains { $0.contains(hintText) }) XCTAssertTrue(buffer[2, 1].style.dim) } @@ -46,7 +47,7 @@ final class StatusScreenTests: XCTestCase { func testBelowMinimumUsesTooSmallScreenWithHintAsExit() { XCTAssertEqual( StatusScreen.render(title: "PureMac", rows: [StatusRow("x", style: TextStyle(dim: true)), StatusRow("")], hint: hint, width: 39, height: 11), - TooSmallScreen.render(title: "PureMac", exitHint: "Ctrl+C cancel", width: 39, height: 11) + TooSmallScreen.render(title: "PureMac", exitHint: hintText, width: 39, height: 11) ) } @@ -58,11 +59,11 @@ final class StatusScreenTests: XCTestCase { let result = StatusScreen.overlay(dialog, on: background) XCTAssertEqual(result[0, 0].style, TextStyle(dim: true)) XCTAssertTrue(result.plainLines().contains { $0.contains("All good.") }) - XCTAssertTrue(result.plainLines().contains { $0.contains("Ctrl+C cancel") }) + XCTAssertTrue(result.plainLines().contains { $0.contains(hintText) }) } func testOverlayLeavesTooSmallBackgroundUntouched() { - let background = TooSmallScreen.render(title: "PureMac", exitHint: "Ctrl+C cancel", width: 30, height: 8) + let background = TooSmallScreen.render(title: "PureMac", exitHint: hintText, width: 30, height: 8) let result = StatusScreen.overlay(Dialog(title: "Done", message: [Span("All good.")]), on: background) XCTAssertEqual(result, background) } @@ -88,6 +89,6 @@ final class StatusScreenTests: XCTestCase { XCTAssertFalse(buffer[2, 2].style.dim) XCTAssertTrue(lines[3].contains("Third")) XCTAssertTrue(lines.contains { $0.hasPrefix("├") }) - XCTAssertTrue(lines.contains { $0.contains("Ctrl+C cancel") }) + XCTAssertTrue(lines.contains { $0.contains(hintText) }) } } diff --git a/cli/Tests/puremacTests/SystemStatusScreenTests.swift b/cli/Tests/puremacTests/SystemStatusScreenTests.swift index d794641..f749ade 100644 --- a/cli/Tests/puremacTests/SystemStatusScreenTests.swift +++ b/cli/Tests/puremacTests/SystemStatusScreenTests.swift @@ -247,4 +247,40 @@ final class SystemStatusScreenTests: XCTestCase { func testHomeMenuStatusEntryIsSystemStatus() { XCTAssertEqual(HomeMenu.options[HomeMenu.statusIndex].title, "System status") } + + func testWriteCutsAnOverlongRowWithAnEllipsis() { + var buffer = Buffer(width: 10, height: 1) + InfoSheet.write([Span(String(repeating: "a", count: 30))], in: Rect(x: 0, y: 0, width: 10, height: 1), buffer: &buffer) + XCTAssertEqual(buffer.plainLines(), ["aaaaaaaaa…"]) + var fits = Buffer(width: 10, height: 1) + InfoSheet.write([Span("short")], in: Rect(x: 0, y: 0, width: 10, height: 1), buffer: &fits) + XCTAssertEqual(fits.plainLines()[0].trimmingCharacters(in: .whitespaces), "short") + } + + func testScrollMovesByOneAndStaysInRange() { + var scroll = InfoSheetScroll() + XCTAssertFalse(scroll.handle(.up, maxOffset: 3)) + XCTAssertEqual(scroll.offset, 0) + for _ in 0..<5 { XCTAssertFalse(scroll.handle(.down, maxOffset: 3)) } + XCTAssertEqual(scroll.offset, 3) + XCTAssertFalse(scroll.handle(.up, maxOffset: 3)) + XCTAssertEqual(scroll.offset, 2) + XCTAssertFalse(scroll.handle(.down, maxOffset: 0)) + XCTAssertEqual(scroll.offset, 0) + } + + func testScrollClosesOnEscQEnterLeftAndBackspace() { + for key in [TerminalKey.escape, .enter, .left, .backspace, .character("q"), .character("Q")] { + var scroll = InfoSheetScroll() + XCTAssertTrue(scroll.handle(key, maxOffset: 3), "\(key)") + } + } + + func testScrollIgnoresOtherKeys() { + for key in [TerminalKey.right, .tab, .space, .pageDown, .character("x"), .unknown] { + var scroll = InfoSheetScroll() + XCTAssertFalse(scroll.handle(key, maxOffset: 3), "\(key)") + XCTAssertEqual(scroll.offset, 0) + } + } } diff --git a/cli/Tests/puremacTests/puremacTests.swift b/cli/Tests/puremacTests/puremacTests.swift index 26510f2..d3e7d22 100644 --- a/cli/Tests/puremacTests/puremacTests.swift +++ b/cli/Tests/puremacTests/puremacTests.swift @@ -95,4 +95,10 @@ final class PureMacTests: XCTestCase { XCTAssertFalse(Safety.canRemove(tmp, ignore: ig).ok) _ = try ig.remove(tmp) } + + func testCountedUsesTheSingularOnlyForOne() { + XCTAssertEqual(Render.counted(0, "item"), "0 items") + XCTAssertEqual(Render.counted(1, "folder"), "1 folder") + XCTAssertEqual(Render.counted(2, "core"), "2 cores") + } } From 83a51b9ce1c60ee2ce76d25910bac827cce0c233 Mon Sep 17 00:00:00 2001 From: Igor Churmeev Date: Mon, 19 Oct 2026 16:26:05 +0000 Subject: [PATCH 21/21] docs(cli): retake README screenshots with freeze --- cli/screenshots/clean.png | Bin 526046 -> 276004 bytes cli/screenshots/workspace.png | Bin 450385 -> 202902 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/cli/screenshots/clean.png b/cli/screenshots/clean.png index 2a544c4d3dd0395eaafac56248ab50e2884a9034..505fcfcc5a62dad291d30009854e295de1584727 100644 GIT binary patch literal 276004 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
H6NM3Sm8vnDpx2Zr_Y(gx=Vva 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ƭ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 z�PEtY=gxe{4=SP!x1z3$TLi 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%0A>XIM+e2+0CMO&o}3gz3VLDxX=8d_c@y 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

v?`TYPjh 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

F2KY_5(lTEpt~{rs9P%Gu`{| zzm&HBa=xESSF0&}yL(p0EP^=bzherw4DL7wjK8CFhMGD&wsz0LHX54Yd;H%J1N$gl z4(L1*$N2+*Lik+5yw_>ZNhtjjCFtT*zf#6+S0s{%$o@V)r^cfGU}a=r&_lnD7eJbb zJ=~@VJmRYEQ0$wyIGq}S8y<8K;&l8-K@FDnk>=*+^qh3Ir1J_+a)-kKZMzYWDOlvi zWpZff{Kqek(}$%#DdEBN<53GP9w!@k3j9hq1a%%RJP{IpFZ}LkJ{>!53OQ{U3^$o6 zqShzOaG-5>69lV#b1(%AF*24%nrk-)lM`FZku5zR6o=Cld=#CXohT?cvI716kD;`W zDkKi7)eE0$`i`DfpjI%+0&(NO95;N;5zgZ5RUtPR{Iyht%}ct#LpM`FfX)lbH~U`O zAF`X|{^fQV@CCX=95K%7C%dHnwEz(F3dttCQ9-s&dg6#X9|SvnxB%l^#qAW7l|gnH z5D*|S9|osV-jIu^7@#<0@;q7dRk})ran2~3a)j?8Q>P$+z|rPZd1y9hD$2_@huS6} zEs#gfg}yluCjF&D=hTpq6ZIQ%km3wnug9b)b+l2=Or8!`#%->9gP<6rRD-KyRQAay z%;CSpuy=O1<|wozFg@`FO_J^BEb1--G~|-6b^mSP1>M`~F+jyYrmao;7HpUz179k_eu}6?kh`J2N3x3S2)I(^r%#Q*FUs8xpi}f3=AsED zFf1c-VxoA(+1YK>-rD*StxI^0U$u?fIDD@stJM@oL@CEO48D~P2i3CZ;>dBa{MB)|sp4Qy4`(jj>B_=$44{=1eG&k&EQ_(W^jdk= z^@Ldzj^G!!eGJDCkGGvF89ZJdSVE1cl;-{KHxnMCl|iif*F!Rgq!bBaVB zs*Tfxd-3U;T9gTdbJwU6&r&QIN?8ucVM^s0~j{G!w?b^UKVt^9DObFp4XquC9Js_`rS0 z>5O%~RR+?UfvPBqs3j3@k;D@p8XTG~yJ@Mnpo9Ri467GzxDDhF<5kg~o}LLamQ#Ha zKadrBMUPK9vdA&vYo2^;-gLa<9Hel$-DDJ<_j*e6d+4IT06pCErsC1L9{pdEm1<^) zi=n2x&OsI0Nb-?h|L5guNdLcpfm!O?xnOSNjszfYF4?r$RjA5zwA)e&3k#`P-G6sR zg)rf`W(&X0%ShogZ*Ep6>@-mogf#4Z5nbMok`FtafZ3K6fJnmB?-e2`ld$`-#Dfu5 zG_`nR8%TQsJfJ}tSu<3)EBx2z42T{etHauIcVbl3ML;!~+3E9<6f_i?M`wv~G+a3Ma#ipk z2q+k^GoawJ%w975bPrYIh`!s@L9QaM6kn(qDI80o5`>*sf8I zIL2egDzfYe!@Ffv96wArm)&(K-_AN{Xq*S?6Vb1iR6g>*WKs_nD~JqFBO9pI^X#4E zLwBH)lo^?f zjRN>2lOEn{rUu*-@yJh>KI|_%gvzAeVU09DI$2IHPgH~RTMlub?M6`+k?TA$@$<$0 zD(Ey)(ydkRov8BG)heXOVVCb|>Yut(9cXCnbVp4-sdxjKMkVg<6rke5%iwGQSJC?M z5Owi>INcG;9fRas5`0i($BNP0pMJHxVHaQM1d7<&j^cUCzuro&SaKWLu8nggPb}Ri z-7;=xwo5i|+w_P=uz|h1aMSFVjq>}|NJY;t!Qb@hv{y>yT0x}ib{k9%v^|~db4mggvI(J$Dq55Fq)r%K=|1nDovwjYK|x| z2#ZM+74R5U!dE){l~5I{asyZ0;>zXoNhmTtEDjTM)u8md*KnsF{9bH zW|xl|y=@rZ`QXgCu&bR=fpVI|qaqT#FY?&D*dKyp&xzTKjgK!79;r5St-9urPt~8_ zVpvsEQ#jI+3-TV!+6clWH$*}Xt86#FEv-HPh^q`)@c}XEEiUr|17FSeC?-h z;;bGVR?}XMQ1-KMyri&kn|y|K=w;HMuPaxCay~vA4}17~?_=AWo(0YOY1&AG`Cpbh zTw8bQ1^i~e>RmhTf6nLrRC~s!v4Vne7RU3e0WGUv--Y|V=;N!*8d`fRD>1>o<=6`{ z4$C_&Y42w~fu49J8Z7_}W6gpxI-ICZdIdmTi)N=zVC~?x#RBA4=fZrO2l6||y{Qi% zfy6BmO-Da~Zuq{T$Mh>NR)-^2CD59DYJS#*E7M-c=+2#jktx)CU`Ez{EL>O3{)1JZ zYn(pvuk$p005y1A$*>tR<>TmVBKe-Od8^6j@@enfX|GdjOZyo8*g`GTw=iz=Uu@3# z7;ZDm6a48Ccc8F7eXEAbE*1{ASzNrOvXt(+r52}S7Req%P zZCb+ zYf%L3;Z)2w1?xuG%Mop~ezKm;e+9sje@Bw(+La29O&ljsM`N-H1QMddU!XP}w2sJv z(EC7vID*Lr;=b({*M0aY&Rs0$W02u0)1bzogvd7T?Gbqi&#nYII*0{}ZHax_cf8W? zlV;NX`vY+X@8h!*NXn^~-~Z|EWWrcs>0cG(drNP^k>u`V&~|HA-M4h+{C>VK3=;t# z(z$D2Ths7ce0|k!eLV1q-Q3MHEdBO|x<^WmO&cHkBHsKU&(VgZDU!^^2b3FCc&<6k zK}lU03=$kue{@+aw2G2ReD`=K0$XTztv| zVgE#-Uad5&)UVD;d{CkZr8_)EiEq9Jer*5?Mz!ddTinaGj)HDdCnh+xyFnW@ z1S(u5$lRb@c@5Xk2I>J^D=C;v9knc4?j#p`YQ=qEUY5(DNS$zd3wKBx%a{9`3$Ub* z=n1&)n#P7|8Gr*QLQ^r=>8qK#Chs^auY_BOT=euA+|h^S{*`NRpl~O94osp6PReNO zNH+9?M1ySvPx1f;)Ev2;#>Mm^DCCI|6)YIx7dV1O%VdkL&nHd!sfeUgs!hu)u2mIt z@{7vhMX_RG-L|SnCyL}MCQk6MNiX^~j&#pvKYDm>b@PRgtUsdg!5I^8!sHixqW-j-h6-l z8g6pez$;tL7W;&{V;?rx9*;bGWt*V+|xRW3dUPn+{q0xRDLPHbXUd zW4@ued4Cfx_8Kn`j&S=qMf)LP`g&T+4o!tr*uGBKH0RHJ*habk*5OrrY>dBuoS64w z^cfr&04EJrZc=gWegOf;&&-BVXF?JVF7+D0E<1p(zxtU^x50Ic@KznYAF&)-S>;hX zMM(G%21Dj%W+jKNmppFGi%{EMYWHsC{i2{PA~pI{N0hopdJc;|&-^g`mkB7@b62&1 zqYut$0mW>~Hc}RUfAP?+YnaX^00fZTM=;XcfWeald~E@1H6iLaMo&++?W0Uj5s*-zqkp4);XMO=CM;7vLaM`OZ% z!d7e7-kyj46Y(ekjsLX%3(k7rk6KN`9W2yXvrMsc!tg;9zeG&fL6^`yb|yOc=9E&(~aY494eeF_^U(ouCj;A zkm{W~nDL*%-Y65aw6rutgy*$eNF(sD@l;ryqp{sYn9Fx|3N)!HC?o)-Oeo=RKe#yT z#J#r2zIY)2$aqzE3*(w~uSLyD*0IukC+o*ky#*Sz^d{`bpA1hvueuX`XFAH-=U>se|%?<3%BZgCF=jTT;XV5V2$bIg*#}=bv^Dx zecTvT6Z5qnS8?Cs9GPRjfiPh8=`-Vfjf`=uHIw;vC#$YvOTJ}lOw|@aE=Is27~+=K z)Qp5C2HXf(07)ZBBn+kjS%M9A9cY<*>D^cu72&r+7lMG72r!!?3OVo}Uv`;YJae3jOBSE`Ixuix9!M%?K!16alhd4* z@{<>by-3gj0nh_f96=jUX3@bq7Dogbpd{W?Yo2%*ge@sB$N;LUNi(6aEpoI%a(ROJ zoyG)Ui5yK1=2K{jAZauE`e7rYIe=HwsjE@d$D1RpyirU}P2EF~Qb3au?InbY>kzZ_ zq!R$uwot*DN>=VHL8ZD016>~<3P5~Sqq7ExW5C@AZBHPvCl>7rsl5)XmDSogcDZbp zdqb!6%)c-~X?PLEm}jk(O2m)z`0fTu>hnPKubY}qwhR)C541!3j9xdKIdv)uX#fF! zVxZ9{2JfRf!3wW0tyk$rXYF>q8n+W}JD%nS|7u9mnMFvMg

eI{J1}=MjGk4=o5AE#c)DKXJ&BKl4>xT0VNiZ#Zrp#Awv1Zwjs#cWZ(B76FkAoW zM+Y-t$cPc`4Pr$>VG_5s$ukXzVHKGAc(g5DOH8~S-G!OblMber(^p8{Yb1rKl>|aS zy&Hqo#p6)9xv0KaDKDu-Yi~g`Muc|?#LSL1R~biGQM?8IC9wQ0vkhvmU>&z`O6nk2 zTxt*^$r@q$^%~o~SnMcFBuW!f_KEQPO(;DiL08+qJ{J$d`QSW;r=*m!($HCva9fhx z2EGUcyz7Wt41~YLRR>Xm`bFsfLw+_HqS*;$M^(eu{pra!{uxF-Nnk2V<*fqWpQ*oc zau{}Q;W-stzQe#t!G;ocD`NbkdVuq0ro97^;(GB=?pO$8iAi$_0GltuJI|S!Epv|Nwqf$2uJR+=?Rs{nU`fV1z7w;Uc;hQ*}wf3od#RCco zN5@SH@Q{ZgAalB86`iF~sEpM4EoIfu%O(oYUvA?uvy&*qNOf!A!vnaHAXH8kljN0afNtFSw*;iXy~#BayuIvwe_x`4Re8k z%LKAOOW$;b4m6RkL*cgsKrgx7IA5xJbuPyooi+Wjc6^dz`qi{9(zxXTpKHuMh*3CH z1bMFsI=4}T1+UDq@X`<`#AS*EzdzjR{u(k@AB}Uo_8LGk>19mJ?K{@Ey@>|4M4myE zUJT018CPk$TS?b=R1kcdk9zS(LG*&OH0ZdhOAD*DiZ4rx>v`#N3d7p5cGIst-#Wxv-^Ib6H*D9^bxpo4Y6K%y`FqC*ne_Dixtv3 zv&*{tUDDB|2EFA5&4aKHR3?Vg6|}6;R$n5vI_v-xg>Z;;ZZ}aRsyZgYk!HMMGoFM5 zJ z(B&DixKf~Lo@p*%Hyj%%`E(zWdqMQ|4;a6BpVdN`BJG~nemxN{XDgW1Hc9O@%JpLx zx;Ry+?_Z~JRT(uEwj6^#*r}K#2(1$e-}D&jTsJ*P=_RAHG+iQhw2QZwF$l@8_L}U zuZmtl<5O^LvDW!!8i$&xX?o#ovdK>ZuqAM>!nxO}!w7D_FYhcNu&TGCsuT5?GdDs* z?dmztNm0jg(BZcSy(h*K&@Z7{CPuftIqm;^_b`31OWdnp1P+;zsrF-ryP5gj1D`#M zOodw;(P4_Cl|~6$xYB=e6p{m>@QgvX%LXPnv-=$<_scGY)tc*6?1;{E6sa^Alm`Uz zH91{pd8MUXFs`rfwg9H7DVajO&|D(U4Bv1&$0u;rM-Fr^ICV{j&r1$3yisBA1Qm0s zjHfUX%o~@Sh*wqx5u%S9%e)#>YGF&|O}MAKluzY%&9d9iMAL`Ot)||7J?hm+Z1=pi z)#YLv%4s4AA#|a=U^V%~q&1xNmOa7l8pH2Q&U)B_AAddncEWzCT33+Eq`cP7zAG)S zwSW#t&rn~5uhSez%B-Aq3ntmmU`m!4nT(vGr&T^_j`YQ#)>)44-_a`SAtq($?(>En zc2z-V5Si3F_lf4g>0#u8S`pwr?}qJLp;j67I+ew3ebt`)`X7SAj>s2s>fimIJaDX3 zM|&8+SFlR=^wXm>!{59vh%{;3FT8(Xj+UQ3quSo6t7XmhxNvtD-?hetn$3yTS$}3# zsTzd7vKg|vLjGtShbsE^KQQ;VXkOxK4kkVLa66!+rL&XvvA7OKojx<;3?AFB#Rh6V zp|*7NaxfLh5HtR%c9($pQl|7yFMeriiUUN9#AHizRaI33CgSP*OTJE)6Y>;?tAHt# zuR3Br<8T#tt9)~7bu3EAuAJ$t`<@-6ZD+*}6PWodoChd1uEV)u_{;vn?;8m^ej6Bl z-6@MNrR|R&7wT4_NPc9(8m>;{aNw|@tU@)zPB@pMi+#p}1OU4Z5^9VRNY-tjM4g4d zot>fDrT`zY+3@)S<|qX)@Mlojy?pb=%0Q_4Ec&-L5RYe)^7eAFdW%is|6`Njog1OG zD$qX$kIK1(&~4F4R;2U{v@rx=Q-|pkfSPe8AO7AH$;gvG7#1i#T=I{zwfAVA0!=?#n9TBD33kz<*}kC%rb@t#rhC?m6Jl zT=}Bufd~{$PFD+Lf7h^7?v)ESyOMq<{Ih~6`<(vwp$?kbcXsg1je`=7@G>I1)-I`q zvi(|~!G@Q%0kAq?dsGD+XF}tEn3zFA39$0oty@u`oPdX+gh*s`M>Kg7grP))&kImL z^3>~&Sgh8)aqXIh-o)r=!~I%;ADrdFLWiWzA2c_03?np!S$64*@2UZ^0OLn%dl)}% zANA^>q+SzSAOJ0dDuf`6(+fZp7&QCOXyFUrN=ZqfTjp=fq4Fe1S+IZ9Y|wuD_U#hx z(if=yiRywx3fu<$r&JK>h>5e&)FOv(xpscIw_q-6ii@!1w5jDOq(fg~A*(C3Yy7u6i7OLypS7uzYf-qwtdj(e9g`r^+#A=gQ)H~72%nvfSmRHM z+KCAW;_9lb;&O=hW~Yw^Ib|5_W3A>DXm=AsQ5hNaS!W^aAWb~a8F&fVit5sYdMv-J z9pnm|?7hq#V$^2R>ha{}k1dX|B#xDpUZSV51mjMkYy&%3`RCA>5^O5r!4#0*_X;CW z0#PJ2kG-ivauygm^6ESa3FH_eFDHna*p6TYgXtFa;lo9vmb43m4w`-jhQ2_T8 z&92sY?SGCoI8WY(y|9OeE5y!-lgn!}lK}p4Ss5naTnWSxS47QBawjhM2LvG{AmF2V z)b7+?X0@WCTJ!WbbcJYG*+BGRyOt?9YjGR5e|>}hvfT*WwB2jAkBCBOZ1Gw~(RY=|`ZGokRA_6ix3O*5Oj9=9YiIKDN*# zIr8mttJYS}?_R49%+9^E0l|%+^?v;5g22`Y{nw&y`q9slKdL8gRBVKa-ln=I@o8zF zXHMuNFj^XRs@uVPzWXO&MmJ#)XD)>6dp z_BCRU;{ktmK)2t1xxKpylP=^{sD?2^NmTFq)$L@|fg_WfI2A&wH4F9yNIHwQ@ddDY zto5!;_7XM}Jae0eiGYSe9C!ck$0V`TThFb<@ih?Ae7bGrkYk8hTS{FEzRR5n?1Y50 zzZrGNHv7q^>ZezB3u2EGWsd`Vzr^-PgAajZK{M|gPSzJfY63I_ngAkz5Cs<|k!Oia z_1mYxUc_X3qQo1XI4G;tI9=5{IRr_!-zCll#z69%p!(70(@6wQ+{ez?hX2aW{EUCH zgwm$RmH8q?I*=DXUtdbO^-Z8COLm{7`Te&UG_@`lAs5-s>A6Ndo;S*lJAHzS;So_> zA)pcSqD&r|uXK7HmO3XKc#>v`j&Tu+NUt^rW-WiBpqe(y>C_1(@96GMWe&Icz@g>M zfd1hK;F6`rREJnEhnZ-Ux6TAf(w~|&*#;L$U3xyQCeojqg)nxZ@o@?iJ%Dk;z`N0Rmck z>gF#b+6%pIn~rSs^rB9w{c(m4DMfLeWO(p~Ybm=>M%LQ4)eLv62WbsnO8s|B1Q&S^ zZm=C~Tw9_RwjEh+K2D+x=@aKEth4eH_!K=O)E)C>nU%b1lbR4~ccD{48I9qw`Q&Fu ziy030#wu-(7!{*38P<_$`Z8m6X9H=c zkQ59duoq25B+7>m_ZZ*}=Be9o1I)~(ItnD2)`5gcyt9Fk(HXXU2w%p{9z5%yj2ahF z+QUA(^$tN0#jd-U-I`;f{!uqGN685yy%MRLB4KIDJ!Z8@U@omi`T~h8H0?yhlB^P-c!SHiGYoJgh-m zK3urI|JETc=&Ex_c?ataJYfw|?SB0J#p)#enha4?F|jFlvlrcjk9I^8(d2C4(d)wT z(k$iJJ82{2v5(cAK2bFS#S?76<%E|JmWUD|Xdjz95BLBe=q=my`^)>m>54bxdQ1|w z^>N^*NRi&owHf{>BZb$G_!CGtTu(#js=)46r1R2^yXfJnK#v(6JJ856!Cr^wW=KLR zA2Rc)nV7T|TJ04IE_^ZwLW$eL{NB`F-9jM~g_~@t&Xk`L(lCLRwoHXFIOC;zF50a6K;<9kVZ`k@G5J@%dN?a5hbL+HeKau@g{vQ-(hneKwGFv!<7~7&O^dvV zo^*j}?mqi@c7mP3*sT~>a-z!bjdqaF1e(sV)8$9K z)1#3H(7CfCKlG^&^GfaO)2ib)&s{DwjNP{?l*8J~#q%+MYDwo+WH7h+s-vTefy#M) zP+mWy_omtj@}-mhM@G=vFXeREB!*k{xO(SoFK+{)BDHpC6<%;tjl_K`ADv2=e{CuV+%5sC zMkH{Lg_X~CuMr8@jT^W193eS0>n!wStsvKOLX9-QQ^c9IfB*giUEVY&Car`#n11d{ zNHj|JI(+?OzZq<&)0P)u8GTxRO6kp{!t9dPO~7}6OP87*NzG{!@p$Vcz>1oBmie7d zJga5-KWD^Ha-o?P@;(1)5Rj;qwQrr)q5h3QhgRd=j%Po5^@!raCB;1+%6^}W_B`=4 zeM%E85zkk4^;TTi@bKb{PmI=lb$mlm#qF}I^#VaxE#t%V%Q?f;B}KL~wTVW3q)5AT z{`@YH){Eya2Sjljyq#Sx4!BmZKVhuN-lTDUd4H&F_q1R^sBPE%3ES}d8BBKD=>_@Y zu1c-0+8p_#!(r31)zRdsR(ccwTm&0IWD#AX{I^#cFnva$4JJ=#+e;berQCbkIptRf zRyb__7}AeSTMvdc$5yZfs@#)^x`RfXtLvI-I_8PdcQ6SxEu#*r)UAGA*ZZ4quY9R8 z1O`Cgr6sMvqdigf`Ugm%Q6@6a>1e;j)+iww;3A9Z`EKTo1oA}`!Ib@&J$6@L%`oJ< zr)oD@s<<2uglol*^$1;RZtgh*?8SxT?xp0b{jm0P1KRe8IzL`9SV$e+TxPoy?OS7* zl`n9&FJpvOnp!w}3j}lcZ_m?{p6Iq((u-DpIcHw>A{7Omc7rry2lRD<5KWk&CPEw98?t(A>9v&HXY8UGX2y?W!>q= zBEXZYdXGEVgx;l0yS?|L8|^dwI~ArcNG5&GahHbu(p{$p%x$BORqfdO_-37V&CVC6 zJWkXV=&O_G&!{_|JvkEUeYdZXZ6}}G61RRNbK6{#XoI0`)a0OYw2^w}%bgF_rC<`) zVPf7PRhhK~)tLXzSU{#mMZfq_ ztY-uL!uh6oh@+M?NDFn=KI>PLX3Ew+6$A-7LmnVCI;p#7WmJPCnRefY z=s@7;M<^}BV+87+DPo+&&FU%v?H-8!2WEZVT)(=kzsECM#NQ9~)<<(_eN7&Ysk4OR04oB05qJ3XkZo+w@Y4`TD^0;j;9> z@$tD5{cEQS7(`Wg7)7gj`7YPI{5ECEIC!JXg|*g|>iQm!D_x$RaSx{t>3@9wjB}|s zkg<|asV#coSzo}|W2JyFmf)t9k!Fc)c*-tuuZu>m(~^>-a|PTkJBv)V?B4CO?-2Iv zZc1h*%XY%VSqr!_BwP<>>U<)!v|l#7MYEf&a3=O-X#}WhI;tKfI3=zb0Re?lcKLwn zGp}~36%+NJkuKWf)vYUx=v{FiE<(Pac@<#MbER=?>V69@_Yj zSJ=xO5-OR!g#z-~Q`SO^ zJWElIH5T0f7{_J!AwM`&XIg&w{u-BY#~UgE8#6Dhb8@%~3B^zQ>+&KcKoo4vI#AY7 z_+DEc>3+_HfS_+&Yo;n)I0_xQO9Wx%rn#E94o4P!uZLOHASnv*43gtCJe^;xnS0@U zYi3lMSw~@ml_-sriQYGo-i7B<$4b7h^vbo07GF`osB%vlh4HY;A43dRY2m z{@C3t@_*i@11S(~ZdsTmpV>4%9Hkiw)uh5Dzn|jW&{5ean zHBZQ3by7XbX#T66^G0hf`=uF?R!BGY03t4{E5Z^V#u3?1Xo>T6uE8gD4^%K6S5ntz zizv)Ptp|c!GY}XB-Im_EcH`vQN7YSc0HOK^uXA;;7A8{)Sx*WH+33f4s z^r1*AG`I51?qqMSd@J#LMRt|EJS9s;MZn!OgT_~HU?NQ6Yjrj2qOFq8z9UCQ-5$15 za9w3+Uz0bnki$@g3&EBX5DfSIvC5tiWP9qYa|*{RExNyrN)#^^M)>f(9gE1c-*@1^ z0oy%S;BN^k;=I9nrQqcVAV{pnP>`f6zeltoONq-$@Fiqva?5>x->kG2DkYdI9o){P z+JLB)ICp;~re%DkM#W{U-0Em&{oNufTqYC}+Yr?`Eyp_)-rW5v;dO$Q^(mUMOqI4i zySP3VMeJ~zm{`(9YVqRa-X?O*7qtgN61;0AlwxCx!aKU!+JbY==Ebr^^>AfIf8+5{ zo);A{yUiPAR353k@a7=6n{>P%UC_j??q@t;@U8$0OfQM@+M z=rTTWCxoV$o$siVy6M%Zf-!mL=+z*esa-Oa+SU*19A0oLS<<;3GMosOIudQSl?`zpbwB&qVd){I7 z+xO}Yr9$Rd*G1kK(zL%xE0gz3oPaK0b}I8r@+Zs3a-WSk_*dMvQBg-0km|EQgvTF;BAUf)+3nsgu8oX6;{T(?!JVi6#P<282nnS?sb{0~dQ11G4Gr?P_Rc;;M-9K@;3a+h8o1zLR zFR-5G_3uXUV~XHij+6{T{S0vTrUeNktgE4}&h*2U76DT`^4$WCES=p@fw+bGh0vUa zqu-n@hd`jwqmsqJi0)q3)rL52>6LGWYctYodt~Dzhi_!tElxR{n}?H5j~i=>3yix< zsdYnl!?Q?Ia_Q_dpaBDCdFx}YLA5hh2n#oRZtJ20FV#?lqtsgQ`6z*g13y+|$PH(X z(Ptmi)le!T^OCTP59QLm8g&QNx#`09cO8n&3mk8^raKZGyQ^30*OOm|2C3LusL?%b z$8&QXE7|3(Ly#79-Kpy%_cego)+Z0&=!LzAqlh zznB-XgL`Q(rEZPGTd#ITG`QVsa+B(7EY$+~Y?R;)Puvi6TwS4LIsu%k^wNG+KNfnI zd@CyYeQ~Gf38d=X%b%I%O;c1lQ~S!(2d|PY3tZa0w}=bZ1}s`>lzZMiJ}KHB-o`H9 znAdylpw;)%vtz9Eo;?{_7I`dg2?dsNH`a!^cGKGLu@s`7d(TCo9h5haKzbj{FCy${ z&}quD!@*ELbk6?(@7SU1_m&cIrgqsYiwTtVn;c0=Me9$`|Eqcyz_$<)k%Tm5x9`3h-qECJM~A^M%c$t1oyyzDBhGNjG^yQZpi#HUFE{5doRM=c zoc3W!87jCm{XIx`yGzU;o|1WM(!j1@Fo1*}G=L=M$9?$vM-rrLMqOn(pZ1 zRZy*$S^)FKXTXafeCiD_z|v-P)SnC5+f)Z}F@xAr0L0wQWuEB}F&Pd>xoa@7Jq)>r z>HCfQ87d*kMFG&l-iCdXCq_?`5>L(DxN_wy(>YA?aS_ypq*UoiN&o`v_?UCYDGMvD$R?U?>-n0kW{LLMXo6jHysK+X}?sJ+*5_qVG}V9%$znS+n?;;L_gm!BcZj{ z(bDpq<$$1_Re)u<5?;am;JJ*P!|Se{$LD-W#EG}_T?f#0=Tnk{eg*7!p3<-Uxmj$@ zfru2IwBq?}F{XCJ+!aU549Q33{QDtPtKb4m4|Ug~Hsz*(3$mUJ zw~l13&k8ew=xEHbzqaw7%cwqI#DlsCH=Tt`QFbs%6|*$XBY>ls2EPBt-kXQ@ysz)0 zVVTPiC5Y)aS=CBg0y7H%K#d zl!S#Nbph*F|JelIar^g=f36>DF;*Z|Am%22^*R!aUM<0ZgC;Nw+m@yAj2Gk_c)5#^ z&1^gApk*`U{$s4av(t7U=^ab*f9!5gmBt0+mWr^fk`k?O}| zBrOzaJd|EU6LPBjD#aywZOb`p;5%|^Y7;gQ8J%IC_8i`Gku&x;oZRR)`|L1*ER}-j zYu~b-7bFv@#LiwN$2zbHY|oRA!7bw8P$I#`qpmJmZNuHQ6Xua!LO^QTC-*DV@p-L! zxsZ;e?@com-T%rGGXiLrx1%NEy;a6d7I%oIRgH2yh>sLAv%abu&@{+bR@Jf^z2%5f z?ma*V*Z6x1akRL#^ctHtv9 zxECwaZ-nWIs&<#}${<&wv3pL$_`*A>o;Rkx{t3Y^&LRlrrCPL$J-IS-aLw_0mCr4} z>AZV(@7nbx{kn?{{_*xN_9OFX&oF}~0u-Mz{Dep`i8%Br(@9X@N@PNblK7O-qE@)#cfQ%lE;rBezG zWV6SQd9v5+!7%>XiXW=UE2EG~lhG_I`Vy<&NdlygH?+|=G3f}pafY5lOsFT8JM#Lk07Krn`EBn8&K~$$>@Tpb=j5x# zl&b^RIV5%XQgCfbW=hsKTt{Bw-Q#&pN+C*UybPJ37dimB-EZ+ARN+B%0G-F`m-dpQ zp=-zFr9$Vs0-#_|u&fNHCZovh*}FGYUe(ol64#?d=}X(fd~LJrs!&9(c^pEwR|D6H6yY?KpUYgmp}sq zW_6!Xi3>V-Rr@`FpLmRqXxBKE9_q+N4akV3Nv;T|cq4T6x|B0%F=H__k8oEX!6Ln{ zR}5uG(nDfC3-%5R>V4i^_(WQx#W6*0?27Vv_McoCLdUgT%s2YYn^b;kjiA_e#k_Lp z9&=AVO%3|>`HjxFyu^TS;#u1-=IL9)!bQ)u3?Cohy}c++0I^TD9v}@dA-8kq%|0Xa z=+dv^08-o7L_x;Vz^aGc^%8^-EzpCr-jy*sjF0m6GSDp=T8E`Uo3T`V7YOk4&@2vz zEx!BPkjuaWfH%m)qs?M4+)bb{qQgwhOT-$P*9kv_K~;g4P4kl-SB;JD!BEONjT2|7 zG1Wp((`l?G_zRvCvtIuFuHiohCU6e(A*#>#6P_maak`dL3Xxb==sL#h7y1xC3$Z7v z_!TOxo|;#eJvXM5+=H_C0Jc>Y#mLAbIXRi2hTiQJ^P|Pk7|f7}MVu*07gP+T?X6`3 zCgoZik`NQv@+`QeGgz7;mCxqN=QZI8wn9FFTI0@J0OSrx4nOkdX~{qi#o4#f;{88w zxX|A>oLuGNYt_&>VuJ9AMg0}OV~COn*2Ga!4-Q802$HtQ|I*(xUOad19BB)X%2V#x zvAl|5*lK_Q&|}3dE6HwWXLx`5^D&R%dkzNq85&gY2l@RmDoR4vDHoaq1!vOcUS5q= zta#YQGLzS%_jUUQu_v2U>Afp#G#OaDRwZ?b_njscYZOTI{K0{d*xA$xX7wz1A7J)FODMCKD?RWySO>?r#Rn!ebcx!bCE@D21)8#O7}Dv?15I>tNVEZ*vn`_nYef5WM{!? z_5xDDXKfT9W@S8EqeD}kMTY+XqPaE=U0~yh!lQ{1%}o<>GoHg84Uri2Agfxn%#-Tn z*dt(7u|PYcw^lX{Kr@!{z{h#~S!YrC`K>y2k>w3Hl7m}HrRHa0Eo(jh`Om}@a%(@% zpE(AN+~|w(+_B(ZpZN(My!`u=IP0MkRTEW057t&$I#urIqY=h#xl^G|_RXVa5T1_5 zH`A`Z^%+`zo^eJ-i2 zIsw8EM@aMCK|OHgBx%KYBe3l)7#*0WWqYHl%rzm5w#pvS)yf!iX~NEe>8A~kc9H&p zA&3j4YCxkkn51KRAisMILnv!|EV>(e>u$iVAP+@N;Er#JMoMtQ%qSR2qeiH*&UCm> zG>k%F?_Czew>im|69;8$20o%d7q>z%egT3>6NIp4n=xYBQnck@GfQ<4+STqt>bC~u?9$v2H zH$JZS{+w;4WA?>F%DJ%KNm&p0I}sp#=7*!vv~yto(B;5bMb?*@zwaEy%Eb>cN^$EV zS_kB%gH=pe#VjeO1BG^yJC`IM=sxT;$H^wAxs4DVz&n(L7cwUxnC`^9YrMW51m%PD z*WnoEi|&Bk*f;`ygy)2Ay6;&v-&i8x_$$}lm-aw&qkv;=t|%?LnLS7Hntj{P2dCw# z=LVA`J#BJp3Tt#W45W2e58P^J@>}cOsv5+h>>?(WKUWd7gEe5gQ6&EcE5)e_uF43& zYCXH`F>m65fcRr;n5Av^>&SPpmuw*Fn?EquKal_Sa?TmsUZ`lcPrx=aA(m1HEJ0CX z>;g4Ea4ifrZNsARB6Eb(h%j~I%knPx);<7*Mygn>)d12>YJA%_-G%1R-E5S)?X9=Ae16f>MSJ2zv`)}YGoplkdClBm`%Q%I?BpSF5`wS z%uuORXiI`Lg)LaV_8fYl0sAjYgTT)}bkJqwphXdXioR1B?!$J~>}lncp7ANMG*Gj+ z&yh07WpKI6I zIDQFl&N|~RUo=sbh^y+lQ{}Fh-&d7jrc3%#`V*vQjI6zY1UP~Q1J@XOEEUTY_xklt z%qejYjv#tEKX+8l)x5KE5t_ABA`nfkiOiYZp7Ab1d<`wHJ%5ckytp#+vGbM7z%A*a z&dcY->`durzHe5uQMJ{fDT*8~s--zG4?MKs3;8gTR8&(f*%lQ>yVSn(+w##ki2NFA*_pkKtGuYC#X+<`YHO;{Ow9L39rzxw zUpz2ZQQN^w(5BBbiVS83_0R%dulss_+;(^8qdLC(?klp5o6zQPbKOVdJzZ%E`><{8 z-1oI@$&Ka<$p9!Y3l-gZu#%ZcOCE1qAY7;EYqh5ysWicRFT6c`4vHPy2%4E|<>5a0 zgHLKRw&Impu#P;D=Nw0Bitaxt>+f$ChPD{?ZDK<#D*-fRu&li7#E90Cq5ra zUTttPJpEn-X?iNjyC4I?cU%(3ZaB|`c(Lq91wO%$J9E3h(dCP z(1|);Tj#cxixcckzF-!vp%$LD0#1i$xsC~JRYLRxCKU2jEfj$f;v=Ob6tg24A?

  • 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
    DUAQ^Q|R-lc!lZc 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

    -1byqmnMj_w#Z6T@}_o8W)mHV#jY1=}};6)qf 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 CmlMqZ literal 526046 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�nOAF$=h8W?2cFT?!fBT2MFWhcI~-j3>LEe` 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

    9gk}5;w}_BM zPxlhzCXve5FkmiG9bN|=IQYHaXO4#b3XlBA2TXdL7N`klx@G1>K<_A ze0zdPvuaP{S&Q1(_?N%Vm8}yYe?H{qBLylfw+3WL&{Iew3+n^5TDOvvRT{yAU-Oai zA9sT%L3o~nL+?=0`HJ-#fcHl~{NVE7i-i40k?cKJ4h6uO=l#J9;yb`>@(pfRDSC+5 zgR%sC`9i3yK|ImmwKz(0QqFSF{~8>K65|cZZv?=@x}a2{fwt%(oY1NOnPhm%oRraRzg-KK4};(^_DoUy%e#t zLtMv5K1%yKy86!fO%YgBK!e8mz!mEX=K6Eq@!>mn7_y;(GOv&u&> zCCmMuFOJvUw?#V^$gyK%OgQU)s6RSEt6U%R-f|e~#T;raH!bJRZN;j7k8wy~8qYTj zxHMNDoBH`R2%A@SN=XtT&8twL0Iv-OE}hqp)7^PKo2w#NYZZbqV;x%>5t(I&?l zzUHBE%{SU8)TYWfubD;U69kczG(B8EZAb+N%#%0t1>*&G+T6_-9RvUh#Qm+LV+m2- zJ)=%QuFdE^zN@2*Kyl3Ny+@&@mwB_36dI@1Lu;e)0tb0Y`&a)KaK=0)Q-KY)YFD=L ze_yqU&ONBu^0{HqlM9r`RHkhNMEq3_*rs7imv(U?haK?2T(=gqB!Ro8rNZkX)OngU zY?V%DcNQ@MQ}2(Ic8`enF3w_(5%P4Pze6rv%M`DmiydJi&(lMYB zA6(L_;HE&vi=xSuo`MO;0%PquG2B!}@VEQRG*Q7?1COe;jU7Y&Iz1AreZjP71jPx? z{Bl)rLWf^xNd(yz;VYyYzlxuhFqOXbu!g1v4_=4r!t3*aR|hs=+Q+r^JimEc!%h3M(rG)Lw@3u zp5e+Ms)<>#i9oY*A11Dlz00Hbt}Ml>n{U5(|Ay1wBk>)lbfW30YMz@D%oGu|2#XeS;n4OXU~_s9 zJt2Kbgi@jaMfyOA?AiNJSg0EaEb7Su#v(MUM!k)Tso$|fI`}MI9A5%f20f-0+R1o2 zXVdqed*W@tuoYOZQ38p&-y?N$#F>dArpXASlJX{o(>b_^RdwL#0^Q=)_iPRYWP(cBc=5<3P1Kz%2%z#!DqSHSyl=y;*E(uxazPfXqD@})$-cc8lV zC0*)4%T*~`p>OjG%yq}%ANk`lwU^L_u&tZBjeqm?Sn_`!z*`fG%)Z2U*)a(o4Ro&Q zmbH9Du{BJ;L6#2lX@#H4Z0(ed1@|s_5pqP%E*Ll}#p1cpxKK|>OzW4!62`?r+?Ig% z0AIBC^Yk6`5GB@|cdszPVIRaMTYVs`)8w&2+U0A4w~ERqK>!!X4s5_&EzGTQnQ75u3wnTreF#F^OuF9K zU4vkNmy72z7xRU&3>wK#qse5CxmSY7nhe8_B^Lbv+jVV3ELQB=katMCFwJ)5YwS^K-T@hlRd=_?;y8 z%a{2Zf4^;z9l!|!By=44l57esMhWgW60L0+O%hDt@1V<9cFK?xnew2m@ik}`zIs4K zjM}t$anXmvpSzOdwwJrGRboEqcPtQG>olfvD$PJ0cz?_ft>m^X1ovIm`S~Z#eZ+F6 z##!|e80~aIzBGk3>1Zb0A-3uvSqEC zkL7KP?9XlLOk@VV&Vnz*_rHOrTm+GNZyQQMCY5sF!&E8(*K|evb3^YT9;>{^g?H&{PU3GB7L;r71iT}@DE=yDlhcIX zcK#NjLve-p{Lt$0^5V0e0zmxHVXVUCv4#OH^tfCepM!SDSHwBzPOZPkD`Kln)bnyn zzr+JZaW81qH|6!^Y7o|(&z%k5s}3z|GAToM8@>xEtE$$&3Ho}^R23Q-G30GY(KC+c zYnxEggaB0?v?_VE_Fl4nar?}zF?c7@U^a4 zB8`1`dmr#UF_39I7h3H&g2ciEz1K_9J?GBG!ZWc)IAE0#ZpKqauAYTrO+ zA%yami1tUH)R~&-i%cvZ5=g;XF=GciCql5O6cFhHGZeOu-3G}<8xx?AcBDk{VW~?< zz=>>>8}cPp|6Qw+wBP9`xqsR^-mVzP^xO5$3*zX5lJRjGKs~EpCk&Bic~)aAW=`7@ zSciJNZ$C-zFIMI2$43Z=8Y%P43YZ*0l5;TeM`W_M-8A1G4sRnYFHdVH%c`y`haL8M zKIt2i`;CjY~ zcWpl0=z*kiDfwxmZrrOu!r&`jF??|mxP#vJQVx=aF#yJR^zqFh^O3kT(bI0O??7i( zNePVpuQw;h$SyKF1G{$se*ZeN_-#;fkaMutJrr&#|e;3rEg_5mN{xyOZ zu81$h_9JIU;LArt`IiS*F5f09BwjyK$rx{J#J0kDc>6=e(Zhe(vkKuQ#kt|24*$?Zl7p zc^-g$bk;%IjR2wQ?$(nL<*5wMZ6L$qlX~^xZxcPmRRyCFmtUGwqS*vg{(;vkJh{@6ALI}=eb|zXn6$~@=>Ewi=$H2f!}YHFqq{8H zo-m(4?Z|R3yZ3(@(#?3?qiL`Ust&#g1+-rS8YPgu65w0RZBm@Vlc!tBhNU{c#C-qK zwZh&@tr2A;?<Um7*na_)+^cUyBsO__TmLpZc(4ks8D;v_TN3c7uV5^VHBkHAs`emocbMG{2i~8c`Hb}S%I%8D^u@r4&Mi_uyu#?j6?S3jefVx(P|s)J3nyT!-~$k zqusJGL1s=?)UC(W?cp?H`P(73G)R=znYS}HZ!8L zbDAzF{I}MLw?pxrbW-ZuMgHOzutfn$!}xBLnh$V7R?C_rl%1Jwf6rJp0!OqhXI(wX zafEkQCmBU5angNHOjM}9Nm0mMs4eu!S<0a+8K+b5?71 zsT_d0ZuM>7L4YG2#KP*wProCrn3#s-9?A4XXBkL`H-V#GZXD!8*eT;bd(rMdK~{Dh%y*o1 z)qFdMrh@!Z4Q1U*!S^e8GfYtVYZpK8D$PbEmKX%wb?;&EpR@lu2KVr>M+lGHn|Ko) zaogvFrzCgiYcRfGv~=+q*^$YGZN}qXLZO*$lQnie_{&e^86%O105L?AsdLpAXDb7yA!9(k0fHlw;}mtIr}S z*1obi*A|8SQ8tjq5Ar@-5>7dW8EhXiO&^mOt1i#wCz*1fjHr&*@u?2Aj>46Wq)++! zTkw?KB~LGgTk!C*b*{Jj=@QumIFA?ruYFF#m(BnmMQNK@t}VgV&fe{-AUe zlOEE%-DYEpqXZjFOmK1BF0}x}@=`nrL0u*hJtp25&o5l^HOBJF0|5-WN6#RzF=8Z} z&l@3^B8U2I`o(t5QQYZYznkW)P{0$UwWHeRU_on6m!QAOfe*uJJ99E*c?NWz&mA~l zx>;~t!O!wB?rS&JMb-}z4lFU79;gyfiFb3HTaC$8Ug8npR*;lf!|_ZFL--pU*X?fMs=v{heHPxM+0pp1EppcLcfH8{fo)mAeGY>?;fqhisK55BCK|lnF?z5VR%Olo`B$NAjURcXA*@{YgGP;P@~I@ldZ;^tL%x`TnhZ zVeE7C)yQIq_#VXF3&aIs?yEyTHuSCtk#jJQwc_x=a<)yehK%+?t|7nNBu@>%`lGP0 zDXi5o&-0TxepkRl8GTnb0)}d{os?tmyz@%^y=RCSwc=80!+31KKcf4zn$6OGZ{Cf< zLrotXP*tD}1e(Q`6eG${n$WWvh0vPes880hzq-XP{IL(0 zf>41?9s%Ppx$QPH84*5I->uo4srpvt)ykKPuF7^^@LxhR^&m>axC2Iqgzp ze*wbIs(NuoxJlH-03xcDZ8}cTU_WRbBXmW=EkWC8{Zft52__eYeTSDT0)c5q`jzNY zO^t!#wF7WpoTBG+u`j87#Rx3l38mMUI1R2KEU8+WJ$FG`iV7=#iN~<4%gVx`i>zU5)6Y^1-n6yfE+q`N?3@jbC6JFv zQrv@aaUsJOyUYVBf?Qd13-1eAV7m;AA6~fW) zOhDI`4IH3uO@|lh>FIIEGn_D5uFsV+Ae( z&V^+qlQD~>yP%mO|&Dh#2 zIwhvn7|4GBgZ3eUHZ-&N#P~!Kly;{&ySvn&%cp)A2&{MGDA*=DB2ds}*!HWC}#721!` zUvBk`YL8M97)VjQUJKCC1^;GX`sO}8pE+LOvCN+&+LYW9M23=7;b?ZFN(PIe$~pRG zJHNz?)OBJ9OYHt=U`2v#A=f6->wS*!ylC>wF~JIVwhfHmtzg*5`6%*n=W7LUF%_$- zqXuo)`^*u7CDE&OOThH_Axk}@J!9#VVC$cZmpH_FaYh!woNnuqm;gDiM@4q8Qvw9( zl}a43IBmMLsAi`b+$_wACi=&^3NumHKdc|^90Dvl&N!K>ssxxxliKE+UGT8Vp`6(1 zt)r;O5~cgL5b2tE7-On*#lQM52$6yWm~BK+>Gbu4(0x6(Zt}+!a(uuz!u9x%M&4#7 zb&1!%nI?R4a?7S+aK>S_xNW3B(nu7qQB_L%WKI<9?lPkH?-roSqwe-dAo+RK9NixL z0_t8RbDOg_7viVZ-L>*G)UmS&-R-rkzh*u4Qt9db+ZYNpAFJF7y@p6Pb=`G4yE#os zUa_rDJvn%AcO_=CHW42VYG2|b%KMAi$mnoYpQdqTtImtK;0|HZfHRL6yRLBxqY<4X zxvR{+LWBPtC@D-E+D3u@aCOX=b{}U+KwOF9#73R`HiD&ZkJ29TEkLN`N4E6Sd5vmP z^anNGg|o1#%Ac$}kdI*Zz$&EK8ynYX;0yw2aIm3+@R`TfT0M6i`PwIHHr_2(S4AEx zVb|Y^_CciNkq7^9|MiEbpa#vSm>2M~Cq`2{Ndm0oVM3O9@Mi3V|#So^SfI*Fq7GtC|iMb9*GxT@Fd#cj9rPBYue7XHH2> zN*3FCorN^9~P-vs-=i8JC53p6MVwSsbYyf00V_HE^5j^VIiBn z%Ss2;xb8Uz-V?Kc+jBAXmf;_O+tHD{?^^Xugitd6rf8XjWod8H(-dY)He~F+Q z--RZjrPxuJ0Z}^~8h7)%4$o3-cj}W?XDNq#ppD!E-u5el>N3KMeuh89ga);_7w-ad zqu`yKhfyiv5d~?dOT?cqXm}<32Fj~fCcc9@o$wz|VIy)+bYD!Npxg$o#XX(uzp(M{ z2l)qoMUKP^`^`0(@?Mx4(!Tp@5rFpg&#lkBehf1K@5j%l%4LWKZohmR7AgsJ7N31X z!1|G2h8U=G-Hz-|`OOGBJlWDW4S#P={)zt4O?%6Dps9y63r5UAu|Eoz;-ne3Xn6NaAh{bGnN(@0r}A#Gf@Z4Q zLgk_Z$ozWaxeeI{j4$)o4k7agb=e8!-DN<7 zZSgrjE9kM`V|`5Mx{{jv3LS5>{f`fEEGK__=cXIuCEUqRi4P{Xj)Kgf(|jJgZgDrQt( zIt3+q%N4=Fgq;%pk3Isz56OrLUOVr8_S6M6{uOSSA+)!f`iX~XLQ$lt5?}A+%KPQ4 z`VS+T;xPU*J-_o4<83-EFR#;xkF9z_BfIT1tU=h?y)W78LHgzn*FaS9nMb-~B6GgPF^f_ijVC zaKc}uK0in2bMG?;^FUt`K3zw9Y%?GRjVux8V7`n6QcFT#QsIf3`c}IY3%~P#B4idXs1>%P<3~@_Nri} z+6aGqb1FI5cdans12)AGdJr6>6CUxdQ@aGsH~Qx2;@r};5m>xNnFc47iUs{_0nsJ! zmLOlCpfy%!{YJH#1HwtUjNMYO$<0@=%d;R4FoM9m9NO}_Xgo*~&9AYU$%wOZGnda6 zX}0`#^E0Sskh(RVzMXl-%xhxrHwJ^mMHPZuY7P#d!x<=67$=zeIQKg+9Dn=r;q!Oj z{T(*P{~U+e|JmNFk=~h|69;9WUFOQ@V7ql(*c7*e&G)Cm#-S&+{xp$t(t|}YQ{i{D zx!Y(86qlmnQnT;d{3dq*)5{E-AhT-Z>+PH6Tny_i9~wAUC=bOqS(yWceL)8ZYR@9 zVR&b1@R}JJVs`c7q;Kpf*cBGAhMTNvlrC;N)O`4pSyzV zcmT016~6N;2A-nOG<5gJr&vdL`+Nxw+}N6&bYXG=6&zQ+r6 zu`TVPS2}}*UtBXRUQy0I!?eM>18<1$CceI#Xm=x=fHyBEl5E#0M?qpPF<;%tTKygz zCG50Euo$|RdYDajo+0*Xvl|fC54dd1dLGx3+Bua)^yRN+n}1RMh63bo+vJsqYSE3Z zB`G4rK-~>5jmPpUIWMXiz$GRODpGTgmF%!QP?Mihhhzmb5Ad5dHlEld%+JFv7cB+H zOw}N1h518%f(DT%MMV$J$<4xka#D~#SGdvYNOrU&T{}y_Jcv34R+Pydzkvq=-Inb$ z;O<|LYrR|(xnp2HZcPAdZV)=(pKON4OO@NIvDhK|X0650QCk{=N=Po~KMIDC0WkLJ zGFo)eF{u1skI=tdVqo`mA3J@kZNfpXS;7C^cGpc)Ab-5ke1_)E)5DL&HKbkuheM?J zC_lDFco&k)aY}~IzpCy(@x3_M+(`7-t6WM>h2|0bS@*U4_sBtQ^PrFr6guwIHD6=l zzsIS}P?o)<9LR?C6|CeFfv?0h)J5e2d>Eu==>-gzy@cgFey`$2T@1FGt;w%y=GJTk zdcI&mHxp>d(RlFcjNfVqZ@4ZK-_R=ffBvh&y{)~?&R8MG|MreU8%{)Mim4CY!ax&H z{RpWpiy?Li!njk{n&I4LTF=G+AL{+N^88+8J^FN4I_9#n*yyhq16#wj`eQUqrnP0f}S!(Px_)K4@+y2yI|hRPl=&g<#phBrI0a zzXABWs{_W=BfwBdGz}E;2X*Z52Vex&H2BkmlZ&oJlJr1xx5b~^ zee{E~QO|`hM`p&FGtU%df;R3TX}{R4?kxS_DxyTER|9hYMiU6`|B-1k*f0~*x^=5J zrmGXstWPG; z3|Z^pjEAWvBuapR4g%jM&r8oEmuHlJ_ysKjN88lmie=!y8yw58&dn-&I+dk z*Ibz#$G;V&?h_ARZz)}krJ<7Oqg+v<+TTqzhms%&8%4UA@E2lQz3Tt6f4v)%GZ&sq zap$0AiPe#HuyyxzxVwtRxhRo6D4weQgh{J&H5(#AF+^TQ6oY~#0~TCjtg%D@u9K99 z3PY~~pz<=_TGGC+8 zutnH=^6zSU4R>j&zaKOK($=6A4!-c7_H1}Mk{qf0xa2^!z_CSFTNq$@-BO#CfPA|r z)RpOA9cUiT=sYV-UN8v$CNZOXaTjaXPy6A;pVHr>#yJ3XHNnbC^)!Asd+;Wka) zRvQq@oQwSOVgIRsglE?4kj#*ul^4LKmACaPqyd*suj;$&lAV0`SR(=%M%;;<)o|D} zZ>+TbU@#7nh3PjqkOgx`#cL1yt+hCF#BMdevUh>Bi>@j^fZ0t4w;9=2zDdYYBPcR` zM2?@R8t;c!J*SiY49&2RDLXyzNPRT|=by}E-40}qA>YY1pUUuCgr1qS;v@A? zQ72T>?8vmchoy5qk|Ivr z#s$S$4F0B5fhDz|Jsxr8VfxTuaj`R@(?3VKzRxk-8@x6b^+7VMXXIK3)>?|ZpQgZ5 z$3yfi+OoIbi$mN8LALaUeTuAQzkV)e|2kgSdUZo#%V<;`nAyRR4y| z$XYGcy1F(&o^Uru#Fi)7`4idiEd#$+bD{g2qNALpoQd7Mo9Slu-^B*p!%5~0-a1#X zBNH*vK#{Sa9>!7jeOZm$%L_j4$BAuFRzBYH^k#Op7&W6fGJZDo`XT!k@gZ*c>Y>9 zS*MFkA6M9?e|5`|_rhSI8X*i6^rU{hw|x$qA>*q61xi{B6Kji_K39XMaF(1I=SNYJ z=*fJAh0ky#f|Dzu$jKvw-ul<1&32SA!jQjTuEvnb@kX``rr1{Y?DB%4>q2 z4VE5X&{nF;FH1hk69>r_bOU5>3@hPh1h zju`rt|M1vcsLR@t`|M%~xJ{_)F@5wzin9-<%V6at?|f)M@<5~iIsNilPC}Dt>lH9_ zarXDpC=#-z!oXosdd0jtx7SDVg8hZa4BH~F@33PdU;Lng*nS^LTc(LyPFgh3Ak@Vc z@XtLcaf6(7rT?#=#S`@4^IK6xiPeFx>=I;O!>HO8BD)iTLjzewx?&_q2XWo6?zy0W ztuyDhQ>MXxbS7^uXh@S#`WI+7OO`mMVwhn4g0(A3BapL&BR&+W6y0fu@)aU~noA)u z$`==h){cK0JM?6yn_P{rK}~{tg;Fq$$K>v&T65VWIt(G@2{(K`RgtUp9CL*EAwte8 zG$VelG4Vb%oiYg^DI{(8-F##Mg9kBipE)SAe@ngLa^YO4lCd$@%6jTIC+%1YzJl=G zFKROkBuIDscd#z8{$$Jr0h;2?@Hu&k1pnw2cKFv)H_NV3S24_(|AOU4$I_U7_VH_j zvew%12;JM{=2{hDWUk;#Xkeej+LvzhzAhW&wP!$u_^R~w8V{@oEF#s>ca9FlNWqUm^uNVMW{~?T@BTgThY94wLp={S zA@H53$z4B;ptg$aI4u?sk38;_SP$gQ1VET;jwRZlCq@X%PoKy{gKotL*%thCA9YDT z;S4NVnE`<{7chDpJjyIwC*>p(v(-;lfz}TYpG`u6P=1V2O=O&2qF{+KxztjcAmMe* zgQK@_fnNA8(R%dwX5a5i@KKF=YAQR$`?b;6XiNH>>&60~7(&9AtD`GANvw@-Tztd% zGo(xqx`NktvPT5!~aZyRR9UjXg8!_2)<=hf2M0% z#LW@)X7Oc3rcN?TAd{otDCQvKL6b($W`^+Ip^q`!6Bww8^ZA+GUlsxam&e!x(*vD{ z8~ijV@a+gktu$C|vztPrn0NCu2R8ndha_VjcyQRQ9M#ZM+^zWvXibJt4_orIlzx)| z+lBaPb2WbRtbQ*r9n+2LZimNEmT7C+EG?dbVFhYD2a+9dl?=XMGViZ> z#4!m6I;CHM-gM)vsVAw3rvU~b+^63aHA}k3-jLI9MyFF_R0M59dJ*bxvA=0fzs|%Q zihPA{WR)8UPJ}i8VfVlJ?CPJ<7eIhTZ{8phBsPQ^mpGno^nI%S2>P_=rfc=4$%%bC zn?9Lq=N~&qaK=j@ObBG|H4_oYIfqJC`>m7<`{p4C;+p<%+eUmj?s5ynd(%N^n|;nR zp0wQ!3KAnklSjy$hYnANZv4uBWpF9k_sk(XOVq*Uga3o-<(Rsw_ZdTTpzfD05XNBa zf7qe8%3%})V3ZxX?2ele;|D7Lyt+HA+%?AXkcFF@BvQ#L747c{{^(3 z2wVe$Zqu4gA@idI)N_WI_SQ8 zhUMNL^h|=O@sj%`U9*(4BN0)qFgvXu9N(5h2T(PGJ_8^~+l@N}Yb&c>)DuCjr3mz9k1w zBJm4>A1&~q$$69{{BTorL#y*+N}%?Q;tR{L$y@ieiDt>KjM32?y>IhO%e}vP5wQvR zp{?KiB(i|YG^gg}s@*j!j(UkauW41!$gEd}_$vZZrQoWAt{rgA5V(qxaVNHpKpl`( z+35O{)$|tDbCqb#oL3sA3@-$IpJOuiq$TR#DD@Snatlr1*28Ts*bjl$v8F`f=w=5!G7?6~AZxmA zf3ye%sL-z^=m_!r=5=}b{2-Fh_Xg};_P+xdL_&plqUXM!w2mk~<2vN85& z%L$CHqZaYy&WP9BG3B8qhs%f!-c40s+(Rj0DbztfOEMkU5m)o?&2@@~GrPAhJrak7 zWaE!0{f>R@OEcJ{1Y)GOoMdjbN`>0Iz`@RLGsy6^+=Vy8NcePm%G|WkuKkpSI(3J^Zs43~MLP%>uZbn|iAu-g0@WhX#hp-RR z*7*t{BR4wRLS$`f+pM$ZkE(9Xwi)g7se^?aV2FnUt-Bqm(U52NoX9*c+=sJY(LL*v zuBGO4ihb!`*{fKq?Y;w951f`93N*(2Flw$gek6_c&v?`M)^A<4`|2Sx42!CzzIGSw z=i6?!1(L3fx8BM>h_iVXZOii>;0nvPz$1RqBIJ#R5Yk0Q&u5rpa(skgoF*_WONH>woLUb&)^dN4 z_XDksAsUJZi|c;dq+d2esLzRl3DMPPL`TrBTcc(!|7b~61V$L8L{fkf{bIN@fMb+* zWB?~*Bhn@u?qh;M-2gNhcYGO}SE>;0kdcsIjIJ?n`?uA9@NfH2k<{7b}|9$5*n~WEIv^ziRZsgtoo{7Z- zkGBNNaO=E}C6O^`DC2J|0=TrKPlGhSXUY@h+Z+0klBO;5_wm;Zs}Mh^IX81N@}l#4 zsGs#Cp8o+dX$=+?{p;jGUW7m<5IfHPUMYF>H%+>eE87!(mPEhcfGb^#dFe61*g(>S zEXSESQnn5fwpS8;ntU~+v~wjYK?T*E8-dIsYA-;|QpE}Wr^^Rog27T}Sjrjg`|hy+ zj#oQzQHK5Mje;J(7qq zmbbSZ8*#Zt)v!aG6D)!0u{1yO&Eh9*CFyX^`8kP17N)zblY=?fZ3Z1BLD7hG&X?@FKBZ~PBfq!0&3WKwvQKJ1w_CGooc z*V`LSHh&X%H_>Ch;^y*?T%;RSpI|bf=(gcY!j~&>vLKH9v>hH38A~m|jd%#~c_Q6b z@BeM|%+CzMrglw*(YZG3fItPWNQE^&!|?c2h8sVva8LlweSh(wjy;Y@R7#?F7&xwy7o zE);yj`ZK@yQ^)bUmSAQsps#k*FbHB`7V3Y`(u~|NL8sErdSUi;Tfi$~2$}{X#W?(XTiHZB~Y5VDOLG}eQi5Th|olN-S;4ml@w?D3z>R+M%&hG|2uVdEtIV?63@U?J>vZn)PkZkN zL|P{TAhDA22JwBrx(_~;d#5PrRriUYQj+G*60sdMX5gOXd~Qi#{|A3M={MC`!#I#$ zW6buu=B-4+$wP4rE1F8)JaaboOO9=Po%DTroB`9MQ#n#PR!uK|f2?8rRS=eHKtZnO zvfjAN;`wg|2RNE5mpEi1eo+G2vZ-OOEGyoe`*31oEYN}}9~|JV&5iyGLHzY`n^ar0 zu7iVq%1l9nRD%P{Ny$y%y@s}Ic@D>`eEDBrVcVM>3f zvLH6nC8-25v?~KT#m#!ElgC#_Q@jFAVLDG0%KV;LG`^}LlE3)>Spaq?6xWap66thhhlRd4!T+jI$$Za2UmMp(%Hl3|9`?1dNjZH`B;gwaD@S&b8;wqee)5i(Ke{+F zD24RfMxIYePRLlJL>FkxL+0ibBqO$>@*(8*_FMz7$3nvZ&+xQ&RzHcva)wod+#04M zy}J)y{sGOed}C( zAi4c-J(I0$15Q!7`t>L+Rfs=3VBwM6M&$4(lP~Ki0gXOs-k2Esx}m)OFjn|^-?Tlu z=hHAKo>27_g$?Et@mTch6W?>ogDHmSxWMbGpD#piNfy6)iu=1V0tep$^88_inSCv9 z#?u|(zMCf8Ex2hr`8|DkToWcH2*$CGD?i*uXU=sdiY(3FH@%yeK0+yn&M9hn4=ZBa3ooH!huVKo=l?yP;(2M=AU;rD3r{$(D}W!!ItO4OMQ(U9x-(* zO+9TA#6Wyac3z%<_krv)`e=l8wm*e%2^OZ8QL4Aq6n+Or<*I~JTwi>~g_8$-aiFVA zI6|x>fN|YUAe8P*dymMvGW;p)@tJcXfkS7KT*8%%F-PkQ z-kYQ?`-qLP;Rgsu*Im%8_|7YRjJ3yQN=|tGfG^FX#Tm4JCPtvGmPD3wjUkX{V~K(( z-A?{6V4IL;lKEptOc)p@hF_bA)p?*RBaSWDMY+GPREIBc8_a}O+uFcxOH26_3fg*n zig_RBX9Js&GDm=NFU3LhV3SYWxff;RMyrNnOw~V1+n-OGD-M&G*17V8gOOxMmgHXS zL+qeRi-r{;SC4xd9?twcM&IH-d7^akM3|}%100+If8%ml?6h4q@V3b%LN1eYc1pRB z$l(wtW8}bci2cKYvdEL^{9;H@MHY6cX9vLYgQ0?O%9L)t zlJN1v964?cGg}xl{iN>$A)*l1m(CxCFQ&dHJD_jL^nHA`=KeSwOquJ}Xc}L}r!BEo z8u)CzpVX}jZz~N2vk>>B>d2d{h%FB7zg!3&qO>w2dZw7kD2cWNZZr6@Y5ND_`yhC+ z>gJ>`4P)+_sF|zuCFCCqoD%^Ay7|X-TmF~gMsai{N{!yVlSL76Pqd*lNnoa)nj{rj z{wu@}z@Io*V4LW(FeRbsd#0h+{+qpoC9l>>J}!MP%)_W&8ukok9E-Zb;u(BHUqKoi z2F)_HvqBlo`xV^?J@{gY~5nMbrBPc(!9RDQ+Kk@`)MR3ONIVGiExn%+!8?U9uGI zi5WUgJyDU!q&U3(rZu-6GLKu6Ivy2{n&7XgS8;>*w9%UJ8*_hu8_uff!Ab?bo46bM zp$LToi5Z^pZO9=Gi}z>LKvc*^rPj-)w|i3jg3faF!Tq-_ZCgW)9~SA|Z}O5)lP8dc zZ`ZN?`M%o^cxiIoVIW3>_A9E|0%_y==}(m(a-Q?tfap{ODvCb*=p)*Sge}Y8;E*C> zb2b+Y44&FhZ;9Phf9p{u0uUiKhRB*fY1w2Mqb}f4K4Rd^I;=##a^yk0@KuY6R!8_2 ziJ9!nL15taHE(o+6gOp+z5NdiWbbRn7VeL)f!<_(TP^N8r61e9&+Z$=0bD1b82=dh zv`We<7ssjW5LEPH9L?@9OAu{d@#NC-kyb>@A1`{1PI@MU7A=ZV&QVDUNs44mvr&gZ z$%0LLg!l=AMRWxuzD4ItqD1kILnQ`)Qk#&M&E?tE?U+x-&4T@rDW=~%&tvNRN^Gfb zBk3G(P*me2uEy+C!40I(mhnAU0*8`F%`){vh>YH%fU>^JsY+@{o);nBan%>bEJh+K(R_`PrmX_61~IgN8_l7Gd2Ps z7~j=p8Hhjj!$!EM=N#5;5A5i?;G4Z%8KMN#vCPgZ$B80H@(``|cV_1CYzvBG{)3=U z?##P+v-3NFi2$U|+fd8Cct)TBtkllt|9X0nhS1%$zfd?`BTjuNWEZCsN2G>E(x9v* z-9aXb4D|FA`d~MPixK?Kx+}2+z?Szh7di}IDswbmKbmD$^SQNL5!BM1_=2fvdlv4< zeWD#fVAGP+5AzQ0rsCul*bfbs>?ZlpV0Hw;;COQwzs6qJVM^7dQ7wjT6sz3}M2UFb zOUrt(y*;QgQ6U*l7g@8{fS;Zlscf(q0##n0RtxcsibLtaXKElS1o``1`_-EGo{c7k?5Y*6@v*^2ak?udT747qlT9G_55teMkr; zq4RHQuok)F<-gvr_?P!mlaq0-Cu`LGQBrsR8mNw`=wm9CoKSTZzpS<-nc%)3E_dCi zm7hyuiurqMO8--h2C(CWicQHcT3xGQ)de4Qo1RqUUnL#`SznIXXtL-TcaW*^H=0J_ z0|ndC|Cp3XwrUnWP5u?Hmw$Wjy}Yy4i@Q=;)UF{$eF)M>_fJY``t}8O`#O+0HJBd! zxYd_-Algd-5(OgpdiDMMqETOBcB+Ld$(S_6Ndf5*eu+OL@KV^wuw5W$2NP?&Vc^Dx#Ne8b(J0{y;RI)7$B=qFv?EAz=^4LOYQo|wuliGX-;DpLyLWp%B zEYZOzbSqNFbpG9&x~XQv$UYW-uLu?@Fs-CQOV*7-2Q0{X`6*+mh-Sz08>9uer>3*% z?2;ll0vXZ&s!sOu=>|-SfkAyUgIl}Vl3_bXlbcd4=hyLKoy~G2#O)|d%Q3eIU#Nx3 zpClc`?1>MSI01#srE1Sy&u7#sgewV|+$BW?@VhFs8$_b5oh5P8+4PX$h7SSf*w|6$ zJNRm`8inWsF2ZXr46l*&gizuLmG}Fc*eF9K(lUZ*b72zVZ>3A5Llx?Lk;@0&7{t$t zFq&2WWkA-PHwSXq&S3dTu~J0c-0RM;d@8vF_x!vmf6~|H^5v@?)l(1DUvcx%gp9e4 zSCF+w)%w4lH844baHFXeA-K$j+?wO*0-{X(ImHx!-z}63J=*e^__GAM_+*i=Wgqa% z_y%vTfr(lrTs+jiXb?ahf$v?AF?277Y^c!+)GqZkGed6mY+P00`JrySE%@|rY1cEe zgq89GF#b2%`J0P~d^%pE`o}3wo!2;jbW|?7Qz*MvWq|gFhNST!BaMFW$HtHPQWSB@ z2f#b3zdi&+1~z*g>FZV2>kK7<-aiy``h4JA)X_x*$57vVl>dG6Q}7^L->q|8_*#ZG z>iUl_$Zstty5UlT1r^{PnoE!Wf`~5K@t(soRE=?+=HCG&r&1ZR9FiCq%?;#$q|I1^ z(#Pu|($co!VU9u!l3^$zs$%naM%|EI>p3`b`WrjAM@}M7HU1vj7`1PQp;~_gdN{{Q zJiud6&SPG32w+DE-rPpOYFckiMSW0`hMLdcem}ITS`XnJ&-rwnd@yeXm#1Mq)$~&I zCVejON79yb;C&^*_7F%S7WY{!K+F9F$`>M@MEvT09Y_%>C?D76um_$L>aqagqKL|< zNQecFoNxr2zvmV`=%zXsG!Hu$lchNT#WXx1uwn$33jvGFC`P>G7~+xrNl}(fNo11Z z1Gu0|w1`#+Zk^0?v*HyU6$%|P?a-Yg%vbXTry_(fc*3VG{EPB1PxYwKGmgm>0eQ9b$1*17eTd}y*r&UpgH;|Z=ETG#15B$hN9=8qf2kr~Zo>cEe2 zg$I8F`e8IjP?M`Kz!wM>Hb#9p)`~JJc97oRaZZQ4ubeT8>iAJLaUam)1g7I~=sLgC z(?*}qGZTElHu_S3p!w!5yQforOD+WKJz9Yeb};F3!yb{!2sXo?2y(cWx5MsP;bS)_ zOmzps?qJ#v{46c`u4RxG4z>RoYb z_haY35e4WjP6u6%a(%N|2!)^!tAb??lcteuDj4sDWj9`VXd1UgC}*}tA!U}ZZCPN> zOW^J?@KQzj!m|E_v-|l=1s4Xo==}bNB6R5TcK}_{_YQ`= zU}r(_qr8e;brm4gb$5~+BiQ}V!;@s2QG~yYf$*8=@)%a(K&jc(2tTdg9ix>fi5JX{ zhBQG|E|{Kne)2Z6&(7G2*spFs8@oitrGQy6^SH^eMU7T$Pf!C_a|mASCqd}Ec6-e| zLSj4ojI};jquobbw1>I)5NNTr4w1ZNbrwCh2$!5`aGZSYN6e^W3-jav%s%%wi*$|D z>OQpHk1=x`hkgJU1Wng;eYOgFcHHhY(hsGNo!#T;B)%>y7;SQF6c2D)di(=D(Ikk_ znHFr_g@l7#!8@5hWs~rd#?wPLQb7*~Hu1p&Tc%BM!Zl2;kCFjjdC+@jW8}Ng6e^GL zhg;AuxVFQ=|Y%(s!)DD1y=iX>Wnw=iIwm}t~8hAu+SP$`xoJDB^i8*TbyC} zf)M%sgka(>1GkkFxNv5g-U(~){NFcP?V>B{GA({VP7b;P*J4s<1@PCQ5UH&gX_cFZVp3{}XTb;fPU^mHTD(zVf7y6*b z3q&zBU#z!$#yCXrQw~NrFP2g5a?qiFS)eYVV)| zX;QcHxY6gq!}9bps<3~5f7Z5?#{I5D4Vw^C$?vpkDRoF^!LC98bAJM?Wq}5{p;Y0P zox96L=Ma$;l|q!y>=S=-#MUU+P<3O!TH|m_ng|J6BYedb!ymofcVX0N`bN}tpKmgJ zBUs{Elw&=7n~299mB9F1sfrWkinIOx+sr;`1@AFK1hB`VOfS!W^4-O;&>CrtN(ICs zzwReuO7*sqz3H*9}Bcjh3@M}O-i4L38({e5zgc3{H5j(SErs)w(q1#@KYu;_SaGHQAz=C25|^XUvKNvMys&~ zq-`c34I*0FI*SSHC$q)t+;)uMuyK%SZy@HVT>rVHdC=v&+aT$#YQwTj-=Qup-5+H};tg(_L!1n1qQn?C z78dEfw5R%067g}d?$0jwhd*2XA6IV~7FD=~4b$Bz5(7wgNFxIXDgq*cbR#H&w30G( zBOxhBhf0@(z|h^Opv2H20z=Qh%ehdE9@HYI2DOOC2 zc^~qu5{S4FOR${%XeVD36JUDXBru zY*MO=Ge%W7xT-^+y3I5TY)}jA1B^Ezv`&~sjhvlg>%@vo#;aTKlEvLx*75tTp}d;x ztata&6hA46DVZaKeyu4=ArpovH|MDokUuRc-g}Q2o+ryJew{gu{wkvPpSORB=9w); z{W~_nN&a?TU>&;p>Q^4%c1~b5bFhXNgw%0RD7Z(dH7RChz*hx*f;CUX>09tZ> z>vx_m3MI7)P2^Wx&BO`anE;PSIWBSayu#l>qHn>|WFkro|3N z;2$g`ab)vVLeFT%*7(}|#f`39Sl_`BjW##4LgZ9H`sl_dv_e&D4#g#M*$Z!I1mZ*^ zESN8xhk5M-W%pAe!0o;I{b46R$mI7xK_UyA;&8o~?zOpx+ISMi$H9@+$gIaRSX#}; z__|~l3Px!VdCg3BiS9U^iqc)E)C2XTh^xov*Tg;=nE^tWqXZ0NIb6UjE6>;4(Kli} z9$WwXlIv6qId<+XgIdEu&(Dk|PN(4ARkP}AF^c|DgcNRBSKQ7rTj>4^a7|b$V(zO4 z``HK%G_nXJ-&%x3A0ZJ5zW$4x1m3?WI6|m7chh1}Jc*-| zYs?yx9N>?O$RX;8UK*T$<^!O{52&FqiOD6Y6r)$z^u5XY?v3FvxngE0-O34Vx?$j- zCx}tOhV{6uHTGgp+K^3VG!=^vT1$OPS3HsO>1+SK=NPUj#?{kj{07%2XBYi(j6Otg z?aIvU*uLb@S%;W_Lw*q42iSi2I)qa@O)yR?>zp zyp-gkcz=v=P3zd4;E@f5O5qTEjCGFr_78eGnNu0J#YCHGJS~0Jxg^<9ifIRKD|MO5#r!u%`YBJzQ(A@8r(xM7 z+FW8EdJM?mf=nsWAhbNY_v6h!!#65@g$J}0vZ$v?hG17qRDoS2EX`>$_OIR)p^4nj z81`!K#$0$NRAf493GF0HuE|WU{cHwaSWI+VXpHb0IWXU$tTfs4?~W}7keDFp^#{}) z*Y3f!lz91KJ0k&~J^L~5$qGDkCY4BI?6?AMn7XXbHvU{|mP%^;egnHhxUv&0Kg3~y zdmIwp=9t$1M<*I!F7gtIXAru2-@}^PGYQ)o%VezNzz;9D7UMiw{5uL!KKgX7#Ec;% zU5QA0G6#%ij76xl(ELZ)>J*?z{0|b2Rf~F%;vop(QP~VL-^UY1X;y!N1QT?#O~hD z{EW#%REa}EzGAjkJ+oQK8vY1(6HX}RjkL`t_iq((8B4NLYPS#!_d!_5jiE+qT4-Sd z#C~$qUeM;USL4=KR}_+-0LD@k`(adtV;CKXZ$;f#jF@Fy98s1zsKne|s84r($h(39 z-IWRH)_a*=O+5lmOSCWvm1aUOM?SOmB@BH|#21c|mSv}p0PjEGwC#1)Xa#L(ty&WL zqi_o{PUt@DOy=$sy&lMUcq&HGhiu+Bp1lB4n_VL=qy@R_)tWjW8e>5#W|&ihx5L^^ z>FYiWVYi5mpTaySguJU~gl4`y_W-{1BXs-C6E+8!+1~$k&l`xEVmY z@3c4*`f%WEw#-bD((YQYABN=H1;U9bF2CYMNG(gxldg_g4Mjc6EvWzDQ4-;92;7oh=ceed0L&ItWS-UONn27 zM`gX~Npks|hAa+!=?PyqHLobNez4fH!#=94jaEICIyT70F|5hP^udE0k~gNnrV8s> z5C&vpZ_p-cmtT?LcK%_;LU6yn;rO%ltIX2%aObCz*+~QRUKa+bFuO1_;)$=io;K#H zNVbAByH=hDq%VUfgx%S(wepu|2!RN)VnP9+)H+TA26p6@WSWOLx+Ja>8q6j^mZ zn2Tm`Ed*^S#veA-YP+*u>V^v@9tY@j?SGEvoajGV+iAku6R(?^gtd~Ul>C;I1}mB= zE&aWM3$42ZEqWc>to9fv;bmFk+QyS_Zw@w%JDCz`iKycr{(4XpB$)NrvG4u2CYEt> z9OI&G(*x=Hal5?x0v1tnF5dC&x4lC->@ZH9Y0b8cd-qQgAopQ^?ll!Xv#09UxLgvK z1kd!<6;|FXcWH3<8(&drbr)Xug3apRRmaG^=;&Nm3H{KtJ#V308YZmZI`rxF7AHH$ z!y4@2F|Hi8=h+S8qMVrX3e0d3Wyx#OTi3z$sKOS-5^yuCUNAXh6>Gne2hKXO-^U$f{k3+I&k+k3%qyt|3YBM zwJJzeFx7itsttQS(){v=NF%o8pxn9o!?^QG(9s(HF>y1dqnu}Q0UnI<8MTxb?7x4?!y5Ea2 zK9DqSOnixVKe-Rai_N3DG%p3&5Lwa3D(PtpAzyoX0N+UtqtpY_eBo@#2dP7}}{E;1ZL>HQT?hLxYV zTGZ!m4*4A=j@@8Q&sHG)ZDghVQ#-K+yfOm?M}2wl);2JM?%%OUHbwQ;bM=WMJm zcDE-iS8=tUKMIy@r5;FHeMjN@Ot=an3OC2iZtX<1*z#6T-J$~cALT?ut1N(=R)#w-5DALsb9Wq$oN#o;`LN7T2 z+cQa%)@7UOP^6KGo^!43{6ebpm}rc4&UPJ>VT6w1j~;^UJ>j1KUC{}VkHS8MHun0l zfhdV%zpban-=DaTFqzg@+wYBZ>D&W>pyVEMPuw{2%hqO)I?#S=UR>Ws0a6J;9e{n! zPo92Xw4$~skGcgq4zLY|Qe>?U{AfVJV+G$%{@UqZD`4il?OE7HmU;2JFEI?&&~`of z&6Aeft%~ohC>*8p6DJjXU4*MY$TI7$Q-4-mR^R%rU(PmW5#VNy-T5deDR7HOn|7F? z!wb3hs=EzO;P3?&J!b$Nn1Cfh9_XqMesV0f8ViungPjmSX+Y30ZFN zPvf@93`x9L1yxTZ<*$(ET%-lCoF_?ucXlnVFFRR271nWyyB1Q|$9$_jF=z!o*X>gg z7pFv43jLX8aBqY66@3vx)x2A~K#(fH-Iv8NNCo6wj;~ILF4_Pa6pwrHZnE^PN{x_b z0m@w;a;v-j(lJMNDmXp7D*0oG3HONVwj*$xs|y_+}?paxGf%WI0<`X+Ss+@FX# z!Y;AOXmup+z+qi^;5c9&IO)aJ*%*S@kmm>Z%EFkx>xe!<2J!U+$bXZFf#|3WSU!-l zAw#}%j$zFPEi}<+!AcB&X&;1M^)H0KY&9e306m4s0@TAkvBZWUiFsG?jRj-K-XhB~ z#2k;rwum+vzGbQM3GkH(cSI0K$wF8LF50?&*hYo9T53^6r@r^_W$&l1thR(@QgS{$yPLZ-X&PLFA%CDzR6M#aAX`huvFk-{se5S-h?}{p>cp2-kmf zhF!VOUV&xi+o~6+4f*njOqq-2dWX+U!HGloYX0H_#j6|_&<)nMB&%kkFyi7@&`P#w z!In>$c;>Nl2DmAyG#&HQ5}pzj`xxepKuwSg3G0)tV60w7EC{kB zs0Z-e`!&K^ZwR6-3qCM~I9#(AEG%@mSi^pYITQ`b$Ce;%%SP>ECC?30vf`sEYuhc> z6^?m^Y%gn;$E#bGDK6cJU**1XlWV`H_h9WJIb3)0-cThmi$aY=M6TKJ>iA*SD5 z>f%c)?X$Kga-V;?VIRzYqNISM+?Evby0NEuitKaU@QfAt^F+&m zo}L*Q@T~kH4B`aR@X;lxDWQH5H-F4A!Fq-M3s(6qHrIE;OE{_IqQ!la)tsfAq7#oL zGYf8B5?*<19)Z{Q;nceJH5WHCZj)+<)}o1ieQpuDW^)%$``?zM++qTgx=jl=-S=`1 z;2g*B{&?NS2OZP+rO&&lW^BRA)wr>lPKCXy^qnL{xd>81D1mr8mIiRgB{in>W)-VP zZfUh*{oTA6X>E&66y}U;O*jvIpG#GiCfn-_p*nnh28=6gtWQr8By%5Th;X+&CSZzP zQas=}Lf_&SE+$eFueK_tJf-!Fy|omw-D2D3)^kVPCDL|L!AB#;x4!wsnt~T5#+{PQ zF)lv8&t6U^fyCt5cOkRtH9CU#?UN?N4k9RTsh-}A4%tbIE=aW3C`uiqvX*R|eXz?r zVH{-ZOxm~&!+*t)FK!lUR`!@i=Gbx`&|h8m-9_4eRlOzs(WCV+(DhtIX)71Bi;Lho zRM@gh{lySN-McY$4u94Jr65%JO2!8DIx4<~k40JAu~lW>9q%H1n6v-5fVMk%_b@eX z`2#+2&qqI8fzD8CIaPg7)~I~2?JZ6TJ(sW-*Ps&=m-OA3;-pWXQtpTh_@rfjK2FX_ zc|3*i`x~ixLq({!Z9AnQW>OO6 z%#D{3?E~p|FB^D&d(kBQlz3xP=BsVBMNER&KIkDHKW=gF13ha@-BQBCJ4LI;tZU=R zk`2PZz(mDk?tGE~6B$%LtRY~>Qsif<)iov4u*c*Jzv#BjV%>?gW>+4y>e1ctzKh#Y z1lzBL>U&*S(gj%^akntfz3lET!AK91N3yS|b$M=ogkL0) z%O*aZ{ffQwPsWP<M7BTqsS+r}ptBfT;Z47c(?V%DTi%#wY(W%JXjyQ3cgXUu z13VS#{oh8wJyJrdS|nBAe4A4_kC>Jy`P4`U2rF)Kov-mGOO9d=OE3s5b|KNu*KJvO zlgoB>^?0d)&Jxy1wYqZ;XK!9%ug1)pX@bk9RA_%YbCkd$F2LuUs?{~~^%Z;H!e|U6 z#2=()M__Hs9y)n7LXWX=&NsHD1~dKQ4h;H~|MtXi-Tt`xVV?ip$Wal8J_i7T4i#@; zbSe8MKT1wZPc>!2@Y52k%1ePX{qNAF7S0Td|HRRwmT^;#S~Cr zSbGYry-!XZko8g+0%D$)P^hiCZ{?|fE-k38$NpZMXRzD}5Nc+K z|4FgFhE*lsvucQx`K+5+_Q~iaM)uHLzhB^YR8m(40}@B4UJX8&W4A-9#9Me?Ka zYZ*#biSI+f5BxQ*z21-EDw>6>N6ffcO$dvIeFhk`n6Sj`ZNuOZ!PEBH8tisZrc%{I z=HQWMqVZ7Pzq@@X+i66F;?@}Bh4FTDZU$ACsQf1(_^8wM(-%$|WcsknpExLG@ZkLP zT=l~4K>3M|C%V~-kO?)*AV0{fHh?m%%yV@cTaFT=!S%3PT3Sb<+Iivv0!<s^ySq>XHF7*;djDd0Q;~JU;5&Wed9;M zZQ<6$kNDc=pI!(9=R9@!8-qF3Lg=9#+h75&q*knLXJ9*Mg+haR;IdQ}H!w>7I@CZ| zXYJVXP8qF&Enc1D&=JEm^1fOAq65DlnEz8%rH>8gy}``LBuW&^Y4C?#yoIj^HM;i& z7IB80fmUU`PplUQjw__;EJp;JqB&LE^Q_*-Al}`GC1N(>{*X;+)NM-4oAIPd@1~s* z&!a%++2@$ky`6%%0fG#(p@ErGcipM6tpv|Tu3)5wk3`iCR3b~B;K$$wvkz?!Tea7t zy#{%JR+zs66NeW4iSsjVlH#Y_6k?0Ol?lw;RiKM@14gx!$Qd+VfAS7m8G^$1IfPB{ zkU|{ZL5otSpCK7o!wBf5iU$iUCbWztBzt!sj*Jo*j^=%+t9PD% zOqM24dYhYehr@h_%!p!?Hmeo=Eg`1lfq!T!O`F5j+1}ynza9jb1gjz-?>nVaj^GzU-|hHk^OT9mOTR|R)?CMmIg$u zX(Jr47zyM>*NnJ%s&+sU^_Cg@4L2Ekv^)k&So^!b}_Y1uRMLH z@hzm!|Ngh>dqc4JEFl32&Cju!k$!%C1E;z_XA4NjxK?>sa?Mx=eXYN}sSYY-ChF)& zfiY~spLp7X);$=!pGur6y-w?_J)Kr{Po$0iP+!51CKPgSxkB(UpT~RMz~CpBA!?Fo zKkOlRx2=b7GhFkN83d1VAW2b+Z|az_1oBFRmVj<*Q`SY@H}Kroi1btiEy9TYLw`TK zwz#A7xL^nZ`<^%8e=LCyxE86Gnv#EY*t^`SO3EUIVO~_^)PKAbovXJ-}8B7EFNX$^o9lD^ycZ)|UmkwbIs)X~y zY&T*3*AcW&BuqoS;#T$+^jK> zIvt_^)Pyh8Q#-(M4GgGY3TpB_KpT%J2ZVntH6(6O0#6NEPCr{ia3o_YY_>e8*W5eO zMC6Qn$bI1Lt4uK)w~)}CBnPv~g20!R-5)*%plY7Fj@r0A4sJZr1Y1J1L$D4?Bm9_$ zzX@AjIPwPn6sia03_hTrO$wIt(v*;p=Lk z5~{C~<1jLn)G0>X&;B>ZMZt;iG|%_yz|{@5TfdLG^dqM{dIwIFDS+^F&wC+TYm^rZ z*N6>BQEZdULo=hI3 zd6Ob?-&Z4zcr^LIi3wxmdDYcpc#hAx#f$jU?Ak9AZ6c!=(;Z($BM%kvImIWgFQ>G( zmm$;`x4(W~nG=L^({;F(!~K3wRFGnID0O&yjM>!6USO3;;3h*85I0oNKQc!%8)7+A zs470P?7ZHzYFv+`d&30GI;GuEFb-~;KlDh*Y*NS2c!tK%VL*HnK|PBYarRP+MQdjt z#NGMz(NF48{Pe7plVafhFO+s9idQW62B9=PK%OC6pR}Y00?r)B*xTF$_B`a7ViOGo zgli0oa;LWv*<|hIeBYb5ghcqpbt!wE0j6QLMViDta*ogICT~Sk%VIs+2GU+%3>Em; z|7m|FC{IkuGM>y}7#;Ki@OIpi$P&9-@LNBO=wB?;R$x^}d#;-u8CCO?Nmiej~Yq#K;B$ycwaQQ6NZ*vO$a>@B9=c3{3 zg5H9`Z|mnOFkm)`H1e`9~;J^LdKuhiw)D^9>D zk&KT!xXu9!EcV0CPD8 ze0fS9Dz0ADC;PiQ$|Vx>dbr1l&*nx(?C}AaMGPfz-LnyfxtlDp0X#65IP*mV<vRBEx_4?@b&z&@Njng2V{oI5oPf_OiWb;{u&!+$U=F3Wc!P}Iircx{W-W?nIvA~13g=Ri+q=#LM{Nzj~3?9d_-}Ak()s3Z%b#>lrh{R~1zdC+;@P)AJ11HXB!9FHV^e>or55)Im z5FY=u^w^-Iv5p%0S>S7Vg~#M=&tDu;Wh>o5fUXhUaOzj@*soDB6!OeYIL>;BrLS!@ z9Fy$TFNOWQ#P}4cYccl|)IV3KrWJihYbF={*B_*wu6lnoxwdC$^t+&4HnJt2V)Rvk zJc`2_VEzS@GgBJxWxL_m)gLvdo{nOv35Vp+B+Qn<2fq!J3!U0aTaPpqE>51ee%T4k zj&JP8#(+=X3kvMNjd+ctcp7!?_N$@HTysmY=KQG%PEfMU@anF4;?Ksva;ABsr-Ym4 z(vh}a5PS#3H2lFF?GzyGL6#{2&%OsQNCf))ggVAk=zAD8<}>G|qCd%+ zQKs9;Z+*H)*^be-wMLyouRPN(Me1GJ9<5W!xR7`7myAeYESg`&MNt~es~oFRBaU<& z#hJM;iQcSlg6)opCu54AEvWKMc-|B+qH3bzo-44!w{HChb8?L7HQrV`Iez zSSkBjaJ)`Jb;EAF!in0i{lGVu0I1YG@K&!%Veisd8#2d z4r8qz{=`Lj8kv?pFm$oLJY4R7^3)x9+7t8s`=}NLc{Aiv(8ppxy>dVhrFAR zm{6BMAYgn3Z@C!iG(8!eJ7zUiqi2`Kd32u3*T3WT7tyqM))eaCr*vo)W%iH^05SED zR?dzKi{^z7w0`CW(9CwGijNgH{*&ESl;&Weg>M?JEuXE1oCcwiIP zODV~q{ger-`}Ek_0Z5MQJ@hv-iCk03UV~rR6im;G6H;_Ai<(3?^m|Vaa52Bfe~A2} z+RAd}J6U1A`i+1CbI)@`X*XZPT%P_#+3~@;w&%|8DGso}u`Ta*!T{KIZ?Rby41}(U z5CBoMB5t6afym(om=U{)a0GrDksOt%#_PhM$cG z>fO!zsdaUWs=e&s$G!{*ut7Ll-1czEthJgn)c|Lko3M+Yb9#XN)cJ7bmPw-Pe07{o zkUu?ffztythB^u6j+$v-FN}y^xE!xIZhioJwfL2BKoky9xv-9#5O&g@MkuUqB%bzv zC*C-7Mev0Dk# zCY^Ikz7rp?W2ow^>mW>z3)fy1&GyUQP4gW!o^6^)9`}t?_MGl)$f+@CCb~ehASC3m z(vSA!QSzK_N!~AUao4}7S(Gvuz9h zkz_;nNmaB`50o~Psjqc)p4EC`U>rww=;gx$`xv2ECL^(`Eb}SuTQ@@7lUi5w6ZvD+ zw`8K9jn8Z^hufVAc4{9hvr;ew;!^s(9Uq_NbVB4_@^$EavfSfNsEnD&LB%*mA8%>p z++2r_?+mJRrf8kR{8w@!-$+Lt!=}1}v<|n1RGGS4z1PmCT8}p-3=5S^Ql)ch;cL-i zs3}o&jC$`z?TdPc?XlXf@E^5Y<1a}Sifr%Zk30exr;YRAR9Pi2P1 zLGc50C#34WXn065!#uH3d1%N=ft`Rpfi1Q2{MMW9^<&!(Ew4HD<46O=W1{-f?cjsi z%G$1*t)OqsF(r|l+8UpkfLif!(ktgKL`MK4&DxUi>EvF;$9O>(q!f~9`%{c3CpFA= z5SAt3xszz-rDvtmq|#VzMfr(N_2)m!R{t#L!LDnGr4P1{5!j1?5p)xOx(=GhAd>Mq znv{31%(2hH|6+LiN~Pii#3IB>bK3qsa>sJku!!OxuMSi zJW9|ocwP*pP0Tn1*$Ozh`-;<*Dgd|SGmx9Kay(D42I}+pJi0$Bo>E|xBxy!v5URbi zNh>e}3O^xjrg_$YBanFXCgoc%((~4(YT;mnXVplnAAK~D#FfzujFUrsHMr20@oA1( zMV^P+^=6|YswXH0kASQ>%Wv)a)5W)t*gwF+{0xeAB?zSzRs4Gc66;B{mQs9~k86Mf z567j2FHbfk;{j5X*XB0bR$aP3NuZ3|=K6SN2!S($8NEr_9D>|u!zo45iPm4g<$@)K z?Gnke==Vq+h6Rypm`Z|TbKZqC?bQ7{twr0DTN!XMaaV_$U=)!nG4@@+F}x`*8I(Wp zEb5J|G$yUd{FB2__7Jb>T5Zm4U}V69C0N|uZ8t<%*){fsS-Bjwwmx?}% z8j9_T+l>rfi=RTx8w0Dw>MjI>*T>f2c3}hyg_X%s0sLkx8Pe>lnkmv|VC{xtm~a7r z8DA5I`}VU<|HAD9QaB(Ux%UMuhTRs8o{%U%Uhw>OQ$o5=_#4Qzvz(75kfyHrw*BGa zz^;h$yR3v!U-Zy=`YFw?$Cf$+OORn0&h5;U+cw0g#Dv=GxkXKI!0B?@fb+^yfOBq= z2J7IR+QtN+qYxBweVFsR+4a_;xp>$(_1V)((*(Jj%i}umdZS~g=pe>tm0(mjAS2|H z*5DW%g`%|lj-&O8oOB}{;M+CXYvZX}4UzSMf1nJ3b5u8zX^atW7Glfj=CUY89R`fe z2dH1Qk7F9AVTP@|m4sQZo7W^f_A{$@$CNz7S`01LLU0eRe5Cq(AM81E?t$dDOmSNZ z1^aJ=OtSD?Aac7DZ;|!-0jw#q=$z9Lk1O7*{l?EQV?K|?XtUI!!%1O``U64N|4$3x z3BRt6UWBL3*rtcv50GUa}C-Hb_sULdU)$;(jPYY|BfK!<2V8-ZdJE06@m{G zcyB8Qprp~?jQ7%HOk96{5q?pk(l6&~l5>AD51Nf2sY0SBf<&C>~XcH-SWAuIxbFs^YdbXHLk>ajQ)nLTsKYZj-2!P7r7M6E<)JK+wLnwEkL`3GyQ@V ztlcv(-?8<;nX2+hg#=xjZU7nuhZ|RY_I)i-0YKmoN_St$8s;^1G1Y*hd7-_nH@|TV zdkb9SrfM)n=^JQx)qpC{{FnHQ?kCV)?dW`y>zVUO`mKe8=>-0po%G7Q8*6iB>mOBg z+!2~<83OTIseVO#k%a@#h5V8`Hs(<@0sWV)Okt{Rkp@}O{PlSD=%qRgXJ!nH4@0;d zLJM@y77W2uakbwLmFL)hx=1v?nm2Lyxao|!3}epBi`TYKe05j14$2N3V<8B@o7V$^ zf{H)7R`>b~Vw;|?--Zvqy^@`TD(wL)iiRQLOCqv{JwXCu7gGGiv45vv^VWXVdvhv@ z1z#NwxKHKp4?$Fc?NaQuBkmG;`UZpju?a;0UBE#&apGC`DIA<{g8WH2wprV^xKm7l ztK$XV?(O8CaNss>XA3f$tjnvq9t{)sL!J~MfL}4^S<|U0MzQ4>%q_ynDfp-h$K{NQ zBrFiezRnziJ3dV=fcbWH*DWBfYM~Jr5bNFFIzq3ow6Ll3R>4V;g?{+U8!|xkhokj) z9&F3EYN{FzB6;)D59i?p#T5+VzJg1}h;SB7$&PL09{TTDa0)>7dL( zaHA)WmCA+b)r^Zq#Vs1jT<}d&@CAsSgujRFqo;m z?pgqIHMMWsfg|r&#rq2b--LD}3vH!~teAEBJ3xd^$@5Z&I{EP-1!INs9*fjFgU^7J z+_|e{TT#a$m9~^8;Z?IUDEk`jf)1yU|0X~XSPnzU-Urv+uG#Fi*sz7Jw<=SxZs|J! z)^!s4wvY}E){OIj?cOM1=GYKiLL9BkG!}ETB`FC@8*^0jM_ZcE*ky-cdvbbf;h3wr zF_;Yw>pBWgKZ-2axGx_pJr;nTAA^_1aR;CgW8kx0p1^H^Q2wj)f?>)K>}7=wFepsd z=B06-#J6|n58i=nkOvT(LA0J|=}Jx(VJv1L`6*1Do3$Oq{EAniElfnpzvmf%lnLF+ zmxagFqImN|X|IPiAg#zV(lojcsOuzXQrLs6WKdV1f_ObAk!@!WkqqOBfO7!*ixrX% zfflUgr8_jwy)#cw3krY?8YKI$@;iy{qwwb;xJwLT3cP=2wXh;Q3*<@dy2iVbtMdw5 z*flmrG2jU?r4$A0%jgrLO)@y(K)<#rrfsbE(|an1dVwK00G%+5Je7Pw_yWA9tZvbk z5lX@^SkQc-;6EI(U5m{cu<5n#jiAP(%A7v^#okX*py?Ztwiv5vj z)fZ=zf{0=8C~{3-QuQ13K+zV_66eQw&^sKj9oM3`lZ1rL!%xmGli6Tz-T%C*(a_Vr zP_VeS6p^Ocm0t=fn^ojJ`1E;q9^kcWx`9D06Bn`y1k=Ik!etXB#?Baa5)b^PB z4e}Hcn{^V+Io-S1fx-6`ibxnSc~^+V2;MHILE)A zIYqv1x;n451$<)v?QuM=;XGeW)>3~o?QR_^w%%KfJ0D2|?7O~Y-|V>y1%%^?G~%VT z*+a0HyY2K(vyfb~N&nJpe_TSC9a@|;x&RhRlaOrZ?nU)u3L1hVHjLb&bqyQ-tS!ju zFq|Zq^LC5+H7?-4OS%@`1Hs}V5U}HGgAjnas{06fg*Al(e=iZ8 zIF0$F1wD=R=6Se3mQnD5F6+sVjpNU8Bdq0*FHfr;rS`|@8uq-WIgo?IFtC2DqA)^z z@M|Y_7QGoLycp4dP7>8!l;)*%Iz!&U-NEkRfnJb9;SC>F6~ZiuI)?wLU4bLVoLB%G zp+vzQX>4$K9>^0``GQW&-j+ulv3Yl^_M2Ek)OpOPRey38l$kYb^D`^?_x17{9cL$5 zS?~_b)|P=JECI>skZyy!IBBtkg-U`SM*x>sw4myPN;PyK>T^|+rff(ZN7_cnw6Lbw zCJ7Vk!UZifu3GxMD2UlMEtWRWlMW$uTZr{$`-0u0tabRT6_*-wH5W)Y$DmHZfd#36 zC^YLyI5RuAmW)%xEsBvRS!wq=`1ZC8MrTEIg3yb#P|Vd>EfjmTcm#d?<2kYLukg46 zIV_G+xc>->#tOoL?MrZ&OAxTL>*NrCUM6kv*;);yJFs^x3D#JHE9R<&tkX`Q+`>Mz zL_z`ES~@LAzV#Fhju%EJd@OPLA^q^+LCB}yIee0cV<+DeWSrW6(P#hbo=aI@fiEJ6 z4KDlvcvH)xXD15B+`3e79CBY0j{ANte?O9n0**6L^-S(L0tt<*aDeaID{#Jj%KqI_ zZ3v(gcxm0Tjm0%0V3*fNA;6uA>mzxR;?bpILuQFS@~p34Rl^37DC0NV!!%~B3f6*I z<|W4084j1F(k0LDb~Lk^)EE$QyOZ?uF9o9Fg&k)8)t?~$fN{5kF3&JoKGBmm<0(N> zCD@o`XS~&c2|F$t!;^&ByZNJyv~(tUyfwCU>PN>A-LaE=_@~{~wlJYGvTD>hWO{YW z;7Mc_REf6(bFc-XFu`YfNEL$Bv00r*6cWL4G+HkxC_=D%^9bWUG?o+@4eQ1cGR6Lw z)_X+C9W0SO{cx?F?bFU&dHW646#f4*{-5#OyhLFBP4M~kR0y!V56N2@ zz$S49o?NlEyh(Fn64bx$-Y>Y&1~N^mEuIGI5-PVj3bHUP$%D*XuVIALVp}xJV9r#w@W}3YxbuX0R-`D522Za~f#K(`-Y_?M|)}K6id_Y+Q?RUSr-hTVl{<;#6qML;Enl!{}kw*Rc4(2i3 znGld>EthX(4B+@UY&&{al_+84(K64T^`rgrk@RJVl?>%JHl(`z2 z$3l`9gMFlvKo6?c7T)FZyXx~ah(mCl$et^OEljx3<9dtrbZ#(-H-k$ET^Rx*4iGfL0odQo&P*4Jz{nM; zBrw__^ce#&;%?6%%rgCc5mp|RcA%^q8yk>E9|8K#e(AnVanQo96;$QlGo>ji*9ICP zM0SV0QBzFW_DfR@PVh(uq_Boz3#B?n_6}gXmE+FKrrC@NC>8sEImz??V#xVPjEG?; zrfkvjSf(sKyQek_+KD-shlF6a<_kiw2bU0Ei?eIV5J3CuItFLt59pAPBG)gW(yGI^ zFt}O-jE@tAHRYsgn}#uoJ)Zvl*>;{I=(}|Jiy7WtE5)xSZ-EFl1$R}Fn>Qx$XW_9u zkKPNIL7s%QPIjD5s>nz>X904mU8x{*izoF<*N5v2kc=zImxcu{KR&vmW-UB4oA<0mI)Lq!`y1>71;WdCC8f7Gnf1k)6}^N}Yp zS@381eA1zO9sfcG9M^63pBEk)|Z8&%>W+Bmt7TpNNIYLM&<*`^&2^=zTx1po$9OIp%_A&gef7Y=^E#FN?Z z-_L{5UVP@kXvbP>6mH^5=t8R& z^}qjF4o2iY146Oz*)rYSN1Q4-;ZYRo6Pg%8MIfe^^AB^*hAGxgoK9(H1F}DSc7GDc z5P2#?ee*UQ%D3WbfYo-BEF?Mq4z;*g&S2u(`6}~Hi<&!teE|-OsuiNssXENddE=|T zK8wZ}@+PO^8(5LYIU>vKP4!bF?#tXT%g-BGuaJ0-G|ev($`qbQ9V7evPf#slKVx-X z8(DCd=YYCbIWr}QRQuh%|M(AdYuy3P|7Bb}mXGB%PEJV8!?WP(WbXw2>gmjS8uKci zoKz&<=t;@wu1rHXNz<-vM z_4~n15jd`{@(i|gRT5&eA+sb17oDUOv=pd*E^%12M@t-WXhq zzqL~<47=Q&A$&Ni`Q%#q2o$2C)T)6z+gjZNj_v{Lz3J{BS5HioE#%h!de8rI33MhF zeGsTZPG^S@^-?@Znc9q*IwfaoyCsXkGZ40ZI4enhUP}Xo;V|3NCtDLW*5AgH+2w_} zW(F~yfMJc5Ig!qUhx{tKW?7~2M~M4&y2#VfbP@Ae4CYk6(dE=Rot$6%aVB$6aOO>b zUpG@m6~EqT%o(%zWjD*>j~~n#GaoZ@DGXY5k^D9%eE&z9?9XUA*huO@A1()t4<-7@&&%W!{$zsx9E6PqGSNPsYHLLI6%s zvwjE22ZC^tckv^+8{`07&OEq`FZUsET#pcP9}34!Y~d=hV4awt!Yzb1c+&s#edg~< z^N^TT({wP1_*_^7el@ww4I0^gv;YHyD36Mk9GIS%W~JJBit6hK0V`hPF@!f=%hE8*+&qdPjXLUGW)u4?lW*j z6uR)Qi0Rk7A7fPtDt?C-SCWM(iW8r4w?OBqFDZrEi9g?E=GQOZ3cg>v*PakHM`WX% zh=-<#GuW~?apejSk+dS|Tod&E&Bkgq_Sg$;8UY&>*4L}pPi^Rt5%okiG!{nH8ZA&AFlx>En9q#0hU z;nLyn&c!Or#>w$)X~NM@6R9YJTEo8EF29Xes%_yv^**Tnx*fJ&{cua9+&^wT-0>#} zjDzPUJ5R|cut>!B!$1g-(BDTa!}|(V3Xl*~n3doKAU(w82$El>L_YBAvg9fi1b@lk zr`s3MkjMybYHTy>Tg(I9xc`if)W$5t8_#W2oA>E8(B`}3L*udSFcus^8l zic<(81bG8BC<3ru?;->1bx7@B~B5Cx>x?Dx{p}xa)FqS))nvM>h=D_cNZhis2%!i zM20BD*`nF4?0lfb&7i(`Af@0WOIoFa<3r?j$3 zTC`6{4j(_I?Hw;BHUCDU9Gc_2|5M!j0(j)^9k0akiU%{0z?!T4dOt_gw}N7N5w_?q zpciRV{=jgqL7TEZjY+knXs-N;WFr}ZrzBQIb&(!qw>(?J^jDA!d_*wulqz?S6T1{32-=NQabwbV;`$Jv1mHE!`y@k_wJ=x6<9+F~H2c_x1a^ zzjg1LwPwxyHSe7BoOAYhp8f3YP_c$5>gD#@Opm>X52hmafTYh}r*!aqYba&f;%=r= zizu>jTV>&B;X^+k48aWcn5bbuRJL@f$ZY$;9xRHWG}Lnk-PCs@+7!pv&PH2dBoJ%Q z_mvU%Fs-g$ZQ7%)uwvD(1Ib+Ejp`Zc!JO3fdB9%CEY%aWkAO54L?@0e;pHiVnpfBO zbDlh)10%|2a8tS7vS+YxHCOLj{QHAtlT5_`DaFKJcc!G0Yh&KsL153krmoWM!r?YQ zYSRljk1kL(2MF0}r2g>Y`}#6sT%?I(_oo{G6Lm^ET&$B@pgaDD8VLt_a|alcU@kl@ zWK^z*h^>`$VZiN&WYUgV*UH@rJog1QCfdU|c3?E?h9n8f4yd8h|5?Odl_b@!sqdYv+0$@q^GKx zO;t~V^J98uA?sDppL1``pQf>@Qu6)1d9%LHDpr8ctZjw7yDHK+BDhSi2{UX#ok*{e ziDOFqPAch4K`aPNy>22IcpGma6r4K6|evm^!znSS3 zp&uw>3}#7EWhKOgydHNaT<(PDH1foZtqQ^qF;SaCQ{Er(-62) zU~RuWblbO}eqkMbh_qqkW%(S*$6_vXI6bl!w;%zX&wpY<%`D=&-1b(n&a%fOu7CvE zi~JDT#u81ANTCF}>OF}8i+(`X|Mk=mLdv%QFLSRinv;HRo#Fs`5hM&}e z(_9ffPM5rV-5sdFXZ+ygwYpPc6~xvKDV}eM zMMWyh&$}$4uqt3M*oV|5)#h->nVO{I53B#YOmK${+0PhIT`Wz&B=(t4Z(DP?`n)Z; z*S`8jBXs45o})5$VJM}|$bO?>5JGH~!{bU%-@@#dHaB5EA`F`(oNO=H*vG=8u~G=A zw;8fo@BXO5x^7nQgV(zK)~R|h>YH^}36Y@hBtx?(vf zVR;Xx@5fb_G66tX3v#7ai>1s{mY#l>&|)yYY;FQ*BxP?@-e8|sz{g$(ZX3q7`XV3- zr={cela*x~Z#UB=T&st(q=krpExvd&m$o(RacKH*E`%`@hj$zvwa*NnDy%0XEId9i zMbjW(Giep(Me$7IV9Vp@rL(Ez|>Ww`HdQKe>xMt#cX3w## zm@#vYELLXWLbqXSJ3h;su0J;TcmOevdO6fA!uA5T2T7~=mXn4m&ET>5uCbs(j_>fn z`MhsJ_EG+n0nm&RMKzz1T>aTJtNmqhzH;g65AKV7myCmGpyvX{6qMy4*BZCEyzDKx zIOf1KL^+B0R7Oorg;myiY2HiFdogXr3)%c`BxAA&Z+bF+!FjpO5VV8HDZ6T3Zm(m{ zA#q&a-Jh^h7>XpK4W2u@&mC2tF(#70Whbi^ataM2%}(5Xv^!%qD%IT3;JBdBRpcRM zN#8_E8zse(-f!rWU)0V znafC{ZoQnbIhOm86ln?)4Y&u}Zw$Zx(uU`t zT0OQBTufZQqGRE6SG^lWXa}W9C~{R@<(ZZ1*Pv%}PX_nb zP|nh-TF7JxyK6U%!`@WANFXi2Y_dLk*dn9p?(EGI@;JJ|X->O5M_+Hx8@Dc%iF{mH5rKkNvm%0b|M_v!)kaAXv<_E5h{~DcddHNeCO0Gcfvxo1zzizv$ zcby4uLa!lbQyA32c%nfSXSS!Ys9vbcaG6v6neBPsX3Yo$mVk1+s2PEY0P_gPJBZKk zW$3rS43y1X>YiB%G@I-IRsv+8GWG6U@2`)Fv@H|M$qvkEsU#kMk%jMYs&T&N|7O)) z3A23^P?d4<;X&b>k$DH1%{zeIXD^lxjaGqu^=5xbb*6jnmq4N7K;#vzkTtOPr}caC zGb3zs@>R(zp#mP_FnY{`8v(d}xqz>d09(MSiE+SXI4acGL^aDH< zR~zBIJ#^SGFUOWa%kLTurX}j>JTc~fEX)1Zu(V;aa#_XYrE9D{G!Mr-M{mRYU;-p^ zpS}d^<=(X3tW`nVQsz?jN-aDmA_yosV=qbNfP-q7#-~TmN-(ot*p%~h_U7iG9N?<< z__$y8!?1}Is5G6X_xBEimF|h*>-m-i?=mGQbNo)f5=_DTt}coVRX%zDoqo1p1IJ

    l($>M(uO+IW)8%>?#1iW7k^UDY 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 Tpk7)JaIp{W@K56O31 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 Cy8{#e diff --git a/cli/screenshots/workspace.png b/cli/screenshots/workspace.png index eb0f75d0a5fa15d768ae5537e0a9a5c211e347b1..867d35a59c2221db8d19fdf866d0bb3a963fe960 100644 GIT binary patch literal 202902 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Ξ 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

    n<@ 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

    )0EynbXiVWG6&Wh|UWBy;in`QYcyUc=DG+Yc+7 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%0Awf8@w5T7ik>Uy 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

    ~RrNttK$| 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%0A;3$@U|$>q{q#UCrI&Tf72TX1W@N zDZjNaLiRu*$Eg$nt+URRjimzk4{Bb*I`HOa3I90tK&fhp~zlggL9%9gY zCnD~zqm8mnM^4%O(G1*6P5t^?mkfQrP-F83>F05Eq3ivu692q7f2A9-uD2A4@2|9k zjTXqtcloYei)5|IbSW#fe%dfJ$>_v5%Ss6jJZv7fxhL2*RAf1@zcr4m>kmjT7DiY% zTp%+?s!hdr+ba?wGhOL!FseN$o`eqA%YAiXhFT8(VAi6zrfD}?}pkJSGAfI$_ zgNfGqSYBb^)d1dCFrH>59!hYmCk!_|GE_XS{V0ftw@?U15g`iLX;gq%0BN`W%JbeW z=9h%4HfMGrIJ770O;tAV$&68;nPtoAmlx&l>g{8{SAK%m@sP6dy|4n2?#95tpg`g; zwu-Evf{IQR^JN^w_hsjI4urR#7r_HLiv*JQ^TC|{}#|8&VH(6A#-)l z)w>yi89Er1I}18)hSeX_E*bx%9mST=9k@I+?EeV7aDwZM<#D2;w^K5-+ha-|j;@}= zCpiYt!eDg{M35mEG|uC&Y@euRhV)O;?iWbeQLTI zM7U;%JBu@bMu5#PqqgjmRY#Y9v=sqrQ)&TA;h5!_zlTa*4vR8$^16^tC&&gsddYs}zhgOz&%&ObheQ zd96?!zo^r>q4M9HCcm+%apd0a4{FY{m$*a4Boz(mlIya|Yg?c0x@`PA8|wVVN}FWW z9J?Jtm@M=@WmZU)M*AZN2Lv4@kET!ygm+#eVIo;yysLcLo?UT$>uOMKdlGLR&97r5 zB&3-e{K))4aza=~$nMuhpRkoP;zw0-HX1IT;89GAF4b0-)Wa~EwJOgB^-a5Aw%L+K zz3N{8pQ-m_{}Qz`&4ogVD@re^`4o%?_e9{&qvIn7Ie*_79`X3SRlP9J3g6B`6r7Tujve%yav$au(FY|u5EyJAp8 zQ3{wKBzfqgv>_;fTeg@0&v?nU@HdjBe0SIz%*UaR%Yx{&Ed1+UNk zLtlrSU9?vCms`}pzI4g6w0Z@{L2NtQ%G|8!IFuQbnz**LbC{@wyO~Mo4DKm|>bZQe z&4H`w?P1h!l;%S<@~sv8ml!spFbda>$6V>t=wMu;j?x>{$0M~8xQX(zsmAnyRP^`8 zHTi8F{aM|0nEs(KSy|(xZhfeXL_+oTit)&BP*m*5|x1nlz$z=C0-v_hz*mFSYb~)8?(XWuy>mLB(-lf z^`bcMw#ozSFUjLWN{5No3)jEzsocXM=T(yt1V^`(URCu`xGSTMIO_S;%B@o%{|kd; zI6FEuCW*J1sYd(>&6}du4%GJ16A|J7PLNhFgMAMs;bR~yBiCY> zV5c4MuFv&?TB-d)4hc1Nc>xj8k;1*Mb*OikeS-baUgpa^-oF97Y_!tT?eb4%Sf0gy zLZ9Jh-@~foHjnZ8GKref(zlDk=I))6rfz7#EH<^MvfTY!w0u1!tvWR;Fm(J*C)Ym& z`!gxaun%ZEjymI%59eis)o1PAD6zS=-h5iUR!SeWbDjLNhpRZ3=mTq2`FQy`&5CIY zG(71el^!Ee8cCFlKxXz$sKaV;bSvhO%h{?&PW?*q=93^h+(aUD! zv3aqRUh2yG-Y&6W2;pnLd;Nj0ZuA(cj#(~9-+)zEZx0Dls2}8fPgD%!rW~wKuD#F! zGOkIIXwULG!j^6}O9$(d(Dq0Xrz@A7qB4cmla0S8$QPE4XXCKNi4-B!d-V{``J%J; zX7f7ROfn4z>8~}z&y8cGH7-70fNdbh7C$7p2i*xguG!!0k!z@XxQ|T@ilLXy|E1l+ zKkiqv!82~d*2&YMk;JERyM{i=5{wItanKC9dB{f)WR7zzEua(DdDGkr-$N_Ksl2H( z3tVakgzXn3U?^ItRnYT6z7_A9&bRuRvkwzi?GJh^dx71_Q>YK$hwv!FGJCs}7b(qH zy}`84aJlOkW~6Desj1*#UW$g49|J0p6(SkW__#!4-|1Lo+!`enTHn`rMY9&b$uwM% zJ6T1aKt{g54>99ALg)z_V`~N2s6v-0Fyv3F)ry?&=7do@I0(4@Mfn_Q-%4)!Rl<-oUVd!jLz3@3aNr5)%m6z2mh^i3&@eq`v;SK#K2(AEB=QRG9UR8l%f({3*0 zw3`^akWh~qBqHJ0V{)PBrmId`SL`{g!du5n2cG1D*@?K{FrwS4g0$h%i1RIY57I%Hjyd0=oA)f~0VBrmu$Oi`T-PIpV`{qm3U z5BI~fOE{|1`Q8V3+$nX_XF{g<>6zNC7s|8O1nV--Gz_+6nVwg}N!ZENlh27Sux|Eb z-4HS7^50V8m`_^P|IWB0*rh&`jY6 zxji$NDkEP0cs_QC8~Mt2GYgTA0A)e5!C5A%U#}|}B*HeVFCkdp|Z+gUV%1+|VuGk4=dVso--toXW{j!qBk9T%L zO{*Xln84-qXKy=D>C-tHj%{s`kstJ;c=~`OUgdB^o!`sSCL5Y)Nq~ao)gq!Zd!c?wH~^!x;VKbrXi7 zav}u6(PSsijPJ(~veZroS2o{~oVQtbON~^hqi%|GurDV!7B)o$Hyzi~BP>ACZbWao zH~ThpWSzaI1Z`9$VQ;h%Sdl5D*C;E>+qsgf=c$o-tgL}~*r0Mbk-`RREqSanPwno9 zDU?WzZ-(W%1t7R9&h5iA!-HOIQF*F#N~8~p{RNnB1yPaFG21g1J(_e($(WnU5$>rB zK;jN$8FJ}hW!ykKBpz`q1H{P!tAj>XTy|~?Ws5z^=YKA=2+bf5S63Gk+f2HnL9?7I zv*O4c=DlodH>sc-1)mv$6$TxDs7e7hJqE*fhRhDQpNFPc4Dnq9OOLBNBkk=Jy&>%3Y4Y}HVKKL6?kV7}`(`*dLsF-=VeN%>d&^RJht5=? z=2!t66{3X0%tS*7AF;H02F^T2rIncF=kU;LfWJr6wJX;Lq=| z@k{ULO{pA=3H!PWRt=Ngz=yw%{A8k39+le0X%V4kaY4DOf!J_Z=| z%nXQ3k`JqWw(aWt0&FLy=@=3C`U1AdgItR6T}(=clf~m&wk;Q z7#5`p3%ah`U^o{?zO1L-^82gVpT9tvcv{WJI|9I_OBa5-i-h1j=*%0XPJ3p)aNGYG zy!md{bR2;EvDd@qPV_Q!4c(C`tdMd^a&l=RHItEaKLUnTU*j zT%)G=52Q!ymi>rM;HSh7d-MK@TewL5+C>_qg|<}Q`E(%b!q`SAf$TiNiqn$XfCBi5vw-^r8Omu z;^(KG=V2=qkWcN`cv` zlxn%ij{QM3>&*{;w`P6%l>LsIC-&EIPZoM+Gq&$$#ICq7*FKmccA!NPWFq%8fkVYsS*0Hr zyR*_?2sT7vyKpdsjpT>m8}Gbd(Mb0wJgy0D^A=v;&iq|9T=__Qy*IbMymqNkp`Vgt zINtmswopXktylmV9qTGhh;ufom3OG{Zj&0R4^r)5(C6oFeiI)nVHP~U_RI})Df7QW=;>$40^$J%6@Aq(mWXL(5zBR zS?SHCuJiUx?NSd+|7$?6A;c=p`Gv2A`CxTy;B}Pb;m0b zCbQ918hjuP@dmFd)pv+hI`>)4%iH{vZXY9vK$^JZ1+4@1CamVNTmI&C2r4{Csu)ZG>|RWEOt6Ii#=nm12qdv)0RY3g_#|j#?ov_H3hTLT$dC)u)9#y}@D1=8<*o!kWa-jiSnu)qg zTKIc3x_6!TAm|k-c1p`uVeB4< zfGiczK+ngo5d#yHd0JCULoJiEB&ep*Q_<40e)bN-*!fT<(+uyjQ*NcpYnt?BF{$pR z4EXU#^wZObbjsRr2u-M6n1=D#qod2g9$35jT&5nA>~PSmxv1jVtj;~t-f|w!^QW{3 zyEZKM*|^k3LsdY&D zvid$g%H=FK?Th`lL%~-sk_(y1ry=G-ZVIO~mH|Z^DE`Vtyw@%x6Hbo(G3qKC6J*#ETkWZ)SYjn-ZroT*tFRQnykQL^Wj~@N z-oKes97(1lT}HpmE7eZWOIXe@mYjTMY(7}c{KbyW>DO)lI*wQ?w~rv>dNg_a+$PF6 zgf4k^9)x;Dy_d6sdhZm+baJv$^4L}c+rO-Q{DO1sq*Jr$M2r|j)gHu}kC%=;Ye2ke;H z*0lzer+1J#A?yZtP&vp6&9@UQ4fiJ&kjj}WD77GSj(3#nTh1pPqeE^8)F?tZ zcA7_QxUe7HmHz~#sP~W@pl0~-z#$Zb*GmzKuY-zYFQcE(N%?r{*#u^-kjlCp9~Zc1CGg+!`l2kzm# zqHHuo*%PepgZ5u34n>F^dmipGli3`B_X~(s^nk0GeIF$jes56qbz=wQ!NWN}Y8N%E z2}9ZrYnw- zDmv*;yMBVRTFy$s=}QZ?2e!=Fzf+qsMx`|=k_?kMjQ7w{tiQE&eZO{I6`#3$x!N=5 zpdjlfm}^-n%*i0ntV9@ds_NC8Y4M>K3l^JULNCixq^Xd^+p7UD)zv7>^GPiRutWp* z&^_dsqKoYf{AGehKAl)nZ$I(l#?S>ok=b8%FLIfcB{f031O_v3gaAlH2J1DCDPE2G1~+1wCN zTMGh*UCN?3oMBB~Sz+jTcqM{fl=;0JQ$~?mNf_BD=bE~lRmHb?O5&cHvu~ux=&iK* zq~b3?$r*}{e`jn0L-OG6`8U#fK;%}JEJ7bRafLn+^ZpLb&d>o5q9+#zVuDmCaXn+xD@3j!L6t@>L8S!Kn?8(o*_<9|`%@IF=A~46?|1N|H-}s| zTEA$R1;x5neRQE3QPSv6c!)Kxx@hF{;|%01cXCLcq3ZloX-mQF4+;di-xOJIJ+r*_ zbGF)XM~?ri6<~MkE#>mD=P`;|ZC9OAL@$EJ&$g)PgiC&|x`;MwIs-aX|2T2ZF0$|9 zQK1a7jI>W5K(?XwsWcpPPiTz}j*S#Yi32Ad$}*kA^q+R7`EUOKV`S7HU^R!M*6N7D zSVPrXdgytsX$kWAbvS^pMquW*QZfSR9gNA&&uJxg>MT+j1wW)lW|5nuboQ?d7Va=k zr^S+5BxH6^v+U5PsApT~F^dKl9ah)aP*33nm^wltk;0LJ`4)!xXa62L?Ws~CbIxp5 z4KJk3lDW0gF4Xyqn63BGPzy`B?Rb)~dx%1Tq7KV!YcT5|D@ZB`Vj;OXp?4Z3cJQRA&b1b&Y>MAY6%fDiD$bNQrSorKvqYH7fH17H8` zYlmMD8YN1v5qp;G1-VqfRwMC846AXe&%R5wETP;ff0m|8W)D>l@zJCI2Kpg7OM6%r*2|W6+O&Mpf>=X;iJmRN6$Dt`y~kSgij!qq>FL52|G6 zFWWIZ{9Pp1#YPtik9m5sbhsHYE;|O)j7dE-iB2u zsxVNW&8^U?*pBUQ`VWeO{7Z^0FWZ7ymJLGY>6C*cj1#r&8W?r@0?S>{^BCafybmd& z*qcqmhrw}TM?0WG$&+n9am}pULe*h_2imt`t)mNk`LRr?j?|apUaiwDE4z_-e2R)J zCic$OXKGN`fX;+b9L*i`oa^>!1oFGL76~s~=&|_T8HwI@oF|!!qd*N|bK|gfTOZ=# zK3Wrq^D(8|fG9(i6geyfV@-Hkay>D#f2CMuzEF!xc2;!{?3K2@Tv6pW9msKGRPDd#o50 z$nUjd4{hAGxCsQ)-;xXNgInDHcE&UCy0~kgfbGz-XJS~anfBJK?PH^C+LuVew!r5L z@;C=E2owGUA04AZn}^wn+(yN{;z}Al{3Qh_3BJ&#zf}M^WmJ!$vF+Jim~Ri+zNTI% z08K$?C69uYwGHoU8Ay4)D~gILAFJXR*z!M7u0AJ~Ti5x=TUQ5pAK z+fbx>gCe|iX8gLlBML)UizA+Hvfk_38?k)fqq@WTxJC$_7wX#|vq1*0y~ zv73h4EtgNG3p$&)j!e0DJW;!QTl=s9p-dEw z>6<2QjY|NZO)89j8gMz=GXKVRUC8Nf#34}-$Tbfy%YqZ-rn!B{AS(-pLzo{}ta(e$5wWA{kyvyOY`YGrUSu#m4^6*?kLkMES9WJc2ylW97%#`IJV< ziGL7dgu)QuAHlVM3;7OMTF(E27$@&mdQ$GGjjSWBep51UqV1?h;iB8k-TpmDngYC&f{tXZp z!$idtY`+Ry1GJgefM1cNCy~^h+|}fyv7O)~VYFkoN#rBP+m92+PgW+=j&@qPdPE^- z0)RJ6@39G*T1_E)QQyDQ(#_rHUVY4kPPCK9R0oaKZ`zO<~)i#`t0dNF542yd*q zhfHawPc|G|oZtm915FpG3kUKz=_E%jCKI(S<&Uiz+Z6@4K@9w>#^I7^elX|Mr?daAI{UR3J41Rbu zsIPX*ALe44>KdE|JC!nW^UMx+a2{qG?o9ndKl>y84f#t6>y_3o;qSEKcNznt?tF5p zYiRcPU$!lyjI_g5C_lC(I+oV2j4Ay4-%E$WK`sk1>FG3-*F2`DS!qvJ3f+%u&Sp(Z zaBbE!W{0!Ysnn01cOlE)^JyIKfXhd*V}RaO3bG9N+)JId%Xpjmm0Czjm2ongolH9CHJ-;^i)JDBO#GU-V$b zMX%z2Fq>Z#y1+(~J%ZSnl7tWrIdk=F{~2(sMZPVFx4v{68kV|~IkFPod}}q+bFX8* z?%dOEfAU2C{laA)iTLY?beP8)!dF(#Z5YpMeosQEb60LxCSg3t{3DDCwrp3SEx#xI z>5@pz(8-FMX9R#aDvLHYgFTyUd5O6=CVfaKwn$M?{LZ`cv+QsAZq0lz>dAh7z<@kd zzOkj-z@P4;9xr`bz2(}=_`cv^RM!k21eh1($vB^m=;J!UYTgH_LmnKXlMwD?=#KUh zR47Xwv>5L7qn7k=xb4BQ%QOml(Yr7eaITi-9dKG`LHf$D<&W|5L)D>I3hHdDGY@uC zRKQ37yP(ZuR6rTc!as=RD_~Arm|+V|?H!}g3AWm0^fBz{z8}@!81n1QH`E+(8cQa6 zgUn^yNiQjC?&E($%rd=&+%k4S+GRnMe;_v*ytcPBj>fo66s57?JGqHYk92-a{N*2? zbo=?RXCZzYmBlBABsuN4LV;XPDTWeHno&1EZy=TIH;~SR z9{HfZza61M`MK@M8Dgv~WjxRh8q*y};ItR`dPwkDmNnotv&KJS%Soo8F@DtrD|b?K znD<;U-Z;`VI1fGHwEe*`!@bfiBoA_&pc)7*yz(t13+oTjRD7p)Wx%!Srz=+PquYiYN5gr4j%_Sc=zM$9 z#QW)$^eBq)t~0TAmusT6D}AEtmIQj`0HqmJ0pV2new2T?qt^C)y0mG3b?g@Jq4$ox z-JS%DkK7{x>I3F8yu*lgP#io7*S00ws1;xU90s=|jbdtuO$=9THM_qgA&lN}U(<8y z%$09I{1QBG#$6>(lFoHnsMvz1Bf9lp3Yk())0l!bBrxoWRvt23i(vwfcJ%i=q8Gs?9 z->)R}2>VvKW72L zrgdXfJ*RvvAjAZwhBShMzP&xhoY=~5!`oG?9+N$GT>tk)ibZ8vg;HAn--PP~3jJS% z-q)!2KH%a5Mu{RT#JtesK>3bdTyxYduWPMezP(@|EaqNttl;~@AC$iJ70q|zc)E>F z3^0G0qNaN_^>AMQgQ0!^40fnNMS+7v166gmu3 z)6SF6TlOM;)A*n#V8=krGf45q5Et3Q7w*ltg=Cb>i8V`+27kK36a-hr*1jK}TY>Kw z^d@|Y>&QYM^C>-=`D*!H3V%1{$l&EO0yB^B2;XeDp$Kj<3i(FJ_AHs&of0}eR@6m$VZ#cK(Nd^x0kTaSTUhpv?$B=0rF^}m{r!Xl#g5D5U z4BEm@{=YH|mKApMiXac$Z0WXy^ZdDG_&3mkQEybL+p*b491sWo7p9z!J-pyJJztRiAHS^T9 zd{5LTt{9=WD}$P?O{t zWCokre7ApAH`ZpP#C9@G#DL~grtdZ$twITCDx})Z!rX@G&0!u;f-8Y(Ev0jh|2)h) zmu`X-nF!C_w?dM;`PBo@5R|esGNdcabD;lOKFa!eoQH=85ZMUC`4p4ast^zxnsTAf z2McjL@)bKoB!HC+T4&?Je?lO)wWUHVyV=DeGGM(;c;(kc!r}@2{81AS^d5FTk=Y~| z%YIh`$G6dwzkK67X_I=3tYSd9x4p&o$Zzzq;QJ^;=&-#%;N>|52k16OibqVc773}!6QIObTC zEIuUe8`8`Ii(-9Tl*Sb)QOpkVn^mC1xB>zXNg&NheZKReCsWRk>u;_*!vpD4`Ha^S zIG(ekPzyB$&*NVsBd?R{d>6!YZjO!q#2JOobeu(*$6HZ>bu%e}56Xk)xR9+%e)sQN zRl4+K>f`}-_}7oMheqjKW-Ea6lsp(>RRCNDUWreXI@GU?MFt7}NJ2A{-O7&9mgLJ7 zPZPHn)H>(ud^??VNI|I>x7U>D&p_UeD;Z{+-V5G6diUS{o0e8Mfi#guNN{j6Ai4qJ zLH2o$0h1{Dz+1@$c91s*DBH%I)XSdp03Yb%4Xe@4ES@V&U4mj;Xy4A} zN|DM*IL&HrQo<)Zzmu#eZy7li3GiZO--wCY&|S{2`yw~@1+g6{Mib^+Z|u*8@qh6J z|4!LsX$k-}FTVRo!N(%15a1!!idn0#?mjU^K>1&gpp-}L=g-xUl_ z(V#%Uf&&4W0{+DJ#N2@BsCFh{aw<-D%#1CGHJXkE()YhrxjlUU*ZTiy0Wjt%wdC2U zp;lgO{+m^Clo=!x*-qmT`bf{*Mo>2_I06sW)DyAO3J_g9CXL(CmN z$oAa#=wP!&Am&{g(_K9BG^!%-k}mxYM%l^jC1qaV!g4>fyXQV_M2PUc|I@PbOo|I) zuh;o2jN}{L8cE%FK3g|l=9D#lW^3T`@~EBG?Bc{i3X?E>*j@)I?(T_2Xk8Xx&Fx-* zAW$))Um0RetH{VXb~1EQANlAYVpXhv!|L;W4nKV3HArmcO8NE+nL0HT4KVllF59&n z@p9n%edRLD@{N+)UtT>u{J~+i68(~a$S#*=^5xeuVusZN?7sV;uV(0ZiJ2`PTVlJJ zDA(Xi$Fh!vvUCS^amUU=dt1|TPjw%H2h!cR)dP;xk_S0o=CW83ziYzq|}?e;ay zSAwDW#jQXNmeP;+&$Um7?ulXD$!_z&5hYjeE(F$=<8awIgguGRS%NB>GK$0%=rAw0 ze=&&TB#kh+$WG!gLxZQu-Gy3D6WX~FT2E_Ye)+j4*@S;9u3!I_bOj1Wncz{|VN7Wdu!~Bt? z?9DEW#!Bce92D}EsM`wN3fhE&vl411UM5+g>mPzwFB0C_LzUk*OX)jWmw_bt@)XSj zr%GHNY_DJjRsxp|9F*pKHr!)^x6c%yUd| zBLJ}rQ56{rTj~Pc9A>0#zrK_|=uFF-h)yL1&Jaunue6*Pkt!7f&00ajx;ou)6GIscn8s2lo1$!+tjI= z5x$=A#CHBsC*>0=g!JX;7@!m$Ij`LGB;PtbsaKD-FyzXPlt&%*%&xN|?1rJCWFU0? z;qNz@<;T*m(YVmvclNbYexK?SxCrRS7nlFO_t{;Rdxkjdays`zP43Y8NbFy+DbE-9 z_}ao3_Dxri;xkg=@$Rmz?lI@bdV!-Z9}z-Hz<&lswIyUBGQ zJ>Tmc$=$CTJ)TEUsGI4w=yG!Qr=iK}5`|cZNC>}^)~|Tb^nkpJqSUVKzn?0h({Sq= zL0EDUfRw3FYtVNScNO!r%jlEXuJ5X=G3CVxvHG7YUVv0l$I2w%|vU zrW`uWL3heE-^I^=0c%itGI<|iOuGj7WCOn_mCs23r>1`K%~_g$jyRHrX!S7PmHH&Q z|EZ~qnA5>gLI;=7X`>eT=51wlsdQGQcQ`r8dwoPK0Qwegq;VERPmD`qI_3yb` zt>08=hvm1s7CRe}7VB51SLW*%%RL^SCsQ$}3cc5Q-u_zVI<@)m!SbRy_a^1go-%d= zvR=?)k!$mpY*+B!>C6j-=`D07y*`6k zwhHEbhmfDmBfnYNvzY_hTk_-6C-6rxwUEEts;2!N8S0WPf#59bhG3efE4qPo$D0I9 zG*!7DClTuU!0_0X;*Cnov2E)Ez8*G27ab*_%YOgK(1f)oX7TH+)lHT?R~J;k0S}>7 z4%K-Yz?J51`eBZ~16&B>n$G8f3E(~gB%#42yWs8XsnNvtMEA*>*PiH_dqlanvDLro z8`ka!)+r#y@>B0l1|*#!IlGTXu%GVqh0sMWT4GszJ{xB-dPY5TcxvP~`8>EbV-p?xIwA;B~w3Zw?x-caBBe$3=ab|Aa{7iA5O?nsUFj{HC*6Tkw1I_1Q*1-*}n zRt6nTP9;$Fy(jyB@%PGb`F7!d9pfbo<1~d6=CCSpA+mdavee9A?qOU}p`GYkrdt(? z4qexnuuk2KS}#dwD&G*bj(qGNX}E?(Xk^i2Wa}F28ucJ?9py8kJ!|7=cr!7?>-x!I z1Rmx$DAz`vHu!vVDrnOSl8H?78S6Q>mwKQh5~ZTyHCJ`jYc79*VGlD)TAO@1^03O0 ze!Hvu$&i$)bLRuUrQhn=?w1neroIdmR9kyiU;p50S2eTAr`{}kubg|t9a$iZ4sd(YTCzr5s0&Z1ON@h{lQ6s%}>rhcdr>SZ&d~EFXPKiykxD*Sz(QM_p3T_FLXox zHul`m`Ynt%GHPa|Z8aY;cl)t(aw<>DGq4Hq-+L`*e+|zQJTm$8FkzA6!Obsm!}syy z$@8Lij(0~O=Muq}OHZxPb|HQSg~@_qE=DE-D!xU5$A?#=WdWq-Zu!yQ_tOlb&miaN z3{9pKeuTL95QO*gx2i~A#%k<-I~rm~o{~H6sF`>+e|GZ-ukq)+6H8ne#;)FBLPt1B z<(u_Zg|Jdlc@nmz4%^IKy*HoIrzdlLcZXbG?Gue`u8*W+sZuT;2@}7#S(7Pio5U-% zCi8A@lQHj5o#F9Y8_<3H?KPD+(T4bcVFwGfc^%0$q>oqYZ)b1DP^@PY@Ifl<1cCmv_Iv%+P;%9TFf!Gzc%*2PQ}+IX zaYop-dC@Cjm+$xL{|#xY4IJQ2Uk0d>F38oLq88Q=qXy|H^N#UK{=CwhfBUGtyI!@) z7j04r?Avshy>HZF<+cA?8Wdae86}f6pmrdBxirFy6sx$%B?;;6G`em=mP}evnK_hJ zRHKp5hgFLe7yLE0Jm96OMzLfpFC>L4wgRznPnv`hS`^0muP1lmJ`5i*P+|06(szcGSU#i8m+#{&zlOryN09dYW!=%%Lg%kRg6 zd_XPNAQA7XhQLt?gV(K0oWsb0>4dlmz0B5PJT9I~<>h z-}oRCu=510qH`=5Kc#Di7O4Nxl%?aOral5|U%-$T8+Y&39i`AOUvcS{_J02oysTL9NMF`68EWCYK+tTkz_nytQpF=_S$wAr z;`$8)LiJu=m%&)4JbgOH#O~x-a=)I@K@wP~Xq4o@Z}m1r9`&RHUY0kD4ev2y$I(c{ zw&CENOEwhiYRAteH*RnQPa}b8O{G~OKYI{psz4`(@tI_|@4+;}LI{p6Wse{Q4P@dxp%IBgKD- ze=fyKxSOCNnz9I;p!+-ZM{+x)SrJJqyv!Ue%Y~Ux!Hs>%e{PWzXxqYy6RzT0^2?WvJaLHzjK7{HGh{ai;B!_ICESq$ng2uVG5B+D*y*gZ&#f6u(v=-WSU)?p2cMf2DhEn z1rO-jgZf-+U`aaxbyBIE%yrA4zBzmikWciAUbg=Z{-TVKAd%CPAGl~+14I9DwriM9 zc)xo4Nl5BuNnWPL#G-DU5F+@NVi2|PPGaRdtjOWBzlRUJFljy;cz@Z_1);<)1Q`x; z>wkkc#&JZ#%`Wrnx=>aylyB{Ht+Z?{20|^Ee?*B$#FIVAs0{M;N33LF8qyi^BIim9 zdwCljJak4s=|We|7!F*&j1^RJl+(~2|CH3OA>aP~%Jcqu#pjF{8avrpro0m;k4G_E zr*Xf5i)jbIdWXDVKXu=3^Sb&^hZ!POclSRE5VS2eQtjhq#GiDU|QQ%*xmRAFBwS#;=a^AMkhW=j1-VB!3LIzH+%F1UjXiI#3s7 z7Kd;M>pqox14x@g@5P0w%s=mJd6|`s4XZg?Vjp=V`InbvEPn{$^uU`a@8R{&G_dl^ z(U1q0u|7%fl-PFGr!mL_XNW6b3!>_`!YaR34cim?gXpdWrrUiptS?gHV3NGiWXN_) zDPFdrj?AunJ-sf={!@TOUOQudVzeDc#-#|F6~TG}3jqvqJ6QjTtzNdf^z7m)@1>)4 z#mjDYvXy_jZu}B211AH=H+HZ<1M4ZSm1Ox`pQST)&QVPO)?8Zje^tA`1SDw{Z#UUnKGvt zuDZh)8&ivTG23wE!#4Tc=q9;W5#*X&59>A|9*UCSE6|Q&AF`o*sLAYO8js(%6W{5m zVX(g*D^YcmH19qa6@RnvDgV@Mr+H-P&b**~O`z1JHyCq94w-z8V5%*g_0!G#fIK{K z^lsV^q@uoXY6en&Mv6o|PPJGu(sfT-RWARqG3r?s5_|B2=}1C+b^5P-OuyhtD(A}Z zce*;w<<;jIpan7ET$sx+sMv-`q!i*U%CZ1EzF-5Vogp0Rczb#wW#^S13oks$FbdG2pAX2P6L!5o6tE!4qh+A%o4rkBaT@e-bD8$>AxZe>`H@`EqD7ErfyDv zy%Gjae*0?vdp|n`;s|@IVn3CBKh^*}F}o}Qlr4}xdPBv3O~L&u*V*ArNk9SC3jJ9p zSM=6>w%Xl4KU_w)O2VcDnC1tueHC~bnF#Qt-CE71Z^_}|T$E&9Y>)zPa~94c8`Q5I zIAJ<7@iF5+{m|6kJGg`W+UGA`Owy#~y3|NXpn8Sru!}%993*gA%0k+<>`|ZV>Y5h= zK?0U65MX~J#yyj0F#EIAE=aKPyJ1=LPFug+d0Ney26?<9B1j z4mXG42128xJ^JcC$7J6S2R|tN2E-vjx@Ck(ih$<%-{eE4g_7EuRrT4CFSo43O>;hu zXpl*mP}xXYm~dDX#UT5gQoxT_*@u)}lH1PSEo>CAm@H${Xz-R2R*&SlnJGWIdDq)- zZh;QYQ%72LyM#7Sq|)j+G6+o0!aDDuPRZONerx#^)j_0e3CvLZ9+CT0u13Y(f1@~+ zFzMy0!Alui0mXq52nq974-{PkzqKr+T=_#fiO`q=0Eqz0w>#S5$(*Jtlz-&uDL}CV z7(GG_z$mz-QAz@)?CR!AXxcqWhK4u);AGLBVU+uE&oDUg$xS|(SklyE5x^xIlL6P2T1OaJEmrkTNX@Vkx6zL*GM3EYL zRjM@Uy+a5sfn@hC-`{)Z&b-4+l0P!cZg%&1&N-iU7NV*at|5M}B9T0XX?XITti-u= zch0Lz7bb;z@0b&Ty=pGzM7Qsbf4cFjI0Uzyvch%tzhBG^bs$uCCf|24@_0k()zSJN z^8L|9kGwazqU=~vTgromCL17>qF^KKSXtfT8!Ok7nYq_ZDu4LW`4EuIHGQZ$!@5;0 zVEM4ep%-QQ2#fG8(Lpb3iF|f6g=f`D?)ug}JPO1Ft8UrUy$n&#@L`hk`K55!xf1w^ zbfMz}c^t|rM}dk{PB|rx)@Wv6-PG?>TP(zEg!@`V7rtV=Z46La==_7mXat2k9D?bXTZ{0_Ztm8ABA zzlV+iTMp53Yu0T_u_+fnT+_BWn5nIW+mv!TR^xhFMef*TS>p{MmxPmlFJ=qlj7s%X z1k$Un47KCV9c~MXd_X=OPWRcZsyBj6(^&NkSMT~m72|kE6U}@@xk=SyvRsFRw%8$c zs?O&*fpVQlb57W~p7}fBptF7N3>+EL1^XAEYtp;3PINT}`CINLT8(P|>*j%^-#UJ1 ze9bWU5$ZFhk(!A#V<$A$L@LBd-#P3m@w)b`M&cc$ z+`Xpb2N4PC->Q|eUA*CHtlz@blkdHCH*k%_;>v%Y7H210<-l zFZ1DS0lZzu0DrAw1XMPiyD%ww*_(|tpUnz#{Q3CK2$*!$e8Ovuz~>?x^ioy&_;Bjj zo$2o}3TLyq9ogFxtSMbTM6Xuy0_=#b`;T!2XTPRC(F1WP>%DKx3IK)1MGp-B$kjW* zPF9x{c311Ex_#_mzFKtu%U!0;e8+202=x8ZPOizi13YuPq)B;sTgUT+QUtTK8zX99 z4L6d!pRpxT%rg!%wYe6W7=O6Kz9>qLv$M_t*;|gHeO_QWHscw9xZ#}MOj4KxUiymd z1H@qh{PB`%)XmLbq4WxFtQ&TD^Z6a9 z>cATU3K9`gK*;1I#|zv>EQgj9FoSVF0CA+)_9@sUIV8>*&P&Pg87wj?Ghh;wxvEM0 zRJ8=wRzG+$E2~D*ATq35e@)GC?Y3$EC)ZH+aGj2^JOOFXS9-^;BC{J7AO9u#?@PD< zc_|YcgWrjeE+;Nie!FV?k=H_tt6Bhy4!4FA?McRoS1pTztcq6txP!g9o&ZjPb?)sj zQe7e4iSI=SXrcT2lx`v-jf9v&J+>>(91V*3CvLIFIt^LW7HDTlX7g+y_jwqvV36Pi z3_AdKvLZr?FM-J%IM3fio?T@3IllV!T6g3=l&B#3L=^s-H3!)>zRkBy^G(hP$2$wA zEjYB`14!up5On%r8pt^+`lgZm%^P?q~R|rB0z%!@g}7WVH&zt3;ekmst)M(AgrC9 zIm9OyXw?82W9X_YMCUv8Z81Vjcz*J`h?K}X=NacQb9W^09I;g73CnZTcE zERscp@A;$u-Jg07FOkQ87zp#<5QO$=OxD~PA`ASE{8j%hR5ac&2<%QLd$iy->+0p< za5UtB?;Pt|Ur3?MLj1#BT-*nvN$lu#ib_fD>oe6HX@sMH$@hAZ6}3&zZb&ahdGi0#h!bmSj1M6(_P= z5d*Mjj~pue@pCc+i2`-iXOhplG{8pxJ4=&_aFWkDI_ki239KIp59QIq26=F*eo(@~ z`BqMqn`qc$&HLa5-P)@mj07PK2O4L6zqcd^%XlB!f6$^xmUsE<)ZD>)CTb-3M%c-V z7z;;+R@}1N3ZtS(iKFG+`f+RhwbJ!;^62ocj}WXMBZ;?27U;EwX`1+asRU&k_iAU5~4Bn&~R4TF%KNw;7igzCYLX&rynD zwzAA>cMY5zoNK!unxcTq`=UR&~hQXfu#dUO}EgPXS%&Z?C1Q0BTUuL?fx*|U;BHV zG3zDdVj&(!O*)LB{rJ(}Z0>T?s#}4K-6j55LF0yWA&XzJe+*Qs zUvxxMbv<~9-64$_8W3rIqv21Cb)1V#{V+9uGD{?;nJ)W0WjWCw(?t6Ybgin_Nz`Qr z=KSV(yf=mngFl!`z*X_d3fuD)Ssn*{;bDFvhe-VC%o6^zUP>0A?tq`gQLvvjbFjyb zm3;aMW=nxWdt zvTGDB&$8y~0rkz~WTB_&IKIfk&Z9@1kB))V`43l?#6Ek=Gb#@~|UI^^)pOzHQJn)yAJJ4kg$p z+$UZ94l~UPvZTu3mNjHMd9k67qurvKu-D81GoU32lSbGLC1J;SxuK~JWs;Ae?Q{Y{ zu0B9%23ekf>k32{mjbJ?F@KPpL_pNvPs;Zl0YJAo^TRIwXw(Yy4X(i^|3SC`-eS8V z6QE`oM-uR;%&JWMTNlT@Wmf*%YW({p&mc}rltRq?)Owjyao&joH6rdRXO_`#@0qGK zBV%LRyiKK(+j=XIWc2KCj7${&ZUveru_x+>v@r`Bu3{7@+S6RDXrU{aINZDOcMIQ6xef0nt`NP zZxw^i9ETBI@weVhe|OXxv3u~26E1SW+)!FzqHbYYWnv7WxN)u-If$hI>;e*~YL8o9 zxaq^Lu6Fz8#R3bd?fG8`-55+p6z+En4x?VxjcCT$S%F&VVD=)EK@E>T&-Kdt#G3$Y zY`*`2dw>P4nL!G~3bGGo-+B%{$V6m8qmxToI<)pZQ9D%i`FXG)1^NU^PG7*B3l4&0 zJdb@R`{rSZ0Ou{bnr6_`_(4(hRh61Eq=Ys2?F>=(_&-j2B5XJhQUEM&aPS)on4Wrn zeJb^kXN!1JS=-}lVo>)*gB~?ovZs#P7(dQ?ZH`)dAVH^4){%s`*YNcRRR+ZSr58$C zua`KlUO|18Yj&7lEP%xIQ z(xiaFeH)|KE{JpFd>_xV;e=IRN_pQQDkWiT@V=?)x2zBkK1)`-OEvOZbASbKa$0Wj zPXEdWE`;vfbDk?soaj+pt8CbInXdEW@S>pt{MHIEbuN^;m36kgWb6yU!G2=x08D$=R zvIB&Ez2e*o8P)}iuDT6?U(LT4daddO z3ASAHWA4$&Z5e=BFp7+gw{G za2J=C{^Elv@foJ-@9Cx?TEV_?AZn4z^oPqbUBKExmFC5by@>ZkPpQ=XIh9V*CkB4f zprCs3&O1Tl5ibh<*#=|R={k4#dvpn!Xgc{6xx1LF$-g8B8)XSg_Bwen8J9s zOdww1ejHA&b4Y>com?r<!4x-Sg(m+-b*RN&Sp<5?=yEQD~!0fM%?zKkh3+@k6 z-g}n36t$E^=z!Nz67tKAs9F4CDfxAbvU96ee5FaUpdDGJ=E|==8=}i&Zs;UG#m*WJXwN~i2TfH4$Kd5 zO62Z(yES@B9LP!BExqiQdN_0=cq0r$@lW?l!faIa2iM83*QA~#sVPteFo-%2<;-p8 zm)S`Df>g}>yFoH4{prF5JXGyF)noVAY=tgv{U{u8$gnQX=g^`P$@e{2s53oNgP3hZ zk4b7?-&Hu}ql~3;X8YaCiv&)p98irB<2woWm}5oXHf?Od?0c!P<5fANdU>;VGLU5S z{T*4JNohQP8yPRg6h%Gq+-4fCneu7eyi$B&t4L87kfi{s{vPurP_>7+XUX;pp^SoD zh$!lhM-Ki~Kcflyi|DX_+=1LCBBJMx$8hpwspkTZuPadV+LJBZ@BNX8UZ@NS3Rrt* zN=J7H+HDyG&^?@VU*s>N+#tYg^nJ3Fo14`SJZsT~7|i^M-(XLB)$IGqfEcRltJcE^ z9L7_e)K&(HZ7e{AfJ5)zS^{VoBDK=`!0V6NK)vpAooJ2RmfiPfxU*vpC<($UWZby- zlW^nH>gJ7{pjFph%2J2devWwXbmnEoMlK05C5rI-Qzgv!S?DzRZKgvJ(v_tFFw{IT zfS|3l3XHa8$_et{UyAYYP)iK;?=0kc&imvyU5m-h-i5Vyf?u9m%zG!97r`v zwS@rjAq3#$TX{eBjO#sB$Z!(w)3`U=NQ_>`=Wc9h$VK0cNb|v{8eJu9By)kHPUi~D zy@{A;`M`7ALK!zx=So%8Yns0PyV1VSfKikq3@4P_k?TAEM(Vhmy=-=%=8<79)tBpA zZz=IvnYbW)7CopY<0j8C2#at(F5$Ev0gd&-XI2dd>_O=zWfe@HR2n#>JQ=t;Ci&cagKvj zh$dk+omW*7?O)#1DhRtf_&gJp6+VAcKu@uw|9j=tXQ|iCe{BV%j62_2SNSAV!W1r$ z+4G58Qh+^@{I_{4a;ckT^#p9HJaG;1Z+|i0^g!z6JYT@kDlIcC{vBWC(2u?=)eZx< zwn#e$_N^NwqQH#}U{`^9niC@H(bR`s%vXdH=nIa`Fwi4@uJ{}y>xP=4DiO*~P><@X zTd>05r!Wo6!<6aH{QzeqCaMOU^}+{XOx&&JP`RUm^=8fh$3AGv$F2*xWNK#)1Ufd zTdUxwy7{m(2iHliE612ah=(K#H>t9^W~ueXsNBYQd!j;+=W)88sKyPB_kz@KCr>)F z_Yl52YN1eTJNcdh3QbKy0)q~|f$giL|2t5LL5l_H&1$Oto6gaXq zhYbenF7W^sgd6VLVNbLA#TkO-a^t{iOzb581nhU*Hm~?Ok@e3dgs{jHHJ8RTIpsCHbw_6dVZN z_l(^^xi=ATU3FG|L!u(8^4-jJcL~5>6hTQs;tUB}=562+)D55IG}l&GWU`OiDj#z_ z!Oxk^F%W@#FEiT?<~EeDM5hs2%H3R7(1j7yI^$>)Wf7dx(Ql6GjHPnE4DMtlG$}>& zG4s_HO$ZqvJyrM}3m#A#90C^yR9oQrj(e{mGN_;7T@OdXZWyUYk1l(R^ry4I__pWe zqqeO<+gl}T5CK>{;Du10M6xc^lIbs;SHRhvUy;{4fv*Hi&jQR`Fx5-wP1@wHL!|Rc zF?v)>q)ks##CTPsp3m4U>Fm}16b}s8N_N<1^_O*tA7?9qQ5xLvl2f22>Aw?L`_1AG zkgWp@aNgPcjsPUycuPAo`H^~zkn0kWfG8S9YFj-84t#QS|8Y`r!)!O>)6`6-1sw%h@*vj(_1}Du|b&^qcrFnnEU?Q3U5?_P%?6DuKiawkTcFk`-k5 z5T0R`QuP|4v5mmmj1(aZx08JVJl2YAq^|`|unb3X_X=anLuVYVW5STZUshwI^*GS#V zLt;%EYJR_|OkwxbB+j*!fLule?^)CuC4V*hrT;#eXaB|7dX{@Hh(ChYJQq1j^Y)O4 z0Kw1;P|qFqXKl&*5#&$%UNyN`>l(N_3|3ZJuOYxw=`PvBMLyQqwQGj0CA_&fdJ0dq zLTG}D#x4)>_~p!=f8Y{wugBhE6u-f(a1c7Z|CNDJwzu20s@de{%b72090*q8 z&RkEJOtiBVw@5SQGma)m^1YDxRp>8QPNphSA!UoG^kae@B>AIKDVB7(q|&-$-Wz9sL@E5)@b>im*ky6rRsr84Ob zAflIrVx>gq5{9!m5DJ2Y<@23f^5}&kEmN*$fmWi?v962_ku%L~;)A|J+U|inyWbfz zNUzjR=E^*5w3-eZ8tqzI!)%Ihq`t4PXdSD3$Vv*|D>LMEINlUP6Dknj@8tJ(APQwi ztpOZ(&3`{!c{5B)^K7HNH}39bj<$h4_A+nAjjqSxL~LpbA?6PvHLJDCC{iG)*ax+< zGX4E2Ce-NXGg#Z$7RQ>YN>5eLezQgZ+ZsX~qmTEye`;HpA(B`z(%GzH`qhjJ8Mu7C z{`{Zosx*ja32A!TMrezC)1Nzu=+dH#$Pl(?2#L;ru;tl6Y%}D&9xNcz?$nPe^j*5w zdkh0Fq_G=E2-D>|W60UusJpuQl z+yo?W$>c>|>cLKd0M7~JrFQ8)1Z15V{6&g#%29QC9I^#}CgPrq%Jd2OKoyZ0vTI)L zwOfPD4lD}Li;RP9KTAvERqza?VxCS+^kn)rJ~V1o{z;4z0R4Jo&J@zRiS_1y&_xG=Qa);po$U;V`xRb90x zBmJ~hG^RF0n;1oAIHC#MCDg~9bRm3ofM7~pNkC< zo$Mc+YfOi$481X;-J$x|&AJcS$UOQd8tLj%Nr!cu_L>tx_om)fVHp$&t^zm1%nBa* zmYEk6rwdyWFFBg_+cEamo0g8fB1j&*0=ARVXdTSX1))aNT32|W(4MY@#_He95B+zi zP)uUl4?(-G_%BZ;ORp1&Zco<+&?-ev3Avh9rP5ASiSZsEM5Q31-w?745bAd4i5cS# z3{+YjI$Bti&$*KZqnGn&-K5&iRsl^PIReUs&%|%dHbkz&zx^}^kI*mAW9VZ0B2FOQ zQ!$ur;^D#;ayw=oq65ll(~e7DrgS`9Yx}?ZX$*ueWqcgDY{B}OE+Fmo+>_gK3mzX& zW3T{Aq$p)dGO+oX{!vHP;p+0IQqwrcMXnms^?k0Aq*WtZrEu9C6gv-%C?+ajK<1WX z7tpgP9~i8$#SzFEUZV9>xe2L z+92_&e$-7?H{A6eJq;So_(UXU)MdNqaHRW1Lt6^0!DjqHihn|Ext2B~h-rlkZiiaf z9zoLZnG20!#ah3sBtc-TDVk}Jz2BI+J^ik;XZ*ms#A-7jd&>$dRC+Ty1hPYh%gy$?N9{~JEO{+!p}nhbm?j%EArG%rtuWIUo7qScf% zBQ9*k8724dWAiXX>p|{$i!)~Cyr2SU_q0`rzXoVGtYdz*v+xseKc)H(%7iSww{XMX z_r%{XGAI)8AS}G8?LX6bzuy3Xs z-$~~;beNum59mb3RhVsgZFy-h)KhTThXkS_28kLml{kLqdN{m9F+2Q{#R1PkRBLp; zJ*CP*$cFPdr*n%DK3Fe+bsqM(>fP)_)tylVf#IQf@fh}I#NnKN+7>LO?HGwzcym39 zmim7hwJf0Skm}<|H#jwEvUzi1?c{kD_$$@s;>RC^G6jt5uC?8fN*0*Cf{VFSQ#~@g z!%V#L5)%WAQ2@o10JWpx=@h3{nAmID)J~ zPltzE^_i(NT3>5YsrNWSb2^Z!9z-5jA^M<#>*g5Zp9HRLXUGQ&@#l($LSSzVd3BYa zHsy3ej;1UK&bv~8S4(RsfgQ^Ap9go_^#|xqtIHY3ks3P!65c_7V$_>4RiQR(-Q>_z z;lAb@^6aY`3unha=OMRe#++e^ISszvT*3nGd7I<4*^Lh0 z4?V_A!a)*R6mJ_vF$*E*83N`8E)!qMZdQlPyfXj(DlrWL2u36Ahn47Y#P%aucfo}a zEbJ4oVyb!Hb^JY)yrWq*T2%P7ExZQecANk3D*9?&r=ycCbED70fTsVk|7UKx&EeRW zYhO~g;G~e=za$M=$~TSK3HoT*U5r42=aZ}O5@xv+Ge{*k1T03iU9#wcz+~qxkFTV< zR;HdAQs9lrSG)L*%S#76%g{xfKz3Z`G2&k3V!a)HF_JGSHEL(o1ubBEo7^(Nd%RnfbEe;7Q)V`_7X{(y2uD} zUA>bE&6h6^i^C1i(@<%@qidEsR_A1#8W&pLkoYL;AII$;E;D5)8+ItM{ zLU$3YnNv>#9VMr^)F@RI!LWz2@nFMET|j3u^Z$D}kElRSoexlX;-k2pV3qPkDE#FY zdx#~;(EpG^n_0YYf$S5J-u;~D0GX6!)xB^bjz>*CRVWvi4afWjyMz7eWwXt-`NqG{{M|R^G93bAlk(g#`TCw+Cp?+O?12(Ybv@>gXKN8 z=Y$LdG+>^zU#DgTK1BVyppvIJiM_nc+ELJcltlKJ%o5CdNqU{|87?{_sk zPE6hS2{`T~vvLyE59cnyTAcCyTB1JDait4R@~+8L#GlBpJuVet-IsHfvQ~oEdTp>C4?ongFffv1ROI zusr4PpA`4&E>~DL+!`;V6sUKPMj!fd!(UcodFL7aTWLPnY`cDf+b8jn1%Y1PI-@=7 z3rV-6z@!3YRrhaLKTS4hbH&Z9FI?6F@KYd4UtC=8-{txIyO2I!K0Cx)s(skLBRaa` zxmO%i;idqFVu3B@KZD8&=dD+$AWJ!rtgXyLA@3{9_Zek_6heZ@h{PxEs z`O~WhyBE-;1Y79z&CZ}&Ido$=Nhc74qM2@Z(Rix5aIyR_cvc|;Fl|u{;5Vr?GrJ!o zb)ndj@jim&bN~V>(@LFdeAN#`kYs;R78L0^gux(h5pjnT!7;U%8-0+z zm-F@l3|o?76@Of^`>71~j^B`Y#gKqAog3=(S{Xg{0vwMxvcPHF&^l5Igk4}^&)cPd zX$%;W1tN0SVVyjl6Fz0X!T;9><6&mj=!7T3Qwteq?rfnq=l{LHiCt*Dnt)42mURyn zS$-EjR5SmaR+vjjaFWBob5@?9c79)a(7!EW-k$4JV19)F{!9ECJhc3zeXh?#5|cM2 zJBqX`dTdbrl&eVL(Y_7KVM4+RuWm08a8Oy^%A8@Ts)q8IUA6Iedbn}B4G~f5bDwT-y(HaL=0nX_LhwpFL75|mJ)w0LE zNCu260)12NTTda^KO?pVB3~}%HB0Bodr~yaKiIvT9=?-ucK&C>Or=4=k;;RoC#t=$ z>VfyvCM1JVZxMB28iOdLRz~Hf#+u$VzqzP;n2=R%>w0d6CRh^cTV)^x^0FCqmFbj> z4l!Y28Q5egRTf|8&4q){fY|vA=J^WDmj!lMd%`ie^x~3B>xNI0Ygb_S}`2fQhTtNbpWbj-KeCg+x2IbSpo|BMI2aDYmtoQ%JK!gsNO!@@zx`NGr z1ZuNlGlw=2r^lvt;qw{cI0hjj^}v&D{(7&q!Bzy?pFtrm`XNQ^zf;y#@Lt{g-FE`U zK2m8{u`@p%1mE1bolk?|d^>nE^g>6H(_}LKmarAy(Z-+g$){tme|u~oGUmKaEk3 z$MVWl2nEc0z+dBkXeaBB%5!Zu-$r_Wf>!W9<8K*ks;wj~anp9Pd3*KM=t*PBSci0N z9Q9MK)m?*B1n_g~F2)cM8b8(CPT!Zlkx$|B zlC^rdaN~C*EpsVn)0a8Nt z91?&*(8P$0j;|Dc&r|H%tBQ{XNEM=Y$a|Ky%B=K^kG!sgUff`_T`c|LE25_>>948Z z%-MBL(5*ddbHrk8mNLl1V7XW1ooPN| zgbxC+9&u9^3==>#q4CevDwSs9(J#h=^n>>-w?4^lzhy?qe?u5o#Ge-R5;ATww7xDa z=;M(CCMzsWOF@}}srryC3J$TiLiP6N2qb{#ac5_w=Bk5eS+^m}43!<>d0Yu%0eDNY zmoLmJajH07>pXTX16gU^s5xEZkWMD4Cla3RX+{|52GxY_L16Wn2pgibcaHVO$EBNW zh`bt~CQsZd?um-Utho2}5Su+pm+U9&Nf-%B+(Tz8!7e_o2Cf zL$*mY``;+l57NnP<=%2VdF0MI^bPdejipX7E_dZM`{hLA@rmW{pZ@7g)PN7op)^KT z7s1i+UcpAQLyRJp;S1=yGolTf&9AH4Nd*>=;1$N*#d@+k-APQhEvbK=+6^MkVZ*v!8-wL{*d!dky3IH7 zcTY)tKx7YK{CE|p2j1N)SI9y>Z4ok~J`N+l3fhf=Rz1iRb7)y!`E4NY)GN<|c&CvO z3wZXA9g&)D$bjNla>y;>Ap8%qh8ffbF)fKui=?vgpCTfjz=qikPZPN~kTyvJQGRhf z6AOFzWD9~om4#`aT8|hMoA6)8)HF?{oPW485?L@YN|Z9Pi%O)8dL^2<|CSrV=;yv5 zVMYQZ?U4t|t}IU${at+IvE?99`nMxC?O_Dfa(AhJ@$tbtWx_w^b|d?)cw=$j{?!x~ z8)>6oUz=wCVNHY>?FeYEKz>zW%?&t0!I#-YIJ1F1?-k?@6N3hDan`}@YZEE*fLW{R zrVyFyS%W4%c|NAX;z#6utCIT+BooSdON-Ctx&<-!AJUjo@iW+stRC3)FGOvEF3MLI zGM#*~sE9tN@y^R4aR=lg;(;&p*XLQ}O{CoZ#U4$SzG_+WuH~tW3~1?DxWOj>*mpQ{ z1x6XW3un05@#svX^(pg$%hLivSW`uXe06*EB>>{ zGy32oc-&!@DlMWwO@R0v^vr?$pPKl!LNDZVWklB+#RYt_5=y|PQ2ju7<3dc)TI5df zi=zjhk=%cX8G}=}iytI{I^yX!HtHd%ttBXdkH~R6k5NNiZVrUdLWoty zfx`Lx3Stk>JF^3q%aH3hVYui0euqko=<`8+=nwL4)irKczh_yYodurDA52R=)(WU@ zwTUh!#+G;#Cx_g6tZLWZ>~l3mr;GT8PzjU^c}&dJ`&*(AoSWN+g73_I#{22T1IXIb zq9qf>@*X6tkCxg#L)~O*YcaJ6d7zWylYho4s6z#VhXosab@J@Xh2^p;_~@PPP4hyC zIEhTOSYI}XMX#kTcO?ks1fA}sKGR6DmITsTqR4N(Z+}4cjNpD1t8Ae94K}&2K?X&+ zS8WGVfUbB3BJKFTdHjWPvLZ@=AS7)VE*qw?p#@;`=aNa3NT(__yhMI}B84+&)Le&g zoOW{~N5cj#OEgg@A1ORsk=nA(q{V%%#rR<&qi;6`V%!SwXl1BkkWDp|`PY*<R2sh#^O&Fky=k^JCciphS+3T!>*Fr}==iOg*I+$;+p_0rO<7-6ce*E|)@E*tcrU@Fq z>FJ=a5jpYIqC(&wy+7w5@51*97#9QgF>LHGMwC6+BTqcSA*Q3_#blDT0E~e!)C8Y= zUcz@gtTdci`_Rz%m1-0I(M_D;2olOTtZ49HX{RvEHQblG%HFaHqm(~Vqf$4y@o>4V zND_b(Kt$6Qqr;Ux`c$1uvqU3BdNE@v1Y|g|%Y7l}iZ4Z7o$pI}4krayea7R<%#mP=Wvi1~vu$wBCI!ca!A(9S`7nYTW=wL79QfD;YLWBplcC@1s5L z5Lfa>&k9o>qveiMG{mRXf=qaCdt5>v-5Sr^C&0=&$K%Z1P5A$vT0C13F>=hKfNYat zQs5$sdaI7&HTVl?c3tIGiEMps#!t<{c*H4VrD=fI%pBcu(iT&B#@?Sfz{*JN89^@m zRc*oT&N(7f&ULM_+ofmrN4+*!*Ty zY)4Qpp#=5#dsnX26u|^czw!$p%0>%Jsr*T~gjjNtIbb>vVwWVO1EAOYL@p_nQ1sek z8%9a&Yi1J83q?l#)`Yn9Br_@JS(#j^w>IR`dnhAf%Kmg=g;%F_sypiC{8QR` z>8Tr7kJ%WD=ztFjpkZs(PGz%+%lOy0YfJ6^%1=^Lw9j63gt~jL|GtK-&gD+nUg5(_ zoPvQT)a|v}f`1wv2BaXFlH}m`Nid-m^;ha1CD(rcqe`p#+FAZi*2T|@yXLu?1$PsR zEXG|d&Qv2?EJYEa*|@R~F7jhV25XPKPR1u8P>cSH%`Yc;OC9VSSwY_ulq(g5Rs2nT zqVPV<0wq2?`s%3tY^0|bU9`t(f{SrE8KupxY4EF?wIGD!t{NUEtn?&1vnYZ`wqgyo zD-T82rRj1SWB8(L?8o(m@}ST>9VJU#{eD#p6hiI0lf2wDV?MTUcs*0Ux8v-1=o+E1 z2BOlS=nIsJW{z&7R>lOjie#)g9a|zp70=IDWj)CfN-Mv}0HzTc7Ul0z;txV3kF_%; z%`KK2pbpG{l>8fi7>+H9z~i*%`&!o80HM|OH`)o4U|02KE^$jn^R9TGcFXsBW^Qvg zS`gwFw9XX&oHs2N>Gnget9u9H%1jE11BY(5+$|;AKX`P0#7_BQ7oN0nLup24KZ1(w zQ~G)@%OYajcv5rk=B|d+_+4GQ%38B^WGI(UMupnGjoA z{A*Yl=1$N7<%4?SG_=B&Ge?ko$GA^^v-?hA3`Z&v#40U1j&Vq(JHd;i-!*jahkjG! zP#rp$`l-F$M)b{hM)Ji<(%#HC-^Aw!0CVUz{CrwGDwhvYX7=?t zvefFw7b6wqVh@3EfnEIh*tlL}Xh$7-i+7V@7#oK%ZEE^F>pzzG@754Vc&+tzZAKh% z927^j9Y6>CW|F8qcwUScd=I3jvb_A&*H$8Q#fyvau~qx8sBag1z)Gr?5i6taRL+l` ziH4xy*qOiH=?MaPx@(Vh+*9thfQKt2%r(-%jVelEfPBCx699>WJRvi}O}`0w2J{b7 zuDHz47`Xlgne)W1oP)v)e(&5@JmepRm8%Y2VjmP0aWrWal9=8e9GlY~PaIphf?j`t z9{HWwo-AJr9&#C^17F|D)$6Mb(lX2AcWb`sM@H6DA0Ju#roDwA#y82|XgTFt?*TV4 z9Y61Oz?g!YV}2S}*r;Jf7{;V}&kFm}teSsK6q8`2o&TwCtDQaq=|33$iKlad6oHwG zLsV+a5rc`!&qI6H{M!TdWq~AC`MW!^H|&&tx=vP7pmrw81t;x7`@C4B-BN~Npq0gs zmpo850)5g8`zvRm>lzvou#aU;pWC#tr7-nybhg$P;{pX!6-3o%jvks8acY>r5G%>_ zg362`VH2#)sKdbF+p=sFXvK z-6Z*yk&yO+N%q(_*z@zTQhhS6Cz&RdW@Y39`bjDCRusE$sEg@^k*rPOo;ToGNc48O zOOsYNR4pvt3wyvO{4<#Fnf91qR(oSS@q_+IU^C2@W@0#BZH`+P6-!)tx;L|=g&KIu zuFUkO*pM=6$Zm_#)@k^oOaS*S)-&fv!sjP@GgJw3mFxNi54Y`PZF6*h_zXTS#fCGF zd&)rFd@$|2Rg94oR1Ms=Zg`b?Q?gdTg9JYLg>OZuNSXREr42QCHAh+_y$D#38dqY7 za>6Zw@&5WAP*&!WJpz52r3Bs zL$tvDaW+DgmOD^@92PxF!$r4sxZP6YhcZ{p3T916DD+%XO@HM7d88Gp$;`Y^hPJO8 z067$S^fPW{r8`h7q9Rf4|2Py|{H;c^)S29XS*{vCwA$c zz$k*aM$V9a5x9`SAAF4lg&?7LM$4O*+s<;I=0jSC@V)vDXT=gJkpq5a*liY2lw-BcRut`88SF)9zZQCBixq?!lEuUV%6^_Cu68 z?~bkW@_6x!tU`28@RK-vE`~}C(o6RJxbxuO=SsotzrGGv?(`!9fkftOD{^mRsx}Dl zePEzzHL|2kXqPaX2xU@17!eoIHLICJ+6!}?5HfG@DN{2{76URgz|SNiiO>30buSps z)$_SUKM?w7lYCa|Z6i-&a_`#zCBgm-RhE3wep{Dlkg!MpwnkZMhep zoOynUYeK~ZnL_xUJ_J4&ZhYUq@1hxVy7wdL_o4>2%J}oL^H_0z&Dy{_%dfop;3koV zp3)7&Zp&}-3gtJR89_w(;hfd;`>WH-kdXk8Q92UH9H8 z65M6qq})z?M0>Zbx9w1|8{+r+?0GRLP-_WV%nqanDp)+5J745K9X_f3M^KLdBhHp6 z{bjCfhGN3{d_~1aIg9WrG+uw=Msv@ftsigIc&)iizUci;3d(}NXwNf=HGf7tfgIjZ zG-s}>8iG%*mS9f=fTW=AXAg1js%bDnTZhTpxqI?I2V!l7@3?b|GWYogt4-4n91=_$ z1uNg`>lE9TdlS~VM%~0G_Jiy^r28sl{7R<50h=^AW8*5k+Y~m99Ms z`E-fUi(@Ub<~0&UQ?9uPTXSE&GiWN23$BK%pudz?jn)&~t;yWx=s!NKm~mKjLK&wf z{>bDQw1SM~MoY!cdbRF*yT{FSK6<_urxly=Wf3<62)uO>jjXK$XY?tRZ-yW!zY&@V|LXE z!z4`wlu{8UuJZxBl;8xFCBs~l3um_p$wT>TQ+Zzfgwrw%Vrm9Tl#A6w-}&v^6tSx>EvnL>lE_B=6;m z-|?xx5RSB8Ythuq^`HsvGx)ocbFLtuedX3WB*bqUpp>33{X5g>j--e-O~^n(w75qd z=aj)>(^L^Wiseam1kv;I6yMEmEHzC5QRLK>B4&*CET7T26UB+B0lx}{Ox3nE z_Lv5`{W)Vpby~>tFYGH7=9V{vVpoJD$q_ z|NpjQlRb}-)i6S~V@qTtNyf>_XxP~f*;`R&j#aWtk-axLHc>eCc5rYUXZ)`B=X?A8 z%YUxpb*|U*`FPy#PZ{;yW7S34(XUHz-f0a%pzqnB4uxlO$rY1e>fjXb<>sg>Ce84q z;f-{2p30m^{MNrB9p+dL0aD$&_sj_|xU_>CR;<}HZa&){bdqUiyBV8aDl?k?cpajy zA`hvt(PG?Fe91fsr`ub8$cRMRQ0NE5_T0AO(6?o?XXdIaL0Olri7xU<6Di)ucf{?% z%xzD+0)4fd$^ED%%Bz(~%*^M^B$MMc7*v;=?{XhzZv1zGnU+f;=ZKFvGM9uZAnmE$i1bYtyjvF>ZNGfictpgKzK+< z)EFwUOMP>>oxv}bAVvG3u)6l~Db-K9|g)fPaOXA^(QeXbcrIp%}r@#Ppo4Sv8Olg0n8G zm1sdrGw_EiB=h8gKq+4zS9_RQs9<;BFu?gHp{Mb|uvbwp^#_*8#(Bdu!K(<%-*zqM zUk?}4WV68hfIE*0yqoERrf?McBot@-G+9D$BK{HMosn3t(T##H_5|K;uK7AqHPlZM zEN?5SKMWNa%V*l#!7$*$l`i>fohTb^zx30)Bv$%1qdJr{Sc6l9ws1%s`CDz@E_9yM zZs57@6>Q}3?ax}|spV3#p%=lrqT@l@NbQOduJequ@o)7c_8BHO-hpH0r?)W!!Cppt zYtj~ML|u#!{v9GLdqSVi?Vf$K@f&~2`eNaej-aHE9-8ZzddH3XIbTAask)5GG9KOTIkYKKQj9ZZmMbK~a2N+D*370%z0X+YDT~NbR=2 zCwik6JwN=Sj~ltne!)7RH9GLDN|e0>qxj0_vn>o?uR^e}V}U&k*_-{H$eEHMAg!Ss z`Tg?Mc8>@OXZh4E1>~BRmX1ZosOGjWpLz1Ddv5=W`2V=t}l;27H1gm*a2Zs2A@ z1RWm{im?Ny@Qu(r*dKJ+xc}G)?`Xfk{H_Dsmo?M(mw-U#E&&^G4ah@%L5swil%w(D z+0Tv#HlY(iH$)AVRdDF3O(HY!`{((v7a)t~4^(?w_e-;FL^tB-Xq8qOVvoA2-X?q+ zvmAiJzNDd7R77LUj9RDuRozSx;#>IXg*Xcj@CSX7ZmX zE!1%%)x{l;^Fl7K$JGkN%dAV34Z^0|_xD_Qv{4f64=-$MNlodbj7_){way((mBoU; z{|j>El&8iGB!M|K#EiLW``IbWU(km@3;7Y zpL}$V7G)-5A93~imWLJPwLpI41)!Ol{Y+r8*diQGkH7#K-$&* z7W=#@ot+f3p!by8bF!uE-viJ<8J$~e1|#BwUJ+w%D`E42jUekf z=f0CuCIXx-G@Y7ny*x?L(8(DPl@y1El3i-V@-epL zqA(5}To6*ccH4P6cin8Im9&DbPqzJ#SI>OybbWLhKfzY*bKK317nB+xB`7xQD*JqU ziPb*qri-L@`9XiNdojT?!mHypi+-BCXsx(uK~>Up`|nnR9u9_hMqi#8)4`wRQ_eFU zb8#rm8okEl%9>Uc!I0+QCZNx%l1fa;Q)$0>i_gt0nrS7iSAtZK@N|7 z#gqBR(_NEK`MDnz*5C{vaejNj+6@U`E!_nN!!drhwV9znlkh9+l;buyn6=vahZrMK zOeXQ}l-cY{NzQHe#>g!zK^Xe66LB)VHP8fGN$vRTYl?Z=KKgy3<&IDbX3DohXgwcO zTWC_CqF{uhNhoL6pmpm^BO`GGn6v2$yFQ*?hCN|usTD+;DzH+nSyC<_mLe<*(?Yu5 z@^x3f`M02OV_ATRLxmsEFbx3b@z6DNQd`I|Dao@S%vakh*VE10fr*)^;j)yMl1C;y z?~j4}Dd|`U_lJ}&f%rT{Pc@OtQ&(G9#xVspk=r1tKACMYre2@<+En!CtUtmEY?S)afxq2N z2AB1dht^o`+v!l1Tx;l?dHq0oW}q_}QhylwV+VSQK-v zKsY(Nhhth#GxN;1V@fZHqwhEDPD6pbcOXT4%t2E3T;6pz3Zi}6VOMy#-WiMgAfac# z{PL!KYxFm}ees*)oUBO2Nb1$I-ka$Zu}uXUVN}|?FxFL55x=C5+hx%dBtT@Q$2PM6 z-rVa|D05M0OTbZ$(?OO|)~>;0#*b6Pa<>q2o*zZE5};{Ti*E1nnV#JoF6))oqsl%T zj!&*Ecu1q1aAGUWeH|3ZdGf(>p}X7WV-eeDrjny_Eyy+6hIg&=buO%}_se$U)T6sX zvUb#dI59^G@q>k4jRz&c!d0*a$G*XN+=C=a@T)HGW^AJeELTKXR+Ebre-ORUzAeg4c8N)^!c z(&J!&hLaAndOw>AB3MYE*eZQcSYc{FY&kj<6E!+bf^i7rt=~(FDABl$LhWD2{`%W% zn6Zvx3H(Bdct6nrR%70IRYWtoYVRb!?i@!{1iJ9rT#wB$I3Mio=xisqTiq8p)4uSK zi>|ALBHGKDtB=2JoJY51-8@z3brlqFl6eMeBP#(^aVJ^g0rm_p3`y4szT##b!@_rb zS-u-{a}N9WkEX5f)wVwbHaNo~XudUCk-dD9wfWup7j?Z*IgccBv2^0%>%Ci9R*klc z_oQ#f-YA_I?6G>*8QYjaRY1^*>mHA&MU-IROqW~5mr+a_D^I8>xGMa_S3F$F(W5H? z%}uQ5os|_5z8&p~%fUt+foa2Fb?cCeCQh7oqlsWc4vt4of8_dVtslraNyymd*URc( zjdLq*T+BHTIh^~&HiKuxTNLdxc6#OWu8=3&Gc(9+0`jdJYv=~T*fzQ_ZaP%Ks~3$p zK)rPtv=%(MpuX7X4e2VOxV-Jtl_BlRfiJr#YK+dQMQg zbirGfL#O9 zUgV2VU76DoZj(*BN*0y6f}dIvc5^KzT}iugIjR9tKUAAZV25$R(yjODI3x;PAb2#Z zb=|t}ZylUu%ev}?i%1h@q6-iVl(Fj`ceGpkx=;R;JrpSlKTFP|W77T1$&@n%{|)%A zW$GqjHSK{|U!mi!NC;!#^*b-Oz2<7w3!X|`p?FuFVrHNGEF%CF@d63?8rLpjvwy8- z{8)n!4#ABfMx# zBN!uro}kHmgC_#to|9pHPlPV+UhR(5vR`MAa(AzOmp1-zU5-n0bF74~e??Ayr47}7 z%Zyo|`|Fhj7okZ!|8d~~1J7^ag;flp_D-s6>E)+@LTILR+$kG6sn%JnKfekPi>4`m zsoMuwTWB4Dw~bHmuuhVn)J4vcFeeAizsXD-YWR$yjxq?md{nuj$rt#;$zEDvSDb`b zG3?uN>!Caa$iIp4$uGY3G@vqOwZ>^9iS&d?1cjdn+h+?t^p1LuJY_A|b4KiD0$D2xY zO@th$c5k@|6GqpNEjTS9!CLV1pN2YA!7E4UEF!Uzsa10KVZnkvP}j-leTkkZb6Wb{ z>-J`rQ~g$}QIUH%(d71YOLQJEQY;Fij&830@^3>%`%^pqJP&2BZ%SswIv*6I{q%u*esAdgrE>BFbQ0Jm%F69_?RIZxS_YGI{D zJ(MSvU0Tgy+h)vQCnh((V+5{@Q$1?sk8L^mDzLU<1+7$LU6UaE`rF;~$mLNCr5cxq z9R+Rpw@h{x7Ga{M;z3 zSh1Me-?RmVsU+d|AORu+m!`q*TwL!1gx-l@@lDc^zcV`FDz{NXoU&r=^rwTAq5(CEeh+ro8mpIk>L`LCoEABO z>zvKlYv7j10ChEFSZ3mEUkH8J#{JU-RVVYPqpx27#a#G>AV!&Q&{VHXg?a_4-K$JN z43OhTCUdAyYyD{kZhh)GlQ7K=0#AQ>OxiP8c>opDV<-MU{wjov%ZV@du(D5KP7YbAF_E+d5 zpT^H{o=g~kD{&k5e~ZWmPcmz@E{6qx+OG$MASME3Nn-OdAKA70B5l4iy?<;H{WjY1 z-p~ewoo<1gs*q7WQER8stWVGBqlp;tpZm1l*Ber;4-CG}d!j5`zkmp?WDr$+8r?%C z`cSiD@q<{Asu{+8%1xBdO2%1-M%ZDLYwY5{(M>z9JQgde2OQm7bA$)THeH;1qiDyS zp5+T7_KcTST_?v>Cp%Rj$Au{Us1d}0Ib!f$2{)-+d5{|qOSsne*#L3KOuo&zkNoDP zp~n23gkS!iPvjg^1Qcs2_Y5J}5n*!&XUH8an5p{}`lWnj&IciF8-kOB;jhkhItJrf zc4WH2@3mxJ!_^E+oHbnx(o3;v`o2;NWnb2XxvXPlx~Ixar+fwK-UC~G=~4m!v{lxw zQ!e=jY?ZsF9Mmv6y8KOhbCppt^{+mdmG&%pc6`1PeD7tBUj_=F%GfS~iMLJ%2L1CV6|x(N z=_HTXM-QTq+fbCI@hq_oXK-v9ZF*#T&LHM#TgK-6g}65{^}|1pnPBr|#no+F7xU@c zS6j;dYr}h6MjyLX-!ycu6nVYVp1fMp2!6oNV&K}gw~`foVH$8K2P!HBJWNh}3~JY} zcF+)>%tr*fvqF$F#Y}Vv!)_SgQsA0DfbX=#N&2R&^yy=uU36Yz+SWfFy$;+*$FM+q z7^8?fvGgC>rcb|GTqH+z#b5!&4SqJyhs23f%8AD1^&trRsJbEuXz5;?9M~AiCoJrO z2)~gzi(iGb|7sJfY_6)4qpTW)KhhAIVK@3&hKXEU%sVUxw2hmeBtt(6^Rr&U?XVX; zTyRe0%be+m#vscR~hK#IC>t2dax&(11!pdM}kDwOFgal99Z z5V_umMKO7tGCBQ=8HXeQ;z31h9?lwwnEkKHGZyNn)NskP`E#0vM26a$1w~)4Ean=U zsAVK`Kut?5z`!f#h%(Kk^f;mM=JgHoSRZ2x8j9-E^Vy-hRX3K)ZxcP1NR)q1&nLtD+3eb#J2Xi!9!F^! z;?2iZ*FSl-%?xp)<|v(`p`URR@x5*KAb8P8Bgv4i4%0=tP+Q~HwTog09|wygvz&E8 za%~3z+=d`GTp*{r-DhT!7qbVf#wDunipVdJ?(6xhV12=clQ~K(u;4m=C9m|Efor6a z3*{gSYu%Jzp^a?lJoOjnL0Pcy2?#1Oav{Jl-k~Q>BzniB4}Nfemgwfji|Qm<(JOoL z&M-rKxPl$T`LUGfYie}(Vf$*2x3;6GpsH8)=DUOS zx2n?oGo@iUu@;t`Uh?rv>2ZwxQ-4O_!8f|+M;j{QGGpufP?92K9kwI=FsgcRBl*|Hg#LZW`lZK_9&I(rem@vWz` zi#{td+gh@Q_u8(|`r8fN!2zV&0{Ry>T_R5v2xepQy5G82+G|lLJz}EipExKSzyZ=F z`}CvQ$H-agUAkev#GmpM`oizC!Mb6vD?uPS&voP!Q@vk0%`Fb>5Yuh&aN&0Se!W|7g{{Ury zVyqz+Qq?W?}62TSwD2DW1yo)d_`gia7H4O&MnM$iT z&gVh@44&+eGa0RRtHpf#C3BJPw9rUePy=pFYxdUS3LIk%7W~*%kf1iVI4-nLoF-na zC}@DdQWF_BbJaq3O~cVe!SlkdfktUx_?1#^f;%t+ib&oj#ac z79NB#p}7}zTKiX(dvsa@{{C6Fv)v#+jN2ngzJZu~u;v{^Vf#^nruwIfMCldf($7BZ}Lhu0JaQsjB z@qif18pi)n2{JT>`yWN-6(LTRf;BV`Rw8{pXYJ|&k_WT>duecg)`S~a>0%slaR)MTx`>NvDqEM)b^h?)np&zK{dy9(EizvPkI{w&Mf_D zy~i3K(t@SnebQVEQgn{mfwBCFB|*l3`{eN1zm}A%V14mY z-fNF7lFL~MVfiltrV%i zpg5b4WF^7e(o?x9rnHlYml(;EESXFC7PqLz!<<8kdNEy<8pf;Yrp`ujGNkV3H(sL3 zaDtMRpi~;kf|Wo|4FJZYujlw*8R2j3)?mc@&rhPCE94+ev(2${wCgh5ICAQXsPjeU zu~+p32w>lmn0PbZq=Y<{{?*49x;Xz@tTG4T&d`!qbRe(JOKKvANg z>U5bH&Ry_n==dlRUo@Oax!mOn#Ai7}AvQSm(35x&1=kOAZ#*0jSJtUvNY1%j@{VC# z+9R^MGDZaqI4W}{-Tg=<+NCDzE-NNoE)N@2O4@v>n$*^L(xXFPX!k(Ldo4sCvkzn=etavbh(esl zUU=>4qtAfV@C#9TYBi=SS&mp_xhZ)2G9DM?DREd0T$mQ`!FD|kt4DGTVZ#o9MquVe zi%?vu1~+nQrC11T?sa*8zep*DigR}L>3zOG(zy;y?T&g$-NxSaPQs= zXfWJP7Stq?+FfokS(v7l0OFmE+@&IuXiSNN|Y zc+Jxv`m?K$Ggj6;6<(|_&VNQV_}do={GP2jb#Q(4rgw-Sqm^1cSMJ6Y_~M!i%vI-c zl{O3>O-Q9`+L8oa{-u~8ud#UcU(OsTD*C6t?>vI6ka9Iimb?wS{z+UTD0gbj^g(je zL17%55ZP3N5&_&xZD;fAb=OjBrPfwGNO3rxC)LO;aU?NAEQPy!`XHkT4Cba^HJ}S);tpeG?i)f z^+D*1Cr38B38qeWn|PS>DA9@jJCZeyxZ1~Uv3}8Na(ZX*lRIS44S3*t#TuS7jr_Y# zPaoob&_Qm%wrq&kdzM!!d&~KF@vrb&5H?4!X)&>taDk2MFcY06W^BWzfNvo$?P8~g zUN=<;|FLw9*tOLi0iFfqF5%hwxBtU9PX2n7%AoS9(~$Oj9QA@ezi9U>%O~S)iDFSl z#FKn0q|FO2lO$zMtXX0)BaxTk83=x6Mz=8YN+cz zb^4y~-t%j30~kz3bGq0WzR3H6U{_Qtq2^NWTKMHzo7A2e1$ZXeuAYW{B!wLcy-`mV zMGyNWq&q(G_Kt^QO|zA>E=Dc7-PR@*^6iaoO|t}iT&N4G?3qxoe}N49RUGxy8*Z1_ z@dBxS`KP!q7m^4wlb6KPh|_A=uo^n9uI$7pe! z4@#hDE9)T{hKXN=4VQR898hU{T{y?t*1=}F&Y&Jkh8e=bqGHcJTUO3WkS{ozd-Vbr zq~FEFDb3FD2wHL%`{12E=5S%cCnSUQ_lJ6~1Q_CdqtqAfHTBQ4Rs{L-Nb&P4dj5G! z*;4p;WgS!VM3pUwT1mFr?$=|DtCuWeUi@8f6i^zVBNyiQ_b#hHss6=W-JQ;%c0wgJ z;{7Hlt{)Xy!(Y|iBW@gBwb=0B0>A25Q3ewxEZn_|p+|;bvu;|MT-{KYR>x(a&V@#G zK=?u5Vkn^8JQEWR4X2mk0aG%6i8}(iECZ?hsxC^}2clDu+g(5;G*hUWtH5tJQ}QXp zUJ>;JI+W2(N`iDdrgnu7^6q;=MAN;H%Z(3gt&8L=vDI?G+zV=*v|C>cqF-eZ{+h#A zhhF*;X%CMgeplBw@3ZdojKFKz6nirFa-dTtO7z!k6DbI|IaGg27?l+P`7@R6QtIcy`;o@Ih7WDvf>1K1jGbRbl{^KX$Vl&tuv}~cMF90UtvPo zGh@}j_~5np$+&v9n@{-)^5|0@w0)=4AD-}DgS=?@@xn@ynq2t150*1vg2?|-(g&!G zF!Y6Ok2}1w5hlpzE5vpEt*2kRbN&$s)x96F3_Q-0kC6fFx?>)t7rAXzL>t|StFT=0`TW*=Hm z&>7R}Cb<^t{8*ED$dH-MT+5H${C&`j>l6RwioDPl_C(7$1u{oQ2`ydG97;VavqzaS zy6o3!K=-qWR~0P?^$QvBMu{1gy5>UsU28L1`&V)$zjEhv)4Qae9M2z z66j8PPg7DL84xkpMFQdTTV=hwc{th25|t!)fkgNNqAb2v<_Kc%uZWk{>(3<^AXh1k zXaSVil$>ktHAL3mpE*K@bFlV}>-}AU2?1g$!?X;&E zn8~5Eb9MCeN#dWD03&{@afgNqh9_0X<%`FT(3 zBtg>fR$}Eu$pKpK(WO)Ep1|G8ZzS=P01(Vz-aNWcHxdl{D<)!~F07umM}w#nL$zB= zLxh|yUj+(HtSHe4nNTz7OSC3_VBh0}@|DSmXe1$_6}pmKpLUJNxe9=@T&%~91(wB^ zCHHd9h*ezl7=pZ}vDl;cF%BF=f$R+TYpuF16;5!yr_7^t58{X({Q+`Fj4|-hR>7YB z2$D+t6ttN$*po>o{gu-n(%`q&5v*{S6ieuaOiQeNW4>h2mcFy0KwyfB6kOP1!1d#^ zio*@%2zgz+hU(0czTe!4olzH2mUaiU1F{V#%bf%~GNHe3i~cfx$w=M{v-LZ-d+nz< zHi@Ax5?}x7>h2q8JE|Ul7!N|EnzQCIP!Pn?jV&gY<6bT{@W);RJTtp|h*-mbLyT43 zCn{nl*Yi9(K6-OOkB?y>dKreL+$cl-KayGjLo7#Fs1ucj9`yq86b*Lvz5P_H#x;x08t5O(R=;({Ome{NG{XvA=`T0P4-GevHc0d&D0CXVc~A~ zP)CKO5KIOtgU75r9=tS1k?ctVKAQ~x`40cZRCwv*l!ZFyKi6_7Jb!jYu`Dz@iuS$w zntWvbyE_|U#wE0QXUi^u{?C7$z~uoQf2d?N(zifct-sW%*EfLXpUvg6|L zRt{6GbF5+V+A<@O)xG!GA5Rv-sb1i*yFvtVFxrWp5YHkNEeWo0B`87-aNxMw&r>M) z>dpf8O@rL1ZC;A@ed2}K$`A~*qtB@epR_^pfi%6Im|x;a%V;a+Hbty3B@?sz{%aXAyQ z`P<@`)+!=xS0WCRuF@TH6bavgQQ{dxcn6kX_jD%T<2$Z71(5lP4k$)v(b>C8i06~E z&+rMCfEkc;e*}NV5WRV@qWt*0yDv7?o~aX<(n7hAC%;PQY3rWHWv_y<(4!ZO)KS)U zclqdsh!oF`V1>a|#1uk5;B%6pmFN+CYD@_Hl;!hhU0UMVX&OB66~R*00UNgiowg}Y zSNZcz6>mk&$n*u4OGpXeoa!ildC+okG<`u-=Y|1=WuagY!*tg53eCgMEFw#7kyvOr zx3T4r-3h()#SI$Fjo&W6Q1qPBw{m#>cRBkG-|HzfBIvn+=}EVXw+bRj zS%5Iv#2?gktZ!>pFF|?h6GVFlVMwUAviHXKd5^3gZ+)$`sx8=){yR!3)USrkei>Qz zG#s<1;rU6$-Ez6R^7Sn>W*y=lok1e5oX%-MvYE4hqf7X&+aKCmj&4^+F!iMzX1~kB zSTL05y+$B0?9l;*Ny<|N=aq=ah47Cd9Q_3fGUvUQ()_q_Vy}$_Jj+Uyv|zZ-J{=^%ien|UNia;j6Zz~ zGp}w-=6`<3Q5$yi< zL7y;Xu?ga80A&>10TO(^sCU0iIMlODQ&u1c*qhrBHc3*mXIi z`Knt~$q~^Hl_M^V{lRxB#7`jAaG8wZR3cZuA}R+qR`&_S#}q-fAgL)PGJ<3h8iAej zop1fZQJ>0OIiHb|uk!GCAb%%SKEm*?>;&o31qN#qd|(fF*tA!}{mb%0>xN;oa>4Q! zvj3|5jQU`xm9FLsu!EA$ZJlhfe&{yw5vJ59awn}hj)9k~M9*5D+UIPiOom|kq0VLG zYk&|Z`cwY0n5o4WlM1isx2(mngF7e4cg=C05ikjzY)7KO!}S&g)OfUz4b8d=|AifK zD#KPsW3@=mxue&RghNF+?!3-{bIQ9&J0^ibeo|e zs-7=$EWVSnE2d2o6le$GFgN)J{IITjzb}avT>eY3-f`u=S!3OJ-yFEYSgx`~8|4~W zyee10W4m?qPN;ruNa_&TDRdZ@!AaN{&YCi7G5GbifCSMSLClyp2v$F%h)L6-C%)YV zU!Fm9uHGC?=o~}ooK#B4OIJ-7_?E8%-7`N`BieC3LTW9*+V^9&g&R)zc9X&Fl&T%{ z(Y5h^V{xSBtTzhe-QVBRL&pgc10no48N&R>w!RLsv+q%i?>|=mRpY`E4Wq^XMaX>i z#sF@3ZMRt`e_T^r0N9WYu0MP_riwTfI1V<1j0sUsU3t%=inghK3Y@soqGtenfXWwN zkO4++SdTS&bfc&COegnP$!Ku7!t%zN)2(6gGFY1u2iWO2N@)OH^&7s4Cs?os<2oa0 z+BUeiZ|@blKHR<2cPw7LhDv%%2s-ZQQpEBS|6t@Ubqup<^dr<{E&=*lw4?bhP`wUz zG5o-787Pb&*#zgoUJ|}v4s0&N;|T8}Ys3AUqNK-~(~%#FQMpEu58iz~s=;Y#T+HNz z6u&^+VjWpC0?kTU4mes%Z90>^H(}6#h~K9g)Vb^Iyb^2O^FDP9nHHamuk#V zVHGnr^Gqk8(uMXyu{&zWa7T*9YgDN;Pri=Q!CtXlO2rWCRwn#Bh!*v?*(RDVCMQJ; zP{kp7-lW;6KVZ4%qn(6z^9FJE`myn8Ij*KiPD-L{W(4W+TRL_Po6kZV69X;0Fr8S& z4?Z%}*JOEIm%}dj^W!L9swEoydVPD~rxpyE>wpsoMQJ$?gNe`4fxAO`n)y0D)vWdBHmmfEmg_j5gYNC9GTeCDC=}Eve<@ z_>7K*Et&Mv}R~(L4iBALqu(#(EtS1C^neP+_4b8v?+h6$4${A zxIr}OoRnz=ea{~z@JDSvM+Y(e!Yh@+US(}vB@A1olaUa~bOLoA4GueMAQh;KR} zU01wVSP!Dvw^Bs?oMKKWEevCq$K5|n?1gF@UP>t(obVP zbhPwzFrHBaKDZJ3bKON3@+2{QTA#)HI)RN6x4-{#KW@(E*y_lZ>x!JnVzNz?8^e5h zWN@AGTBJ}=ndzro3i#66!3x9fLiSBl$W>Jpw1)|-)cj732<-B#uI_RrVJ2o(bVERm zeU}hMsI18j5jY9o9NgML1Tml05uxEh*D$`;*9i2#7i#Qm!o~=&P3!0p=pJO3%yF2t z5qhB+ny+0jbC-+BU%POrXzk=1XIh3Yz zX;LGuh~N*jXp-n?r0#GcKLG!PZFcKSJM0*U3G8m;qoK(a*UURSv-%kQ}G znKi_JI?zty{%yQ@iYX)P?sM2VEJ9%5_lgaXmq@*nd<;@%%YxjHk@1pHe2I%DVaBd?KM_yuuD zS2bme?r09h<;!GT6OEZ&5wrNf_nrR6J+I$Tu^WE2^j^9AN8hxgY99&mYw;9hh=phq z!7Dn|I_p_Szy@){ruQR#@@*%4f+pe)eLj z0q)G!{a3biLs@5xJ(&5ued-4vf6qK?P}HW3aX;|<&e>~G2XMQqpgh^;HWp(;8w_e)R!z1*Qn zYw#}AJ00@3_Pdd5;1CO~fDbaWKvyGg$+rM%_n`(jiKhiv7un;MzlTwCHKgiVOa0CA< z0L+NGD%l0v!$aArG#FgyA@{Jg+7c_AEbrw$5WI0r8eAcrZw?aGxL}2+zJJMCC?8%y zFLW(TO{2G?Ba=fO+>u=L4GmKHQP7v9wFQ9SUA-?$*7mZUG70-dOvs%}4fW79L((H! zh_m4VtlLzP_)AklTfxhX-1>fJ639k9I5U`wQTc*T(yFF)^}h3;L!u+o4{Nkq3euF^ z(MrL&C!&!@$liTW->ybK4uTBWp0@{v&}nNr(YWX8gHNc}-kx&qeZ~c09AYb$Dwyii z{wS69Fgm$yN+~(%2VQr8=p4S_GL7bqgNf0rTQXDS;s9&W(V#edbf)epIioi=?wIq4 zs1zEbLvm{XJV)Qg&sdJK*g<$r(<6U(9~G*@!?6jDJv^sx!Ru6e&)W^ScyfJ2C^g!s zReg_aoSp4?LI>o~vb8_q)*4n+^hysrW~&lfxKFzFpK1D`m^$$mMYWmH$FcQZV__Ui zztMN6dJ{<%Ylxvtp09!{D%v9lys>4gwK3+kclqPqj>E4s3Ia6fKem&ipWDQmO_gI# zWl#4RaJk`!=-Zj%D=`B>x9*dqQ|j=#v!!EpjRq|bcM{lEew_rfoifig`97QP)|e>A zTx?I+<@Q{qxvO@cr3RzT@n)4uXjn?JSJ!3XO=U5w9?r_5$2MDx&D5*kUwM-nN6zOr zjXmS6qripu9o5*UjP|6rlz{mY?y;+;Gl1zekBSI7sUlE~lfipnGR{d-dY1m>B8+AV zZeP=z>1DV~#Br($jX0WEjw%?d$oTwV{(G3JMs{#_(Bztl3gIT{(cpo-A|oz91&NkzDrS)+)C!=^cLIt2$8M)f^3T4!^kG`c3a@ujHYpsIx#R z`&g0o2e*fC?THlhQMK14N${p+4wd@;<9R^4jMP0*PVjw|=!(`O0VDuymT?KyYp}xlgI|CIOq-=V98~$)JN(S1dAkThLhutygAW2Y5?Jw3(m<1&a^R_DT zK(By~uihdDrei76_N59Q%z1t&RLOEliF)b?8(%4-3zSjuI^JjI%0MUG6hz?nxCjW* zhocO^lcFfjqs*HYjIl*syYIB^pZpAD!T454q3WtWqP^Ao|?$)=y);b{#rIEAA%K8duNn+tKfcM&pMD`$grVP8cx5 z8dsYdzoJO*_2dnkhVF<+wWk5aF2S3Olu=-8jEmb>UKPK14p%VjWJugY_g*LS8SP$b zpH(c&W6U5vg@@T)!lA^DHbl?|7dFt=%%yTolAV}(pbAXHy5&;o{(0llG@9#wMjG5X zI?&Ctj~mSf@JNkO!*#o}?^sRMgvys)d*lwIF1}xU_5>nDX={jc**@ftL?yx@_iHR+ z3)7q)k}S-6s!nan!N9WbF@Zg&&}jRj+NER!oX3I7oQ)8PT~XUFk1!sBYXY#rQh_&1 zW_!LK+#kz|KKea>8j&7rQP%$PI_zo282b7f5@#M4>4Ca|4yo4B#w@FJVrGZ@IO1(w z_KQ4@Y3x5C?>2GFk6T6$9~UI1(Z9tZ)rS-2p3Pr>)$D&HMBVc(a#Qcbb<#O>MGIm3 zfKfxIb&~wu&_U#2o6_+uJ)#-;9t-Gml0ma8-}<||6ePo|QEaJ6GK6g{;$h2?{!gJ& z0Gdpba@*y;T&8GZaXy{<_Bj$c0@oS#6jjb3qwt?c#811n|xecwwrWBTDLku*hAIA zH0>Ui7$xF`=JxMN42fY+;Od|If%B6Q*|~uFBZ^8F#lS=^bhI~4UYS!+Ijs!Y9%zNO&Xry_*4}p4gq#SQ*ugcf|o804>eQdsKf+o>t`)Un& z{L2d(dVJ3KMan#>St`1LX}^!$M4;!oYb33$*d%35>el=NZD$%YF` zc}wCICi!a0WUKxAXf!YTuvMp8Aemn>&jQz~X*eU8o&vb6^NGG%1XqT2g~-2bBSR2e zFq$_yJ^z-~hjTmwGZ zD&Q!lXb`+rHh9|Y(&6S+#!#1&+ib%@Jg28@D4sDVnR$N%Sw7gi_@It=ui!1WD9caw zlsq}kHS0^uA8zY0zAUm)GK18`)8s(EQAYH>3ForNq+x+2Xj-wBg zPlZ%IRL=-D`b}Qws$nCDjk}AQLvop1Lz}AUlxXESFHJujUA0(k7Q}<^AJ45s{amLr z)&2|@PcKQCSjI5rliacd}`iHC`5zDsVqDUOqKc>B}T+ zWrzH;zW*)ZOY~aWlXR`(C7TL*4)s7}X^>wXn|^~KsDpi`KpXZ8%F00k1oMED5Qtou z^~dM#IqITtg7BwUl#{}X?+%X}TQcBNugyVrk+DdG}=mAHy z8_qef4%uu9=JXpLwyA6zqfvslIQoX)x0DYvyjTdv3#h)jj|9U_s1QmLC=>J=CwElQj*iNWVEyQs|5pGE!F>{>OZ5J_}({OSfxr8 zm5ziai1gkG(u;tAiXswe0*dtB2Bb@sj!2UxA|fbFfl#DNN4j*RLqbhLl6i*j@Bf^$ z&YHC#FJP@qvS;tRT=(@!>CDFDewNbb{V*Ut9WR*fM5aUG@Pev7;k+w zJF9qJ`A#3W8gc^{r#+IpQFTjUl-sx=wE$q=aq!;Y7H3LL?m=B^VxQn0pQ2;A)##>E zv^%(X=vLd`e5`Brd!rFzIw0_SUAi{&o785g48!{NQSmR7#iD zM>wOZfzsf06ID$X>G`7QZqxX3+Jd#Ngauwr7bn`uClo;&57S7sZ~B>p(WjHnT%F8# z9S}wYCWelP`LmUdRJlol2}vZe~EOgp7gAWAOY)Fb&&^e~ETV>4`not<*+i`k+lvV)}6 zmS%lpk$TnEa2UySu-=}9zeaOP{pfZI@SfbkW?$}rYQ!UIMwALN@#H1>@Q|U+A!d-* zNsUxEU}~hG_28Xb6-`qh1${fFoy7*c3Jbt}iDdSJ%r7KbYP?;WxbmkEXQz+}(>x`GVh>EIg&te?;_oSw-d01_Boh)NNn%o(D$;1;z&(TD|#u`&5JrtQ9)$jwV$L~lQ zO==?MhXx0Il46p(!#HEM8h-~?qu1556fK4z?Gk6FHPPYmXybmYKwsD~z1N!Bg^+vg z^!dxZyT+4zKeTQ*_KtEyEY1}uTb1ZDey`+T4U%~^MlU{>7#020l6YTRnlwu1`GT_s z1iWgwbcj=&ju@Wh5Q1E*uJ$?TRMN=ceyRkU*sIB0dE*y|H^Yi00vxK_YUO-*t=$IyLwbv{I=vxF#=w3cU5NXx!jVK`)oy4lN7V0Q%Je?} zuhQ+|a+>nCIu0lBrr0)MXnVf57Zpxn!vO^3nP!-j*&#d!pJjPobrNX*0w=Dn)c9XR zsY4AE&lx9zb!bK8g!~N3R$+^hrpN&M{_n@P`z+%{4@O8BR#g0!Q)Rz=Bpwv8@2#-l z03}Dm;GDBZH90IU88D}`Nb}>ZKOqRmIfom#@H!J$>)BZNKAM+jaDcrviSz+&06$dQ z2;;57GRzh&IyAS|X579+Je1M;QzH^M3kJ4>s?{&3`CYx& zn_hT2OJEU@oROx$Czjd^J5Ler67SLR-AqOHzD`LQ{RjI>x!{KF+PUU*H4t3*dnRTu zjXykm4@j{|Yf_paQLUW+%CFG`xvz8T#SZdbv!i^?y0j*{Ws<4zHHuinflSsGT}?Eu z%cG@?p#RQEpLUZ_-XI41pe$s2y8Mic@eV?ia^zWAZeg58Pgws=%2;_4D}g6K z#JVLX0d7Oe3FM58w%meRVf>JRli_=oR~$>LWf@-W*`+v-jw*wAaQx;VW+oN#}iDjyq=b0qG1rX3XSo z1sFp}#}8q&uW8yE{KvY!13K=RJ!atkx$$W7hg<&`0C_UAS$Htwgvi_x zE|X|u`l-~jT%HH$+F(T-@Os$a6?yD4&iJ`OFV*>2`F5<9vaC{T*%Vj*o*ktmUUF4H zVx?V5<&o){u@lSi=I%_fli8%INd6*{@?(`RwXz%M4HbT4tXzC8aaF*-_6;WE za@4gx*%NF>h?4`Ji9zB{#82^ zhRf%EwYm8RU+`R!_%Nz@-m*ygXO#Hv%!481nG55|KlX}OMv)7JBnH^C zH9$>r&4tjW#r$QB*^(8&{#g=miT-s@dN;#CW?-}j)HO)%D5kcfUjisr4i0Io-=$C@ zg9H5n+8=3Q;V`efsAhieucSOAVAu5Y=t{$$spPdNzfKAiX4_1ZX;xuEzU5IoXUn&R z{9W9y^+}JyP;h`682Z@r{^lb3u%RV=46`<q!>ZcBJ|4-~Ax)j(^PhK6ubyb&v+vDhKS_-INO8$`?lRLgC_n zu6Kb)PGjh>?#!8aanQWVJ@kE)M;dz}wva=Jhfv@C#CbZ!ew4-|+#3kT+RVxOSyZci z1}ToZqlKhD@D80pgRaKrS0lV=a1IK7%en4dYJ!NmrV~(>C0D+FMECmDgk}7_lFQ1Q z?f6V1@bXGhUVc&{>)K3*{sp8d<6Z?McrWu&Idafx2v8{bI=<)*1PnuPrbQXD0Q^=07)% z!dupzZgn6|fO1p&V%xGr54Xc`pAjSp7>TZeT^^BV<0Z3($cf}jl}ZZDWJ9J{u_ItZ zmF-u#1CtE68%H!QL5_-%ff$VWQCu=eqk7Be&T^JXZ+;)34gSL0;&o#0dmSuv<^N9? z_KJ9s{-dO^|DsX3tI5m^{^j9*OTam{Z)IS0f4*-a9vUaL5y?!UCZ(;QB__NT8%EK$ zzY?Xqd3ES`jhR*Qt66EleLl{YRvCYa$)3h)X8e+&RrwE2ck-G@sK%K5^bxsnt@xX0 zNP+1+^V6@>H1yE}IkMJmufl^A_pb$AZZ`VK3&(l3)zPRMzE#1L$Y{t)G|qQaUmzgZ zs0E+?@Ol$WM%VQ$a+OQ?{#vUzT9L`SfhC8TxH|(;ajsXV1*AV)5+4Kvay?RJk@Q3B z13A&d_O7>y4PFUay{0JV7jeTeM?o~4ltCM)Zq|s);6L8G{Ipluk=?HeE|`4sa-UbT zZE6-Ko1Yh_bonyY+O3QRuRi|%EKK;AyLQej8a{Mb1nw=CmB6WT<(8HG_S_jnm;;F_ zm7Ld$eR^nDXhJXn0&~Bo!5lRInCXF zC*5I=!EV}PE}>{QL_Z>c%SW4K;A>3P z=hr@~A8stP-8;k`vHmDC(-D4tRViT2&3N1olyjZ8)M&a$izP3l`g2b$LXSp=A+M(z z_1bCr6WO5Tc(@}jUhW=k*wVwh#6Rs;mCXU1(bW$WVyFkySN3vT3l>H)2filvCwoc3 zvjky<3mP^LHZfw#N%am%-7vp{ro+Lc6T84Iz4$6xql_rr;cH-2FPIzHDsq2EGM#$9 zzzg7qCSgHAzis!zFQ++9G_h_3an!VukXyZ2>5{bL-!|a0s?~S|-xKO_zhf*C;C$0G zG|4Tnz;h^%1tIR-y)>4yW*8CbJXc&UU9@z=Z|L>g6W)O6!Ve92Lkgt$5xnlkYEaxm zs%<5|Hh1`3198Oo^iN5cgoY~A&uzj^Jo&i+TfH2`#)o%p!IE<;SbsebNn8PhSJe#s z?5jam9$#|xwJvOumb|E1N$3G&T+{p+9&z zsvgk25NfUx??aRRJ~y}W41DD zq~nL018Sc-Ul+0+DnL3>TF@vUDLq1ZukIlF(c$0@XnND2&8(_2bLashaKq}>ps@1j zc3xL4JshVi`>M73hErGmYtQLgn%Vcdp9RAJjuwlvAhQ*WT;IQL>A%*x(bb4*kIKg+ zNqAP*->u3qs3Y;KSO18$4ppt>@egFgIaIDb+GC`|n}4yGLbG&iD=N)|Fv>3{FtDel?A3rJDv{C-8djqp8=U`2!Sm0 z8a(Iyg6hc&J12O8{v?vlCf`JTs;h#;08E*; zZSRz+M;@3mSy4Y(+|&wRilSYxb=BPQXF*H&Pf9tc;vp@mV0of=)&mCe_#1jjeTLE# zJkl)8vCEs8?V#oA7xJJ_wyrl5%|-9O0A6*sibSCi)#_S*x1*yLU9AgjARu^OehrGt ze#&&YTXRLRS+_wTyXzBO@E2p>1@Lw^6*t&tekT{9z^4i9uydi&c@8$ZXv!9ii4*EDEqj8^7L<*4x5VT?p5H_)x^p zD@_{-2+bLPlE+jvpu}SEf>bz9vD%s1Z(qw0dMy0rn~xT%@Q~T|?y z>htSr6T@}t5WjD1oOQDjqEtdah#`(%W%-lZbMf~!{-|M#-tlJyg-$`Rjc1WN8tS$#veZrtc;FHwfUd*9PT3#^jQ2#$UYF|@+I-s#kuW( z?F^VTrR9=(?X{%8zu}_e>(!r`yRS`h#W_xRFUjpXZsiT4&fLB_4PqVca<|hh0{E~M0S{E<;pCpR+l-y3>Up zz^fh~z1c$LO%m^4_fn+&Q%LlcqS=s3@QT}^8r(;)1D<1A?PrTw(-%1H94+@oHn+6C z)voz(BjbZi9(Zqj(oadClxlKXc|K02at*d}^R|t~SlQp@r1^yf0^%P2G>RC;76lSh zkzxPP2#8`000W?V3-x*zaDLr`-G93182Y6kAc39xXA>9^-FZZW$qX(AnqD^orLpU` zo*gW#LKs(`G>~>nu4kZ?+TBGI4*!K3?dAJ@Ysox+qlhcUvMVj~VF<$#Eq~hSkNg|^ zh4Z<%_!8^|l;6M>+Pmui5ggebO#XxYj(ray;goC^<=jh{1BQFAIaD_(cGtYGX#a=U zU@DH?gp~rDQ;R*VepuSAd>!uBBtAQJ+nJdD<;@O+lBRN+62lwXuXzllwi-C8jS$%EA$=eLoIK`7Br3 z7gK32f71N^#)#wZoPB(qHn0NushsDqKRVq7_+LR{smY_Hf+7=;$l@Nc%?zVyRutUZN&krVQX^N1u3^KUUnO~S-^~<@rda;vE(@6txE>-i4>=&l z;*CI^I&6}#^&#A`)jw%7QyHAbJ#luP#W9oDRU&6_-zt$~QCCtn;S#J)xTG4g-e-qM zcJ9C;@Z&`Z8tE4AO{-h_7JEUVSW0T+7c82s{895G$?+iohX`}PMHTgZjoZ>D>l=C> z{2@ju+qD&}Itfk72uzt<hOG-1Mu4_O)m+?f*J>cB|{EvY_d-n?*QSIQpN4wiGCx zM6$N0oo%>J3F~Z_v0dR+AuxXi>Y-_#oeBfHhc?FTX!oY;cc>`yFp)NvGiTB4H<3}q zNpmtE(PRm%E3~A50O;4yDsnJF7Q!IX-%K`b{|5+MyTvXu4c#4l7ALiO$${z#Fo_+V zSU7wN7)x@cxXaf%nr@++e=i(P5_OQM)jIa?N84V%A`M}YBM+`5ejbWe>=a}czfNwP zg{L>>eYB){$R4C4Hmc`T3D*XO+cES_1H|{m@NyZ0fXFMNiK3foE%e>d z-@aN3D4=wP`Cr?c;4QlO@zgI=?jPPx=T5oGbt_zLlki*7haY|M(@f0`b!*ECKT7HiTKfqC+g|Ed%YeWDL(v$8wT}aDKle^#r1!a}1AJXJ> z1+Lyo?pH}T;DWH^iJE=Ji8hJO@=T|A&+9a=Xsr8MN-n<53qVGp7cOze>^icLS@kc4 z$-gDn9Qsm7?e}=@NDi~Z6bRi&|B={WHvUYe2ay93yu$Umj$p$)HZkI7inuAf!(sja zSPD6~+2WEm;Yd!xP#{-Id9EApi=d_F0zZEV&{$D1hE}{h@|eCXp%!`hv_Y?#+MP}R ztMtJOazrW-<2g}fp9OFD%>vO&(J%q?^9Sp7F{#uo`1#HKC$6~*zP6Jle7lG9ot9iH zwy6E2m=Be-wI-?%Nr#9Q;?pmd3gs5HKRULfVRnS5eRr30ayi-KLPYeUiW%dlf(QR$ z!954sCtxA82MZJV&V+#p=?SO5S+VO%AzcN{<)7K?}E~VC+YiH1=57sBM4|0YWek){s|~|7TpXG-p#{h zBFbCXJD=k>ymjHHQHBgJxS0zuuXlk*eCWhYmnfZHnR49XfAH0TUS`_Unzr}cH#0pN zX;f(||KDwF25);Pc0^VMy}65~_k;sV#R>h@+BN)6I00{`GQFI0BK0|8JO70EYMWmA z*k4OO^I3|6;S+#6dJ30X37^L0RKjN<%KHC)sOwP030r!%t+@shv^26_?D#}6+UuGU zN#1(+s)vmR-btqs%j4sabi4q($SdY4?^VaIsc=4f;V{}1)D^v%+9rUF|4-6?mw3Ji zD8@<#kflHtkt}`m$hbbu2`9H%P{s0pMB2^ydIcV@dl1UFh-8w*nb0xY3=!;Wa9Brl-rlbxx@_+U{vht1s(C5aTik!p=hj|QC4y{SZYO)-Q6GBe z&)naR)5k%+))~oeH=>{pE*W|}->+GfB(#AgInB)pb)!UA3tFrHCGTmJMgi~eYwwqy z)9O&?0IfGdF}S$u9E6}nu&|c`pKkXmXd2&AE`OL!qQ|L={A0?*F1nk3_f$(cP1SQkL@>~D$gU4tbw&{~;kzvOa zELYes85&VM3u+O+_;NSMk?I%x8bW+6D#7eSrn5fPEi>WXyYhuE){xltYyQRDoi|PO0133pMWKa_kCv-py4O);8Ke-miZc;l{hy)36?{=YYG|mFK_=``Ht1NIt?MLc8;eQAq{8OaTwrjmp_7 z54xJmSF_3b5HEdX*>fe`{vzKO%I9uxJa3dDNu&RmhC^o+Apw-<^7`JOAsuDYG1!HW zOt{o|{`HqoLc72~_1hhY53Lok2}{l?1sZ!hj6b}0F@&CtoSgsn;wPo138BFaR<7cPHX1Dt0Jrf_&#AAMV3YzOsUSl3?FXOu zAlP4qE0U=F4>&GqQVsqQr0B}&c$Mk8p5idwjT^Ww-}F(``aD>U>2S409^|))&7;qK zj|BLb*E!fhm*@N<$sx9fkP{~wiH199Aik~Hl5}`b^TMX?K+?f-MAv7PP+$_ip8}!Ogf6_ceK0+p@a!=^mt`^k zyr}y5Er%k?ZEj-og{qRd*WU}>G)TYOspw9NHxKz{8gRNL!rrp5xVKM6APF+!Ir{;+ zB6oet?-eS~ycdMLvvY(8A6xF=>*44H#LE7O(w+4K#xyw>B*CZmaZ|&iZV)1Iajyw| zSl|Zs)MlAP`tHnP9%!KZ^AWb-ek@)FALmPy!m$(L%s@$^6m)sU>7H4De-Sw7Si2|I z@sl?M7~Dtl1BS$Rcp2mvHu?Pb@!=ka-_h%$`9f)N(bwhWb>voHk!EZe+u(j_$%5wDib^st`mL;)d-u zumT}=&ex32SiV`)E82sw-!vz0V2ETmiSSaGbDw+?tF#xd6I2`i?pX1HARoTQzOOG$ z(5x7;K}SE|@b~el+gbhhhO<2QBHT#qlDGKvCOF^T&Pxohc6>5KgW|r_;@!{0dN^f! zFdw+z2R%N;cL=!A?~gqduxTNtRW2$6knLmO;}#n-B@8n(<;E=L9zjm77bRjT@bN}Z za>L4?pRgkFOyL+VVf5_hDQ3O(UOz4?ijJLUtZd+(tl$?kQre;XB~8@Pu(deHQ0P)t zhf>Cyt033AM}(mVL{?(;V0Za3u$8QP?^iC`@gV8_ha<{xJhL>&n29GSZ2k9~bqXdY z`z*OEpQD9V^Lyc`pdzO;@lc=lBbwS0{E8Lp@ju^GV^FMRY&nVkAiSAD=hA%s_ALlHv@smQOG?ZXlr-T$6YOg9gvaJ! z^iS?2S=KmL)<=Ile2=Ty*eu;l|9P#9rn~EIsm$FomIs@}Q6Q!pOs5uW7&c#h<^)yy za{ugz+X zWbf^XO+x!HoDKkv!IYZ{Z?4h5P>ZmxXuwp-qa0jQ#x~s>#g@b#FVp(u4N8@^tyHme zgI5nE8FbjlhsK=7%9d#4-k1>o3jz`70q|TVGL89$cEBOfO+YsE=)F9cT&?Owq$1B= z5*&a^;Mx6csyI=3w~{4?28i`rHGq@_&r9dfi%uEv1*KUO<3O=+m!=-?MGYPCr3}tL z&tqBB>i?=_X0HG4?VZS7>K2&yed44TS2pkS%}qF3$eaZe%@OeNZouZvUSSjUy4Kmf z+DWT)Gb7c`Ns&Y%6RZR7`}-G|BH z5ewwO#Zwtg*!l?Qx9H!F)^XH)0h(7ne848-e2ZeDLJX1?q(CkZeV_g;Sd0B66Sr~c zNd+aZw8sTLe!fV}deEElo`b9n62!2RYm6RIwyYRUCf>(b+=>K0Jy24kQ`))mYOJry zysybWzt{KWLv;4!*Se<6B`r(jIxM>f4SPLVG3LNB4Xo_5?@#mZ;aN6#|&JG&_=N<#h-dv=kB3KCc^dYHt z=$KCV3f}Uu`;+EA^dZ#rI8nfd)}PV7Uwqp=)Y7%ENU^t8HL~FT9*rmnO+Z5bWe5cb zmrW;ET?;gmp=34Ze2W&FgqiI=aRYxJR^riRi6*9q_yu@)=$TTvDy z*N>QX0GmO3Y3Hd6Li?l}(Zx_UQrExWupzu277p`E05rFjv~;d0deZx&cH1p?1B{|&qnh>H5+qpflpsF6WHO$**{I~( zw*v)ZyU>BRKNPTVn%V#7w7BJ9KXBjs<}z7&;dSSkjtAyX1&84D0ePJD&#eo$I~}!S!?g>u~oBIDxT1wu3k45*&%1yx`SBu7E^^vK@Mnb?B9n6B~(2WmIRjrr(8kgS)G46)CEF9w+_$Hzh$R?Jov>h1-f|Hj`>5)H< z;eK4Q<7?Eq!G@ZtDx98F-oD8%1-{cBo7r4$N*)nPi0!_6e9yClKzqIQ+Psb+sCjsp zw^v?dp7?byY^C;ZTiNG}A^3iaI$Cx2-isb-v zB~V^0Os+{=t88kwv?9|9L%-@2K?UCx+_r0SHz(lCjNfGSo87I~tIBhB_!uk0C%_iw z(tIr22oga}`WTQmDKUfd?~l!9{G!f=QwIl_KUbCiJ6o#zPkknS2)BYa|Mu`zwlel+ z`QxIDiUo#W*ZBSMDn}@d#6d3pZ*S>HjA6GR%;o0Ji zBnS`tkMfm2{#M!|UeccAN97L-AjRYBkwTw8WB`!v^#wUj=+a)7D86dQPd6O!`-j_H z7XfL3ukz#??gL0|$aVjJ`RIGc@E;dd;;8hOqXv*?8-$_%cbXI00k4i#{x6ZX#|hke zwvE{9zcPk=MPPi{eC9!T3?;;=ZZtG&;#p!OLaR8VouljNhD)u_CEgc>_+NL?Mt+W) ze@-;GK4(6X7~p}$KJm(7R4UAmc&>`t{!=MrR%)1fu-0E_7e&LV{AfPt(6Dju$M))n zxYramU+f&@5+n756)_h(m)oH^SqP=q14#>+IGuD21N52?wpL?W$O_>aR-*=$&e=6V z8tKedes{iv%H>n7e)RG6`1Mw&$KV>`&ECA%nBl>&20ixWBzOvULmoj$tG;g@omAPf zwo%S=Um2`LUh0iKH{=x?jphuv5>*L$`Uivc&eQs$Si()mH!E6out$s0v z84stU_t+jIdKFA^5Q<3g6Sc50QdA;D8=AMvf;)ly7E@hYh}v|{ZUtUD!^#wcg z=U+lSRK_Lvi*en}`DPtb(0kFeMpJN;)Of(p;_IRi1bsh35jW!>4Gft=)J($H+4dfa zBElq|SXs0^sk_`&dg&s5AVNJUM?AQizX(`)%j{~ z#L;3neGj@@DTJSZv}!ahHRjDlQsllA*ob$ahabh@38l!wv<|(bj}ESD`Ld+ZeqeN9 z>;fr~d||`5MVv^&a4rLGyIv2asohsodl!}=AEe`RABQfW6HR=zGGx+vE{|Xb&H%#D zYEm!EwDo`CA3xBzihNmfJQQpXP=BX8kSn@FATO>Hoj5GLHV`5RJN2~I9S`gC3{c^s zXXecwn`QWJWaarv`z)1p10T))CH(Q5weM;F1T>r1T^rx|FL~5ZUDA()TO`Q;txYty z^4Ah=SiGcyWFr3+2Z=LveTtmNN#Xhn1s`4yJ^c1+#<|XT+jkP0kZf8^ima|W9?=mJ zISTa&#{S6^=V{@Alvatqv(KuXBiruAeqtRRgM9mmv8Z^G>pFY8lb`;K9FW8-OBeq- z1I2)|92$jF%SxxSliksOS+;h6-^u7Ri^LNJet&vU;glz6R@O(ho-d%Z!T71S4c>sg zGiB@g@pq6bfBWcYoFqs@ylF$Z%6F?Gz z?!=RR*|-@+C^o@tReYIH4R1Cj;_8uoAKw;zUq5VzQ|y{#eN6D%n9o%6^IdVBLNR#o z(!>b=j3EE@<*9pDT0FR0-$sI_Sr3yZlje{J%JO+&Nesd-D735aXP3UtA3`n$Oai}E6sIk zz9)lS!Eje$1s;GBSnA6*heIyM^f`d7XTktdaX*FUfBA;ky!~CU;8rUz2AAi&3!0V} z>|>OFO~RJ9UC&)cpju@Y1;uOq1pFlM_v1loLdJQ$4JtpKJOuk3rwZ=)bsrbK{d8A7 z8$DwZ(1wXOC!AM-cuIB|BIrY&@T6*RxAMT9F z8y*>!o8DX_(5oiDkf!^v*PANPAIWT)H4Z}ffM(i12QkW%1hk_6R&QCYVdO4w>B%zf z6X(TYZVh`ynkVmi46vw$?@nVSda3;HyrDD$#kU6|$&6trCBBzNRs zsK_)TnTMq6IBBDReb5qU#!D*GEvayfV^;{yWncX#uCs6IfHOq;pr@ z^F(FxAL9Il%>PQXaSy>k$KkJcT#nM?UaWZCDAtc6VGI%8T7RyN=Q+ufW49^HYuAMt z@aG4Lhqqy zqzjSa&BL|q-OwQTx&qVU&P}KQfaHP#!7W|vI#j+ZHOzT^sao@Z0`Go;b;$3a-Z`yt zYkU3uC_nK^njxE#?d%Ty^Zw8fpSZUu@@LvG^PUGd-IIi)PH`+XH(Qu;-Ia`<}Mcg0WI z_Y8Bt@r)}6hq3(`0#rp+jyh`VL-nv#beH?{|AK zPg1_66@1@4`e^%c@B;@}KNnDe-}6P9U6~_6ABB-Tee%aUyM6?hg|`k&OF-MP;DQxt z+P^348xd(>66!9kd0Cq0n-faYPylG4Slx6Gk8l!I&oW9~>WCI-tGZwPCJ17l`|WMu zy4VX28^e96kzbFDJK-o~yYG!BTzFblY|Q&_4tUoiV@~KSjKzwH0=@#kc{M}|`(GP9 z2RPLPWuX<3ggHw(PZSu}&U}kAOCN*7k>P2lt}F2KYpXgdTSCTNp^$6actrl&F@=u& zu;^c0j<&-6w$u>9!ugS!3Wvk7;VM_yKOlz1Wv-5Ltj0$fnQoaZ*h_MW6w!@KIda~< zoD7@3A}nnZk&^CzPoUq4{PfXbgIR>suW;SgJ#u1YJs%C-k+$L&2QjSEY|`z{%e!oT zR_^qgdEW$~La!Y~Gj|+ii2DlS9tMJoXIQBO_QwhwWw@Y1h0N$2J+tkkFBZRe7Bp`9{sK-dfi$ZFi`< zk2C*bsYjkGrE9_Y#}pDO3VC0d`5x3rDwfd^64Mfp9p_dfkUMAY)N7?X2^x50MEnb+ z|HW!YC6Y>~T3w7+aAi4Bi&wtFY%nSMbZi+oyHVe}30b4;x>V{W&8g!3r3yWfqvrH zm5*Nqa1J4dP$BMoy4Tw@()Nz|#9dHu^b{KW?fgl62K62Gd!aHgFntD@k^%1^t3%rZ zfsL$UO&h}4JaPx>EFs&crjYvx)?5DO6gv2xdF!<5^K)yNW>q(> zN7}F-Fx8Pe3E`^kwnnAdp}*eml}cT22rX;Ml*8N3azZu~hcq<}2OUu~cQ*Q1KMTGF z{(1uuOXSv9F0%+KDLwI79Sx0%YmTT&ui=!fWFnM z%}1M}@$Y!jp+^D5c|WCd15p$}%K|>vgN*xRPJ_V~W0&J4Mf#5>8md_`2KpEW5I2cj zJoXbfcq_jb9r^l$sAJ_e{#H!xmszX@XDE# zdot4DCZaIUq)4ZnnR~nCXtdw1Jpw(m3T2k%Iy{F>sAX!8PDXP_T3R-l6uIhC?)|E> zklgReHDtz5izt~fOc7vhr7&gdCT1U6@+nYJPLyEo;p=>T@Nf{0_|kv}iq$)*zA${`mn#7oS?`4(mHBRjju~n2+x;$r z5FfgDlNC241&`1qG<661cPxhWs9bp)?d=5_>PNm+2bkN_0=e2r7`X37)5E&9f;~bh za#eJRP;I5+R<%l+J`|vuD|!x%IJ6G2tF5;J&PVe-@RD?rv^o%)^zW)pAYbsUg@z4X z#g6FN0V~wOI&(3Y1vRb8K82mv$oWBP0`V0jLI7~f_Wx@|?4BMQr~cQn`Jp8e2+n~g z%;%l>gA_PQ?Q_!PONXqL{<@jB4VMxEoBA*2#61X596sP?-buacSdoP3aA-=rY1J;M z@WYTrnyo=A=($(qQH+KnW=Qqy{dbj8TB-hb`x8B18EC{l);eB%$L*-R^Y>@{zokL| zB-UKBa%V>_@F7GjznY`spxWSTW89p7cdqGMPM?_6%Q+Yny(ar0Pzr}uoQ7E zEe`=4R(^M#e29G}Pb)cJ6c;>PXr}YH#Th~u&VbUGyuiUm50NH~{*INq*OcA~E~i>P z#vV^f22HtPo#!2#&ftlF(I)}6Q#HGvCib`S7yi}si)9K`HKk;}J6%!mv{O0_9XD`L zxBKQ*E%+i+HKTq$^VjmX1Na%irU+n@FUl)jLeerP8q7A%OU89taUuW~yq^ zA7YnwqfYH8G7n`&*b%HR_s2w<xcpmJ zjI8jks2jmkdS^CxR;cBCo`p(a4K5l8=IEa5kz8>)HjlE1cM{l5xwXKDBJTr)InnR0 z8~j019}uk%1h@llFrF8kC9v1VubwZm|B1io%j^|i#l6cg>%9v~56w#)grSTQR^}=m27>GiNq^>m}Z?iP2d(cJ3|U7*LKCT zt{g0Jt1vFKsz#?GvW212$H#eqy{q;PO43WPjlP_KC|B3ooGVH7+MIZh=;Hq!Dmnbl z)WZj%JDFd6ovRMkX~AcH^V0j3LsQw?jPjuXKT8dzJaNHBw=~qGch@N~b$zemU7R@x z!iWt6Che(hTe5)u9nLrJcm^Xq*0>t$cKAS(ZjRh zW>-|5VtW{GiF)V3Xo)8?twNwz#Y6q|P$mj`#xgA8ccv<(>rYP#M1`e(G*Ht<$B7(s zD2_)yUGhA@Vpft$Am3mMw6Qo7aRo{R6oM{%by_*qTLGWX!M8tulU`UC|2`7>F+#sx zqKDj%Ui2wj8?2OE^LsRDtmy|8cOrXY60J+qlJ-DFAQxl`@WQ6|CvgExh0=ouuuhdL zwG-E|<_vl1PZfR1a)0U;c)rL*{07w_y9Zt+we{w7fNU33OOhuRC%5T{?RDa9k0_Y^ z2PENGXsCJhZ36sj9P_}r81THJn>2uo1iNo>ylcJYC7fm_Pkp(mU`_qM1&? zo4<^*=wgS!d{G7k%aPmti<$KJOhm|IIwj$Vg}da8pYGxkE;KgpB|^5WInt;`--YVk znZkr$J&Yf$*NA8PnJ`(`laGhlN>H*kNc@GowImmfcImsn*RO+%vy3GWx>VszlMN`l zMfzq6C$7)Fi(#Z;OI@uEP^JifNLVTFV zk`}W;+8-LBF{77PbxOz?)v&fD?)G$K902+BN+v;wol1WPu-Z-eTXnI|qI&PO!P zWh*yW%~pq`hEzpp(tk_SLdO>^JKNGwV2hLTUov2AJ#5ior_F*B&w(-z$y3rXfQ;0r z5Y+x$xYXA`2&&dZxwsAf7c&+ph+z+cp!509NLG-Sk^puf?-D=2!@7LyQdo*MR9E=9 zjnBEFoELGvfZSA1Eb=ztM$OdM1!IU+-=(lc%62&4rAfr4A@=}!NV$7Q(*Fah`v|6! z)_N=LFF(-A5?D{vgYxL1e@OAqJ=FZb->k){n3UcHyF1ng%tvl_t#J!2BcSAebCja| zQehLy-sV|HYWUoS?w6CaN7m}%V1--{EIT8Hp zbxrw7(!J-4&)c18X_GAG=~JE?<}?n!_v>4iPTrYoH0$8^FqX}DBaTM7hB1$4I}isK zx|6!go}9YWI4&*c(-P@y>q7Q77i#ROS)l+O(g!Fz%bzg3SG?h%+ah$SQWS|dZM@Va zZUs`h)@1Sok=({(r#~J8M^F}cy6XBEHBp=d* z)E@#A;xa$Fr)G;9$~?nq7q`O;o*Vvk5c`hK$Z<^vl~J(8i<-Bd`E&rzH#~ZwCT@w& zDQAFtZwWFplfRXOfqsSjSG6>kRdC4x{De8ZK2<%d&P~RjIBSN9+yxVJm3mi_R5*t- zp|sMn%NFdyFN#^c=gmg3@Xu!!BD!88SBHRZ7|^5)5w_`cuKbJPO-f6cnw9j%n}53h zc;5f?X}M`*%0B`P_k+#K%s#*!`;BEuXPWaWUUCP%Ia8G>&sXLL(sPKb?P1p8(}q9x zpO2Lq=BmBv&Ho*LRg(HFVB*tbgEJ{A>mShvRgf9Y;(GUm*!vnvcj_+}Jh@HmbCtl5 zts&b_kZqGLe^g_$esAROV+1;vSBBiZh$}GCiR&FXd3Rn;akuz_fOF7Y$t*hYp-w6m9wENmdbUHUHIlgtd1eUfnMassT!+j0>i ziDHa?^)Xc^OYdYA$ro3M(Lo$nhyHvIrD0Wa?>eY19#YuKI(jR#XBMh7wL;@Ld3E6S_&|#9yuY!28ka5K)omE9?F@p5n{3_!*(f-;zQJ*~ zK7gG_#vHBMY-?XIgdj8`K0j4NfM^Ni+ z3ox2?0ZE)HcB?&a^Vz)ChG#_yZuH*aYUGJX)2Q5DEy9F>jqe7&*O+I8VfeC{h zECVUd#%J)Ou#trkqs==uEMOS9wHp6e2d2vL2yQCF#||x=c1ZOD(}_%s5m!$6avlx| zzB%1z@l8e6ikdEghbjlh=Vx_v7oSE`y2@22Ie^_YDC%T_0JR7zjUU=#HtM z)2G+0r+>nO_~I3wIsGA$8ZVMGHpBsTQZws4kG*=Jcp}(D5mifXEpBRTlB7iz@vv#} zHT5bKOPhOmwmM@%nmPRW+FwMuXw2WoC9%n{Su6c)457!O43et-r+(5cGe_QgtPje4 zTu{pk*b@9Jg^m@-OY4kdb~3m`kXk(UKHIJDbt-Es8i8b9iv6P{3fKc!M`fMMn1#XT zr$3p_HfU3ZkQirXOyMAE79!jGZxlwy$UYJFTq+DWhJE?}adqB7O?6Sf29aJuktz_1 zfC$pNKls;4 z*#601g+2oKz97Lf>%qTo+kJqB2^m|wlP!J_v|b{sVR5zN9H(g#*%USIBK-rL+ z{WSb{$;0uro|Ga?HpvO6#g3jjA}x-P z@fG+wTk`cf9jxudDIIu4aNSi2ptI_PgVor%i;Scrq59&@2oh&r^~i%qLGGeyz4v1{Ij2DWqM%B30|1v5>2^m{QuhAWw5S?cwkEWlWzo?%_^; zmwI^;%9Od6H*UxG%Of5*Lo;gU53E-k^Np(LK6vZia$BYb9((X)p4LkRkP)I-SDO91Ro`xe-Gp@;Bm78rTbUnJ>f0(FhPUOvT=}}gdyfxFSlBFHskO`c zl}c!g4O^hK6842SoO&Ltwm58QeOj9V$hlm?8>BodhO>$*vwY;>EPj>u-sh??_ok#S zc^xI6O(X7$45W}!v*!Xr_Bd5uVM|7%K9u+%j-L7M` zJYr`)jk=1KY4Kg~@ENt5yAT5^p$TUaU!0+Oe6@75u{U3Q6A0Aq2FRf<*J<7*Su`pP zoF6_s-7F@p@L6#YhA54^@tO}f8oU&%Nu0r|B(5K;JIfO@91YW5gYg6z+!|W7HAsDV zd!CEUSkz}%#hqH^maouD1iWiDIOeMSn1;+#SMiPwO!Q5Q(r-W8E%U(kYRz*YUy4j$ zb&@x`vqCl0v&)*QgPb^KHa?{IIF5IW`=|G$)ZFeX$o?#Nhj2)}KQ+-_2lkdad+y&f zQ}Xbr@;RkC()ecCSoc%0t}^+ivCgj_oFhiyTrwZ5#HSFqa84ROzoQi6L&d$1^1ITf zFI!UC5F+KMXNnu1oa^Rue_4ACsWHTtV*1Yw2=-=^g)go?q@XJKHcp8(<}U{mShcriDN+{UA4k$>@XV=%@out5BgP+Rs_yZ{Nv9qrP1@r34k zRqy9+Wj|?xPm|go-l)nfHJR}Z7kWZw&zW~i##(7}JHL~%Kg6sCx?;tf_vP*4JPgiR{)`aYg!{+n34f7Z2cd zWz7(+sFhc;Xd!O zEf+b|C)|)Mqf*r<&lWFUJhDvu>QBx6yPMg4$QK~20Ntf%Z%sl)KjTR*%*Ct`cJ8r+L~K1|%}wT7MMT zbRA z0)TVCKorZZAO!Jzs_;Xd4Ij>it6Y#1enR|yd%V8 z?&l@x7ZP7SZtfn#IZ_vcqYSkynEYY)%b%D6Uz@&%pzB-$b8&nsEo<*4Gykl+hiV*c z+=vF&x?=APKBC+{LqTc0s`;M1K9ySGBWQN@`gm+uBJo-C_q_vYxRi{}9l?UM%Vd74 zPz(UpX}TXt(710;sB?Jx(Y*f#;8Z3mtsBQR9e$#~ zn`@r}jcqyqk#C(Jxy}4RVME{)-;uh_fd5hP65Pa0KDbJj^;NCt#~zqqyGiWGrws60-iq<`YSI_(E3~^7(Vh!OC(O$6=$FV_$P}98=eGoVXJd&3!SpofGx=XmJ1X<7de3i>36W) z0D_NWo@|;eU?^v9(F@!Hq5oqm!8$um%aD0gTytN>)PeTo11)>9WnY*B@I!YC4Wjad z!akcb#LyNB1P}v?_>-a>u2rDuf*wVn)&D++WzB%NVm6Iqc;9FCv^k;2YfsX$uQPHg zylO1K_=I?k%m?|v_|G6*Qd$I<_b%SfwtPG0xQ|G4K#^86Q9?^wibh?H!Kj%gJn|g( zb{9{*v(~g$c+!AuQM^@iA{g;St3{1WfSe?I`IA++W~SB7iP>o5*bf#5Mw)Qbe#|$a zx9;zZ9~qC292p%U32R8Q2X(>^3!1&1RbG4vj!l>X??%XTa9mGL>)utp2ANacpK1T# zV-SyY0`W&A<8%;HupQM1GD{3^T<8MJ0jUT~QH2QmW82!N|bj?#1X%{1Cm!L#NpE$Z-@Xbt@k0Rn)*^kFaY@Wa6Zh*JsvkJ)ke?$whba7qm1*U9L-ey6AzN zB@W~)#VSK_d*7(svt?}@lKP;v3nnkVcf2=1Ri{;h@Pm|(xP`yBcG#OVWTtL}iFlTj5R`{23B z97-U#s3BX2f!$Jf#g*yX#(ZUPc>d!>5W1w(bPCmtknK4vftF?)DhauM7(V^l1~QlL zht0{ds2$;q0C0o=R%ZRq9pM7`*EcE;f93B0rzk+&xSRPNTrL-OPyNcNx)rYMTY^HO zBktk*qHEG%Py|Gc(*a?oi+OSA!?|pH@hVSm^0X8_i?MYUnR$2)pVz%;`~Snzl_!sc zl2DPv|2xP7dhy0H@i=RL0L9p9WKG_7`?^?>`9!O?&yX+0n_AWaDLnHMQHfwh0HkFh zcKR8wc`pYML_$VV&r)@%?RU>Si6fkn0H6T^Z0E20Z0wMf`0i)3R5Bj}gIDnfn%ry0P{{VZbS;x77i@nT@)#i@0D;w*JBz*Lnr;1ynT)}1iF1@(hy z<=1*7>y;_8H51w6F8N22m}oFlRD{m9oiK3T>SJUq4Pt+w|59D~NGP*xm?%8SS)(<- z#n_M`3dKygDsR7NYF9~obEiHkRjjrxjE)`O@}(2RPK19Ly%ZL^;Nq%J#igRAaN-A- z`Ie$~<9(zBF0~y(hwQ_tzouN=O75wJa^% z&;&Zt15H6so=+P@{51K>JwcPi4{tO^ho?S$xbxumdZ4ed4fW+S<^O0-+`oA)|C0;( z|7p(hx+T&Z4VshZsg1}#=hY>!2@vXoS)KNc&Aq}8jUgQICaE)yc$LsFtSCf(7V%>|6IhP^ z2Xht-wRfBP2w-#ihv%6@nxp2UyZ41d+t@n!gm@ozJ7DDr{NBOk9WBhA93JhRP>j`n zSfZey*8jxdH=xNRAR8@8#kUxlvVpJ+3-4!3NK*K?+;@od1{Or3H?r917A(ZpO>1n= zVEE>CH&cAo0uyH0l{ zQA$-oYgy^59@ZIDDHi^gmiZyiv#7(trhoZnmLyc_rRq(i;4m45#q96Pyv35(Q1EmD z_WSeh{Zx~?GW1ufj_O*V?!g!H7Mt6Uo-ZiXyB5{f3x;D2{-Jzun~$D4Hb&p&=$WV{%7wT0dcxLrbw zSk_+AGL*Y#`E*acf#!6Uy{Va=Qe%Mu4w;Rd8esan zXUkbWsYCL~gGm|%Rhov@6322-)?%E|gZXc_J_{tx0eI?^ z?#(yh4)u^(N&NUBVg$U$!41QWW4tju;J>cifOBEcp=LEQuF7#9ozo7T*0W=$>o7BAz)iOWg~I)-rfnV>Tiy$5cZ*3jGe4IH3s zLxBAn=Thxo?;oVfr3qA){#YNsbQpC4grA|)B*p9GK)d8z#x1uRN3*KW#roPRUf%?d zP~aW$8k|}c_~S=2(5l-E;|(@q1W0l4PYOe_feZ<_YTvEL)m(p{dp$WzW%VO^zQ4Ax z0-wJ*WJa3fb)6bd3p5j@jbYK)U8^;);mE16f&}Pxl`i@{{|@&j3$w6`+`@lyjcxqy zi4`)5zJNyLBVA8FDU%rE5OY#Q>nGiEkk-tsKFVBuWQF!#Fr?}ZkX?WL_2pi2dL7lg zv}D+OX>439Am>;CPUmc*_;kZ^^hLPsDc?L)Cg#rC@7JV%wO^k`rtA#nkYsP=wi(xC z{%m5_K`u7F!p)tWs>aS<O+#- z&h$c6>r?tWa)9zQZi<<#hF7AQ0lC&l{6*$enme=#v@m7|53J#6573Hiyd8r&i^>6~ zsC0QAM#8D<+Du@`fp2{;Bn$s?=yU$Smt@!jrnB%mbS4b4v>Aw1QPd>M^4rD9bC8`? zO*-bw%d|UA(UI^e<-0x@lxlU#u6I>bl;EM`<~xKT371{~q??$0ZfU%|+N#yT_XrAX7oF&pFbEz|`5YaH0wxrlzpQCH)uZZ#1bH zQh4M%t_RuS-;ab;6RdX;$AlwqFF^lS@5`GaHdda7#_bBY9My2LoHd#Z?bQP6FAWm& z$<+FW4I*oah=cat^RLT4o)`@n?8&u6_!J3*IG6f+27Yde|6RC7mW6#VUC@eroc>CF zwL?<>s)-E$4MjGRfJ1q=h$Lo__w{XI5Xu2sfLnTh37y3Q_)6e4jcXq;vl~RQin|n| zKb7yDT;6lS0aN=(&pntIjWYd@AKGqzvx%L-N?!=V1EWKddG>k|m)p&wr2i4Q5uo6K z;ZYw~WSeL4A~DxH0Ea$ST2y`=&8Jx_pyT?}5}(X}08yc56*YpZFy_i&^~K>bIfa?2 zml0m8QOnD3HP6XErw$Am+*7_TpgDO44MAMRf3>9LmF#))1*I8AXU(&8bV`l+_9@P9 zV+8hzAnkR?c7)Le+``Ehs~C^svVnx1WvJkO99tZe5m3tfbr*<8dZG5}QuoOW*ow%T z(T7ieu85!>d&~$p_@NC&7e%g%07djtr~DrGl121sfPdZ4|7<#m^bfz40BWpzuFpK@ zkXi!y9|NyF@<{18gjipAGEmLrey=vlEZ?N15u7fpR_Vw)fX7=r33s@O(aM*w+n>|& zmt!sqjNa;Yf&QWM{kja9SThzjR4(|%dc*Y3oEow6f^YIZ{2FXm&(NXvK}#vbX!R;? ze+g{L)Ro$yE!FrpNIqG=e+5=*icMu7vJiG=YnNg<6%+jdD3U;V9%eBnl}V&uxZfs! z7KDy)7mQb%rRi+}MhfBXAXof;5xj_Qg?F>=vPpBk{P)avs5NJ?DOCKh^_wjBEu3od z{ly;xWA{+NO|BrKSo$rhKkY~Xh)z|PsVXPd-^sd!w||F6Y1#F~WjrJ^fYu$)4a>ISsQ4nzZ+ewJ`MYbgVcDMV&ixNr}(ra z>~E9c-GU`<{=&8S^4qts;8NZ9_&Nn>;+TVh;dziO)KjKcggB8*b4@kZ7a&!^l{=Df z@N*A*kly_6eCW9hTU*=TL=g{<@B#moAOMLQwj4J{aN+{5aOt>Q+n=0U(0~y`0uxge z;rTxZoUG`@0hm8k&e#Gf$oVE^TKc*YqIzJo#c!;cax~JC(_k6shsrjN6p<0R03(I1 zHXDx<0}KeCd2YqbM3$v+!1p5%0}M~3ns1Gjgt*u}jW=z0QN92Oub?0s0Z$Yc13ak6 zv@Q->*QpdzhOvjuc0F;xZp5 zGn;W)B>Z#P0TXQu6$jgs(wJ=XYp?DzU}{m&w)$bE9z3rtvf~PvBFYA$xn=)U{(3F4 zZ>*7~O3#Pg7y-a9e=~2&N_n~|NJ{-W(2j-M#`k2+Js{v1I`T$! z`W=%R#AVITY*e0f4t%bp8Qi<>k|cZv!*cv}+|vH;!*4WcqfO=GtklC$mwM);u#ph! z@1HT?Ph6_Sug4|+u4{L*R9D_N|M+_!gD8H^Wn5;-<$l!r$o=S#Y{PtRiN>3JZ@t4p zA+?xIS@ROpO7oPy8#~7(w{}+huU3p_ZKtlB=6u7WzZgx*+7D06)Em$5?~Bz1wzj$) zK-p_w|5b|3+1xK%tN&$Onhgtq!~h(l#r0nAwtCcR+>SmT{w4S_f7TyeJVhwe4+$;W z4}BKc>H9FE@paA`mtSbiIL&f}rG|QxaF20vrb}t)z?_aB8--Mb=187qwHYj%bl@)vz`6?U#0VYElx^+TYo@~;~+hI z*cw~w+ZGLW2Tm&`g}tS&t6fr*94koc#2ihB-x{bv)WxpVAXU8Hn>6G>WSdzeCA>nc zQIJsIdhSTC@uFhZb*&ay)R?}*#6FbgZ1e3GYc04Y)dXJhTZ;T3M~YiqofEV84qK)l z%LuJw;AYM-`E?D*8~yeu;J(w>hlQENq@HO=d|iE@v$}7Q48c2|aJ}tD0`@=xmr6W2 z{rx_PalVUSgEqRp{$z(<_ky{1z(R+{lPY>>&0oTvsx@!8EDqj|>x*grH-SYJY zFrhz%BnjLh1PDJe^EdXqqzlyoIIff}%weF1;&=bTy+9@5g=FTSx9Y}QX3NPXT)hD5&qR&ZNPH6i**ta{`CxxyN2?#UkfS8-(L zD5vB#eLvq;?FN}pg{SO@n9LU;AEVa1GH`|nm!&w9%HOsaCJbz6rM%Sk*O>MCE#I?f zvjz{!dl9>Q`pw9xs=xFFv{9(;F74qIk;hi*ZrKi_6#^_@9X>ZyEX>rqPoK;=zBxbM zWjbUH18zK$vWVlJv8djeu>gzL_c^Gm^KKbaCG0eNxE@Y8pDe|}nx7g(3Bc7x8fcb0n|?yP0`B}%x^UX^cceL&`-WK5Ae=eb?|({IKr)m;&tDxL|LW{aa? zKtnMCMchD;x+l%6B$_<~2Awk9x9*`w9iIG7k(;N4va|s)gRy@2^I9^j2efdHlosY%VO|XdH1;chgKRDDz~R=&+b%e&ng&#;`#3+l>c*<@Qo92Q>^f zX?iEKe~BAJ)w-?)%2Sbw=LPWG{lG6k$iU{*0$@bv}cb+Ms##JTp# zj4WGzvSqr&*weRdy<$_G%kX3ZctJ(6-}sBwxVdtM#Rs!2-8h%d;$^?v@fKbgv{Miu ziWMFJ6fMdj3-rNf?RRE$6Rfm8=t?q$lvTE1SI$QTi(@d>f|^bS!mCeB4ymEGpA-a` zFi-y11>ijF*s8#66DHRKGsenTO7&fbW(1Khf<}*-!D(JBCP(tAkw*HU2AhDGb*Txs z9jp(B@a8!V)0f;c>v3%y6JxC{wQ!vt$$^M$E4X z{ljl|=*?*GegET6x4c;n229x|_N-!)pHULX{qw5!RI`G+lvh0MF}c_>>L9}4v{k9F zYO7usImcyn_TKNgV3*wmeE3}*n@=u_fxjp-d~2`Ft`J<&DnbpBR`lMjZr^>^T42S- zCBg~7PdRcME5XjU^5czW?%i+qWzM@z(@4Bp|4!{FJR6LI;V33Q2*LT{@_{75yDqeQ z0n`gl9pt39+<1cRF9XU*vZb$1D8Iz8BW{>qUr9?tPK>b!a|BSR4d?~YcZWv5CQ;Nf zF}ibne2pyJc0SF82HNl`m~-lIlBz1Uu>{Kw#y5jdvGyn0;sTwxWo_%%iMY=_1XjRW);ex`%D%$1^NzAlV`a-2yo!i zDLGScKg!k%FwC^M1LV6bFh}RPlU(F5`0V0UhQSiESfr<7&-Fxf!(Os@T3TfGZ4`C9dqyki}c+7 z^+Ys~oNv$&(%xb4J~@M26^TVJ~qu)q=Gq(y82PIZ4obOJTTGaR4 zec{Z9uVs@Vwj@5NuPw@;lJh~ZGtpGvvZlpWS@ z)qtp)S@Ip-d?YcklUl$O#w<(FiDlbRdYj!6sHa;SyQhFV4_UV&yBY<&fO!83@vqJ5 z3kZm?wAIQVhVk>a9sQjeKU$v+k~gtcnE&|h_H*}>9Sb(?@tPoVNKtCQv!-30Cd{Qj zBtg#~0J%8b59$rN8*u(MaJXm)@yf^MdxQ3+&to`V|Ng={|7h|Wv0pN98=z(tt7DcJ z8|1l0tBZKpgW8~wHzQqmJ{c2pwaLBF>xd;z#?fG1LNd=H<77kG z^Zsf{oX&##&UD90>pjf|=KvTCAfri?`KXt&kR8+2zbpUhO}!sMF(2m?sv5^G&C%Jn z`GQW$n*cdP8NXp|a7B+2Swy&UC{(pBUB@8Qe6o>jK&y9+@TerymY6L81bmN+Mhd7Z zNPHgCL;ntI{=9@AsOJHvicD^M_|N^YgN#FUs0+L$ZlJN_sE%|oW}ojr)6ZtTpUj6b zkm68GzEc&BKRzW%;Rc^>dS|l|7%I3a#r$;rmp*omff3lor+KN~dCm`jFk19GwDO3s z03MyuIL|VW75ALzf#NE_DY;0?dtH)9RE?{n1%h2;vqgP?p9yqF{etcznvt291sC?h zo-^IM@*X^N9Kl}0?dwJqit0`}0dY1)guz>BQb(AaHp+cnjscRVI$bc$AH7|&e#!#~ z1(e|#B&O+;JC-3PT3Uc}vx~9?L;jN&US?7MhfB%l_Ma>ogk-J-PvYk#c%5L4W=LQ? zW{LQ_e*E3wrcY_WRC}5?bPNMeT)9%@3y#M+kUyM1AoFFM~K)lb+mmeE#|KJ^PyYa{C`a39;Vzh*y- zeEHjdI*m$Er=2P=LU6bpplEf5KqTG&5-S2g3&(r?AqOIQwbBG>BDG)?n6MW5=#19b|I7{_OmQ>H&bs!-O6l{P! zF2x&0Zh~moh01RV7k2+%Go|5HsO9G>Tc~kM^#&e$gbWm51!)(3 zk-eTE%J_hER9o8f!x~NVwT#C{M&d<3Kd%K+ig6BYYhKfP{4~rxp8TEEbn3Igu0&n9 zNl+_TCnN`Kx?qvWcu9ArUmZ{?N=n~!0s-J%IV2r@s( zoOx3UP+2w9QIPx=5Pf|sHNb839W94^GkdGAWias`wJhPgPn%B6w5x<_Mc&xDxtkkH zC^2zMJSiG|6%!eyeu!}=e1E8nIP~j?L9x!$>cydmvSvMGE>+nlb*$=N)dSt*qM0Fu zebQXFzUuO>12bp43s$v4p~%&%O4nFDcCK}P_<1g|-I_EHYL}W_RW*FZ+zyFW0(n{c zcWw4w%@$_WiH!f&OggmlZs$)-;RT&6S+6TgqvulSyd;+;dmd>F>$hY)3`y)=MQZAaB}!2PHlUk+ zDa*)wRg@1{?sey~SsuvnW-P6wqMccXorZIVr95rUR60_jT!`x15%L&$9XQT`PFfMy z#NW+S{xGA}KTr~OvLTMDKs0EJ8qwg{#V{%+PoAH1X=q!jKN%Ow1wM;bOwSVL|`~n!{_LP;q><3HC$X!Tko=XZ2KONXsETvx( z{R8Mr^xf4)Z6sXrmoncGU~6L|tJWJS@GED3g2CE_cl0mvu0*}zWYA@n0E}3JX1xDg z;R(-?VUIlG(AXO`sMgCBECuD0k_419|6G5jEO}JxJOu;=PEX8Uxl$B_FLYmR2_k@R~C!^k?YV(@~RCfGP&37r2MrEAjYm5h!AuD)0U zHnPYRpLC5bdZ>LSS2_`Y)<)tpD;@)^7s-1_M0;cs zsOdMQbv%;eTGuG}@D9!KDz?4eUp|eW2wV|S`CQtTUg5$VT->Rwu6k`Pw`fsT*?U0r zxh<_E&V8#>g+8pCi=B@R+4qK}^V_dfalLT+eR``01PLv^)6>oppJ^Mk#AikNv?r2G z#m&+j^yEW77~{|_zubsv!UF(rnJD|VIH)}Af=iAVS!;lD)e|tpmYy&Nh5Xm`mcL!chY5< znyzsQhe3A&YPiU1jWG2qZ^PE!Rblw3B@Exia8%x>vP_xJ3X$P?>G~x1nxnosz+X1F z&bgYkHE-v2RjQY`O?bS+yw|zYt7d#7_U|j|w5VV;go(-?T7^EHhfj@R87G#wcjses{0XUM~k%5@izyb#D2*%X3V!XaFiK%*+@1h&IL zwdKC<+EkY;@DbPXO2%P6jJ}@Y#DENLnT{*eCy${usI|Mwi@AYsKA&NIj&-3R^Dq9J zvR#uC3g5}4=wh_~tv&hMPKo<$f(qG(z2+Q}*Q33U)<5s^Z^Rz_nUMZ|t3hYrlcGq} zW)HrQIAMV|WQbH-`!y&udcCVko6)<;_S%uB;qFf}?Foou`Z;k_=6!;Lzi*~x)}c}k zRV=)XzUujkzG%amLsHB5G{3`P+I`G^kucuwNh^5OJ|A7)M#h&BM}H|p5kMF2jl@Py z)t`y&k(a|JT5g4aCPKA8TqKC zOaj-MGzlKC00nUMZcC=$fa&@~ZV6c{np((*H;EFcGphOfm$ZDW+Nn#qK=7UIfuk^s zm&v39Mk0rmm#2rX;U_tDbK^YepE4ve2T;dMMly>CKsM$Y^d6pU7MH2N?itP&okj-H zf1wf9Cm5i=Z0oe$k}SR>_tG{hYTEc$Q((?H+kmEqwog0sa4Q$0N>no67^Fq$x=Hz{ z&bdwJcND4pwP}~hzkljf(Z|jRB)+o#Bl6K1jADV=wwyEMwM~LsXW!(y9IL%a?Qs_M zAX;^5>PS7!Vyw+q)vhm%*SGY=X?n!q&kM-=7Devfjz#@yPYd zUY7(CZ#TCD`Fy!U_PT?Fq2Vqc{m68jOa93Y-_CX5oGD%l5iXAzSu?T6vqDXxreB-R6u&z3HCx9)aEM|lyi4e0XAFTZ8TBp%~irsaHaoH6T-)tDn zKSw#wU6|N;*5t+kot3n(&uL3d#D12{2glguJpo3n_&iECF0&LM>MLx@>^GY)3fp7q zMBM8BmcWl_4wKo=Kep*|+YShKe!_xPoT=k`>x@x7!f7VI&juQ)RdVQ5C7#aNKS4z7 zB`LHHFOysjRZ#I=jlLCK-oY)ceGYTJbgcHOHSWrA`+O~JW|Gz&r*(RC8;Q}XpLv$5 zcdzf!s66A{)27*&BhS*`a0gS&`+Y%_da8WbPtute*VL_hCynj{By!ZeoGZ z-KXY0mD>qe1hz9S^#woz7+=HZ?xU^|?3`#-zu$|*-Q2}W1IuQMG(IWVocT|E-|WWAG(-#_r#b5IeeFIJynF6w2oRl&F| z%|0p*t~-4}!}77>#}prR1E15Zo3veja@pEx8t!CMWXa-Sway>D`xQOU+)4kj2bVfp zQ0Xn~L6kG=nS~V0bRQzbae;p(^X+%cU8K^q)(JvY5Jwnn1HmRS!^~e6HWJ_BtqSxD=1|1Mf^d9*;$1VY!e|~@hQTC<& z`TYIf;xZm`8lQ>O{a@m!WY=SWnN9zrJW1xB1T^zbh4~l9Icvi&diGxYB>JtK&8yYqQYA%o^lO>GO+8Wby8dQ2Z(1Y(yL$T z`NL}^Ni#jBQHl6DirjuUj1c}Z+}=%=miyyF^LHNFQW?sg!@d!|d`W9rgk^(ZQh^um zM^*k*y{7~MfXkB)EE5EEIWG}RoSY9+trzCcVGEVx-{)!3azxmbRD=z7!DbO9vT|dO zgl+oZb!RkEg$H?q1h#u8J+#q!RH2a_drEBiwFeK$UKwvoh5n74_M`o4eWx+H0yzoaRSl9wRtb#?U&H(saasV!=8yk8JwdHpW`Pn509>D{aVo!& z=n=AqsmhqtdcCWOZh=a=)NE0}Uyik@n1BO}!@aR=IoGfjuJ`1RPoLSg_+MvEaw57p zibdMuL`qGfR`<=97aGvt?KV}kgMZ$O7~{w+v{BrpSMOGVoQk=Y!DQC0*2Nzg+;Ki_ z+tc3F^x|^G6>VGc)n2}F9uRxjfwf+LldZEH*Dc>i?epX#j)4#{A5ONOxC|HAc2dIU z#wpW|(7PBPU0%#qUW&tJ&C`Y_!$5%yGrDK(TzS_Ert5^fgX39oVB38c2b+E9qkE1% z2n&Gb10w}MFd*XTA(B?m676?noy zZ`LwM8tejT*G7m5GXoj+6y5#IXRgk6V|^wS5Njzs!e>vw!?8tzqz?acOK6*v972bN z5nSjGvOBN<^qz5ye!R7~_7;N&teUp3g zf+J{gSum{eRMpvd;igvABDVq5_p*&(gX_fm%B`{9#k6PbydQvBpRN8UH4T-;3x8|e z#ie*zMKqC5jPnomhX)!_xWKcq5Ys$;d)NWrUZE%sAf^qM;EW$-e|a2zqV~ILp&$&} z6{F0+<`s@eWhGEcOjHKhu{s+%jezYD%DZ0H3?DiXggC zU{xNa_lNtGGQhfcxm*cJroEwXDR8J@{X|2sb%wk~>j~(;!m)NB;U4JlLf*8U`Ia_} zjJcTYR_n-tqla;P?EwEzo)an>m(cT$Q8ldG;|9Ckve+E8BqqsmR`1_KQz=-x7gL}( zX*coC_m9_*&misk+05LtO%e1>6Xc0H6!~(oHPHFoI`T6Z1GiqxLO{z~Y`0Z4=lLCm zU>+_M4L_EH#%&wsTusl*!(PFfYFeF~{J!S{_u_bdOWc*n@hbu1E53q7%rUuP77!0U zsi{4tuKD~^*#VDy;q3snPH3Yhdx250_DxFyN=A@R{yX_%XUx@~Q{8MDzWZbgrT$@< z91`+i;4==o0$cRFMbkI69>5-Tj!8W`jcA#1gw$L@q9KOyFD&3NHVaeTpPf&ht7{L#Zv>w1#2K-(P$3 zc29-gGYM)V>Snj6t~QU75M!5n3%buE9hN@<9jp`xp8#z>8`1bn^1N5=+47xJI;&mR z=v$4JGl{y?7Y=S<5TWw1d%uv64Q+&Cq0~V~4>H_%bC~EutL9X1g>UWH&*ZhO@zD>|mN%xHc(Zz;9Q5o;$)x$O zAAieVHiS?iqQ7A(o-2_POo#}Sn1_4NuAsjDX7M#>Y{V$r)o(F+Q)JB^k2!pH0wyT# zUru|WwoI%iC^j!utS8@PT(7Qo+PDR$TN?Uf)ff4oSdf?3q8 zaOl6eQ#sZT)prpEz?Zv=vP{fUE;9I$L-9vmcR)mR3;h{+N?%}!)kZ!W`jnU;&(tBX ztA%=*M5DYuWgX976YwceuSvs2u~%qz={gCG-vW<#nonWG>81S7R|8c;(}u3b7pQm2m3TD zGPtJd(--YtM_ZeBly7+*QqaK288m3lr` zm~1qaEtltN5N}(2sZleON1&DpcPOfSM#xgdlXT(d6z;OLktC2Ih`*96RtO4KiPi%9 z^SldjpUJJg!433BV^PEoIMkE1|E(l<=VhYlHC8vuu=9h)Tc;Mwcav23K;}wh{%SKD zw)3h}uOj3S)7O>xW{B{k)IULK0x&rK)ZS=O@8>q>G{FNws8Og?h1n}czXy@iMAc&Q zcrR8wmCgJgSqB05&27mOuv^aa&f0r@?>H6kcaKVbZt<&w{)UvW9^vP!(bh)XzQXeF zG5i(+cw6l>7n>q5Ktd>N`%%SsO#TdTZ=n$U``n;692t6#Gm<_s85uHR7(ZK4?KCs| z{Bx{18|IdKD|h1UREC#3Bk(nS$R(eue7+5|U-PW^f_i#ORH>lHC+}frVoO5`qHav& zwlsO4FlN;{TD*$?nx99rN=e%76L4TFn_YK8J1`xVY&qa_EE2uz@YF}hhYwCuh^ts=v$Xh9f5YaHvV zC^n{OaEP`?W%rrRyB|HbeZhK+2{JZb(QnYHd9m%Jd&iz3|N6XZ@!Yzg}Bk;Fi9Jvh}mRb{d} zY*>6Zp~$0DI49F{Abu#)&i=De0%*%5=MNTUI&nImngb$Bp;ce=0clbHej0!GPkSlUj20gZPrWNsThF1?*U zie}c!+ES`F&miYe4EoI`&BI^5Y7QEq&T)D>VS1T71ur#TzsWLO)Okk#?8?LS$J*;K zS`H7D0IY65Xnbp?mLwV)yAk4PSt!;;YD0g;s_BuhC^J5vBqt|llmWB=nkC|FxE^Se z4kBJkVOv!KfMikla~wONrRPFX6AunecjZt z%H2Q^O9wKl+-o^h&Xa!yrf@Ysv|cE4dngkLY6ngn8kB(*$zHcD%LYXZi`TD@Roh4< z1Q8kZ?{&y>T{V?+d8R1#XHRl0pFb%kwKTYkTuRS7TXYvrtC|3Q33gwKM1ysLc7k;yWNba`T`_pQQ+V)TILn*PtTL>vaA~9N&APAxxz4sC|1VIu}Q*@*E=$+`jjy{-~^Pjx$`~BayW-V)kEOXYJ zdCqh8-uHEpT=e6@9c7+;Lip}k$&z<*w{7NqA3rA9oLc_q&c#I@VZm|F4;?9b9$u`m zy;vx8t{m#gk_Rpi6MsJ5sWHJ_ZxtqRs6|NLX<|7)_$%Z%NgQ)rs1>IhSV0lt$bd_M zl8xuB=+QBM*ru%_Hj5n4iMP=vN>W2!B%7!Xx<3u7e6vDJd+5U?-ce-zpA{f|V_!zfVJ7tf60{tH4xp3LGo2Dbnu45Z6UtiAxjZhkr+)FnSe4#C-{Qm4>_yC*G~u7!fIQYhEuoV5)^oyu z^BQDZOW!M1{4Z$Co$WK7a*OtGuW(4Qgi8;X(~IN$t~>@Jy}KHw^yx_Hoe}yPCWTt- zRr|bzQz48Ot5ZvF3Y%v7R@8akwQPJaM*(Iv;}hQIq*H))lHh4BaeWDe!LW!er}dEd ztxItbQ`&Yp>XJ*YRK>`N=r;IP_1JfVJ+A}E2VU{<=yjqauoO?0Veg*Y=ak=Ab8l7h zQX7fo^~76PIf4{73-XE*VSdlF+(B0|b=`jAiivnbv?)|4#HKp0Nq^xA(i=aW=4nRF z{IC%~L0$R6@Bsgw%5O$@)_qos<48+lT&nEYOndpdU7rFL$nXMqD1tit(ZT-K9j$E0 zDy&Z}d{Qh1LxJY^6ZC#-;<<6%W55e)}AhBl^Uyz1JDxbJy9Puxz zoW^VOV*$?l?lc|MEkhO=Q>`JNi#98VP`oUk3Rhvo{Hg#*VzXS-i1nq()3@No-WnQe zz0SJVmIQ8pAMto)6PoiK(RTvsdtawaC?lgVP!y7K!CfdGswK}5-;(ZtAA6d|C^Uu? z#oEfK;9$3}4F1itC7z&JO5fk^^G@Q3`uMO7*nT2(lpjfBFc^TR!k7=ZG_%Us{2WgY zJmp7!1&KBO8FxMjk^W8DGMK+ZggKGy<+y^1oQ7^Wqp1Ej4E|+J=5jZUDI1X+iF^Iu z$>RU%rEmh8i7oEbAXV|?B}AC%GkB=(%P?2@@%OqF zWlV~sMX(Qik?CPgy%j>^2N4*Vp`J>JMu0bPHE-hTEtEr-L-QqN7!!cOp_UXolk%UN zE1eVvKg2gmJ_FpL$-4`j`Q^$;f07FU7D&;1gM&eo9Y>(XvanI5VgJL&-b?`&#A3w7 zbrhtW-HLQ4&MP9P-2483@9EC|6?m;;jvZ|ObO*XWGU*V06Od$hp&9Oj=QLB#dR>X- z=5FvjByR8g#De*;X|8@OViD6m_RPO!ss#`hiVdo2oGtF{>kHu#P zk_6Z}Vy3zR5`2{LGn=>pG)R%vy+6#yJG%chUzjrTrJoS>NyU1@bBSq5N$ZtBJc9Kc zCz#u_qnzTN4*!<8AR8bJ2ksX4zFgy7J0;`9V}tQ%eWmD7QlWhcLFbhwLO+FMWtnXy z?Aq)uI2F}+5K^VK1&W8O&0=yx!73@JZPydFbG?%e_Y)=T_^Wz9);h~L2&lWrule)T z>sOeT^h-LLuWNau(SG5I4b5G-ue1^%?xH&TdkpmAsznNEPx%$b$r{x$o9pX!L$GVT zE=0t8PDq;(^H^Oi2vm0T5?UC4V_8JT%2=542zQad_~I7oIl+_FE|hNY6#QPhDV_b7 z->3kd*cI8z^euhk8x+Lru%^Oq1X=?vioDF?!L~05o4vS$@A998#V}h0Vqfm0clD?& zQ?bbnd$fD;`}weznN+b&e1hQWFZK?I&q)9Yk#b-Yfx9n&JL-vpUQ|2GJZ`_^JXiN8 zLLx52+L&L`jW7UHY(u(gQ2jX(8Ml;lIV;j)KwS07gVBlK3d%pj+0mgS1x{1F-vgEQFM} zO93)(M+vX%n(^hkyMk?&@_a82^A%-BxP~d5tiDlHeB42?X;70z3>fAfecoU8cn7%E zx7-MY6gwW*o!Blb*4`|_fP%n!_dh`q`{qxB65B{EzU3fZYomPEWlkw_ zgN{j26o<@#G|psDIw41oS3?n@2x8)IofJ$$TTppMv>hkAuQ9`uYttjMiPZj61R zg;CYvt&?|)#s`4zCH>M#00RIPWNTH312EM$x~h`F(B86gpPD!@_?WB9aOk{a9qP*1 z1zmQ^}_UNUvV$k@4Y|& z!O4_SE?%HD9a2kbp*tT2Db82_jt?iOAOJjqyU&za0!q21rLQZV6N*TB1f2k~)5t_< z+2<7)8-!ivji@>4V!9xtm9e|q_C(23)|uxj@J3WSv)8RIL@MsFs~sCfDjr}Ef>YCT zK|Je=J9Up2FEY2Vz~d!EAB9zxcd%akEz-KvpcU}yMjh=0AfgIH?O1(=QT^$~fJ4lm zVW$3+tCm7t8p2mX!x0J{9jfn0W$D1zrt_g&84;2f>1?L4ZGkRXAQBYFV*}FU0P@|A zS`t!`5X`S5t?x;ogq4;)YXvOv~Kfc#F9ZzIYTaq*5Y_K3ZH+u!qd8^nsc8;mmdZFTc*XNhyi0^V9fGKJ4-7G)8JvXpHC#l_w zvZC<^Olt<;S#>w_d-s05V{4u#C8n*!3&cFqWiqI8o>~z=DJuv_BrnI{{SNNV+Y8br z;JrdmO!Ze@jJURlz58g6`BQ{PyV*e7ch+!-?B195!WenH^s@y{D%$&P2OYN&*XI%e zttp}CO=$a{1-0oJJK;Eh)S-i-@FfXIgeC4+?M@(n$tLaAn*BX{|2cs5#E;=hI$bC* z*1(-PpdxelxOXQz&ElM`Dl~7buiU(_ydM$BZ+T;oM40gq$#~Qu zPzyrVR2ma+I_h&MAQhrrKz1RZJWGx2W4G?q$lV_UNS(QlSfa0=R}IFEuM=W=P+Iwl#RaH zz1b=?_$S0zccJJ3O($Z$=8!YA)7p1>CrsjV&Pne3*ZT-z9Dq_|fdx@CE4`ypXY>1& zfR}7WW+Kmj4$u8S3-qGkEHZR4e>p!-zJ}j+>rVLC;w{0wK|cAOCv^K_0jz~JTy(4s zu|sT!RB_T%keHeZgRG7M)wZFHKW^!fw(~cK(CLZaB(CUOP?7vhcFG*Y3;emBt$}Fl z#V*m?U*Dwdn#C_qnnnVTwa%3>TjF+<>r~(qrtAA$N-Gug>jozqW%KBx)#1mgx+$n+ zS!YYQYTYE?w?uU-=hsN*@pO1wV5EjUp4meT@@z7@Tq)Lb4FKzTLEU=~Wnb?we2uB! zH-_`&h_=;8*_W=3L#MN}QjnC3=+>Y1_<5@a=aCA2q%9_%fj#hu;q1aHEz93ML_Psu zwM;nz(g#ToGqOdz#aG%xhBgsNk8v^c${9MN=Sz5gUX_-w^>DHdljBV*AV(hn{y_3j zY?kC@NfaE#dYQu4((m*Rr>P0L@3P6c5WTo#)PYIKBr}+!S+IRVgo|dJRy*NF@qx^* zLL%7y8d>|ASSX3*x62A}dZl`*_-XX~58J`ulD~>x$Yyb~Pix5a#qz}A!C?NN@2FCn zV6#J{IM!Oc4!+H^XUx|A@G~GD%eBrzmwIyeyeF9m?WMkuPHNIc;3Du!I|or0@zMlxyDP7tte)EEFDMzdVc)>%o`p$$apwF;cV}t>uF&t|&O|d7(OL(vFaSwtGw2wMU z$I-UAPce&)_IJG4k-DhSAyy7J>ZN`WLcdiBIgdzw?s*VMvNBmVDm__tO9sQScc@Ds zwmkO3k*7)e$r4iZ3L4kIndjYgb}&I<){uFF!b~G%!|yn%;r;%-a{6m1g+;VN1EQ5g zaCedd7-Ro^$4={ct9tv&AT&U)7f23^OV5p1M5jIFCQ*72nx_XmUCoO`j9wW`3<$rS zC4qKa8OS40!^^4IO{MRY9=ZypIh!PeN4S55d72)IIp$Q7#)w5Z zKczo(zFEjQ{e(ZH@E+PPo>A?VSCTc}@cJcwfCzg@cNs$JU^)+)rdViL71{Jy|zte^C43Tmk7>c#I- z2}H^A$nQ|DNYPM+GGXf8C{M~J>ssgGPKq5JhJN<@uB2r5hR>GFY`)kdX)IotUCC;i zl#x|52`UN@=uB&SA;HQNMNGu0GCxPL_rlFiH>db>DkjUBAEEuqT~0$OjuAnRqLJHP#{`Yf?!H|>_h0}X zCbU%NO~%F>3En+XD66>mU!`7Gd@=k!Odq6iTQWV^tjPL`N`rCNJ$emXA<2rwA-I>C zx?pdnw|2!#y*{l1rXUaFdGwzDraPiMRQR0~14gIbLHnA#o=IV>F?T}0hCbDhcN&u1 zeqS>((6 zQjbWlwQgPn%^^dCBJ&b|$}gS9N?#nz9Y(i?VK;F_RgmHyj(yneXO@`nc)98yPk%O0 zRQ%*oo3Qg_hUyGgKDi;DKm2VN*tq>7&@9nado2bLXht;6Cw2F?B6f_H*!{TSur}-0 zoBVZ&wNHu^%+P}7$>d6Rvw932(UTCi@B-LW9e-rB+9tsl?dEhvI=Fc zytqx#m;0F|q3W)W^2oQW5SnhJl-X>zkNxR`3E(uAa+niaU_pUpCSX*6Sa}q>{jDDh zjD!>u#v_N8$+AfTV%LvQ+0yp0b+){%IsmK9nZmiln#L#OxnV*F?L|~t)0ImA6;#+S z*symEY4Vo~sO9lMg(T8c)!g15ik>nzXm0|~TAjn5uPqmUglPj*^G!HA+oxvnC{Qz+ ztZ)fR;w|{~5n~aI{YmM2{Y!1Zj|0)+BLuGflS@G?Z>WCpw+(G;60DdrsM+Zr(326k z2f~?feBgOF#(wmRjNUTvjE{MXtQIU|g_5C^9Y+maYB`|{juFc#U+LPi46>w0CJHyj z$VaZznqr^ZLpp_SVr&e^Yd&<8@a`a;qa__~x zHHB{D+dWkAzzl@4!T*P`U&z2!0?il=q|;I-U5C65LwM_>a z(xRR>qk_N+E4QWikEf?lIZ{v?6sY|zn#Wv5A*xRYaX@zWBbVhG=lD-|*2YEiM*Q?; z-OCEk!`yQ5wnQNi1;K`y(sEsc%&+N2uI5TDn36#YQuNja3>(SL-p^rae zJi#a-2-_(!(O#2!&YzY9nE5*eJIsD3dqX7ZRX6N*ET~Wv4T`rli>8BLxnjh5FgsHz z!%ARBk;H10%YH6}1;IyaQ=x`Jo9Ys*JmMDMBvwbYRpxgz&NW@z)+{$rwdGBGGx9ua z0&-7bOoEBhgynF=s=n3`d$B{y$;;3jf!xecI=R#iM5_3FN)lJn0Kllgn-Hb7=Fd{o z0Nzy?<{y>+Z2;vqiQlM+RlT@J?@+w1X#XUy#dQ9N#fgokP>M=?t-`d%x#9U8o3^dT z+)kT{ZA%4PYrUx2AdBeob#HIfr|bE{Uu3}oC&5Qn{=C_8Sy8 z)PR|TUexFQFR48Ht3fE86VCex7t`M@yFx^m=w#$=^IBGLW@wp?8Orzb@Z)_?mxtdw z))DDquR6bU9BIY6f@3ES3VboG_kU8f{iSB@>soCmSV{o5tqtZZ>kLyNB;2R2G~r6` zN&P7aR{GM8V@br!4L)9RDY$PrrEX9|B!mdl_$_p1!Z}hRG zM&2ePT<+~+&`}tcr@sL3Xyr;(1C0Rm7sD?l5O{;r1?m{Ly{_3?2Cg@Y0oLubc`ZZ~ zyJe>ccFpy+2Crm(b(DmZl(h8NT`#@2i=fMgEEZIs+-2aiE;^-T1ujwM*3)*Q3Lm0_ z;E&MhAC@3%Ln)((tS4{H{fN*&3))gT!Wt8EA=#*P%PsQGUs?8dYHI;6feKRWrv8={ z2QxoS;X@b1it3J4LK2_`it zLD?MN8yLV2Bp3q{|5uthhk@r_z{ZeYzjiKyV!8G`gJWKe&NN*{dK3QdKGaZ)+R7#g-M&}Q31D~HH zorp@w@DUFh8lwm?wW3jf_Wnxx{I+R<#U5dIwf5RFgp1DpZ&W^M#73XITE?Ij>62a% zqoso4@9W(byF71)RFdbD7M_-*vt4jmMmAxuFD#ciDLlBHz>KldMUF2QP*uP^WP`be zOLY95?DF!WYh$>sAX9B|yr`VM{$spY`=sPy2U@(r$yAn{OMDweXlaVTv6=<3kB{jI z69c~-N9elf&K6VzJ=dmbL4nsj&j)Q!g?n0d^_PxXTs){Mx6qfiCtO=FMP5Pks$|h2 zDev?O?!ASYgX6S*UD>ihqp!)^#MCU@xil1zzT0&`avWBj?f!ewbLIAcw5?T;Bh#s- z8k_tD#)uPnhZ!-|R)oaNOL=i~h0ro9w^B%h_l*AU+s(TbAu})8npt#d<2g)}kq0&w zLn`Frqevo@LI8(qkQ5)CV$Wm+e3zfYjt(1T%O+Y|d(GN*O@v8M_jL#7z`4aVd>`8R z+I=p-qxCqP`9X4KNuxggoU!p7=Q|b%XMt3-yU|cw^Spljs}=Xo$|WjRn}mkT1%%G4 z%u%doc}BEk3>Q6M-X=I2^1o#HV7x_S-iro(q{XL9uYvToK(CeYZ4-b<<*}O_MD^&{ zc`Y(&%YkHwJ&*|9@ps-}BeIoeNqtAd$cta`E9sRn5$9q=gbfR#VM+g5@jN(X4G;Xo zT>(aX6ZbzjwZqunZdov=frUxO!Lu$KHpr?kx8Ql+g2i8R>!rlag|ED_30;_U&iCXR^m&@di?J(fQe8EJW-NA?3{c&h1 zjW%pLM8fosLfB#LyJy!_>~yF_Vl*ptK$-5L#nZuKN(;7g4m~0yI6VD!beHrj2IFYZ z0_%n-zA*S0tTKBcs|$RaD6O-fu1OfGP57Gt!^SoZn2(bTNZ@L40zFCXZ;3V{ zRK3oNgT?(wz1!~f0I(`}%bnJ6oNYdw4`rc}CY)x4g>}luA9ZFDIc$a!sjx_{$vV6OGk=Ka3Air0?NsS=t~Lia2_ z$1bF8?Octs;xNc&5v)H@&#EvLE_?ywNq zA}$X6K!dYj5>LrUOoaar3*hV;)6!LvC)s@0u?=l$2}`Q3z9}2d_teoSpVKuT$|c&t z>aumznioBcc=2;Jg%dHX_$!&W|>1l+B{cHQ%MVuG$Uxl63@utNo;{UPO zjUg?4HVU`$C@pmTpP79QdQ!EHcBuHV!sCpJU_FigCN^a0ofsCQS-^a~_gM2?m;it9 zsFY|#84XeH(;;?TR$o%ibv1bs^S~!#;ylurRishr2QYs}S%?-YZ>Jh9CN-l!{cWkk z^`ZTGsi&$CFaKQyeXKN{ARW=*CRjw0SEKa_)|$dn^$G&3(C!J&>tYiE1-&y zOlfDHo%`-VV6jP{?zgGRQCz5CqYc=ohp;BGANQTRQJ_8+SwE?pHbVF%nS?k zYEwmx4{C+qojuZW6YY9dYR1UJStm5_mnxDA*gs_@%z20R@oX`KdHphm**Zb^C3y~* zSb225uyPW;1|*qeFw>}?I?YVM+X;>`PERriKhC4(EeI=e6;QF(K;0I*0;GzlMg1O4otZx=nZs?rzJMA8#){~=P4{ca538q!b`BfkUNhLLk6?du3FtvGlU zf%8p99y=IHFZz9z=A|HQ$izsly~HUhCs*LdOs;lTs6Q)vn_YYGT3HP9Nhs7F&oRh# ztk%`ayNg^59_G2zXs}GiC@~Ois2z}qhmhue7R(dk|Ge5dip?)kpbvP_!rY!9whYq- zn9BUNUOgLtNhcELbyEI`d`B)%t5l)7Yw68Jhf`;%W((S6tW}en9GfOM$=HL=kb2qA z6;rV-FJCkDav@^uSR(uLDm{gNyd+%gqKcf27zP{UZY*sKm(-kcOV7ANzq%)LwgP%A z_O-x^*IxU5CN~~$M`>qGd^Mc|L0J)ob$%PJQBw1Taa@r!A&6sBhJb3!a&B%kbWM%G zpw(oc$!J?fx7nTm^Cc&3qkmcSTs@8*LVrEfxF@U_zpM71=(0Ol_Sm^T^M@@NhmECD zXJa?)O2M9YmcWb}TXG@NEiyOu<&jnTU%~rPFQw7Esr*}MqKNwT=_eI<)|{n65*X+4 z&q)rkK9K|W6ID|8rEImWTv}?UfBr+31k$Mb!9RP*sUN`@xH3W0pa#<|(uB4Ku$6?G ze9*VQh#bP!Z!({%-T#UW)}r%@t9kfQVLN_Bjo8P2q*M>Jw`+NS2EkU%dcBV=u2OT-pZz$I_)jTiRh*_FS8}l< z`}L4N>=wUpGlrd*N(D*m#36zuzW?!M+FbMlMY5t&eJc1iaZVa>{FCbD!br^!FBF<8>3H;o!dgA z+8R2JemkL*=gYy$3D)y1M_YYOOT@iBlDQ_Ezb`I!7vSqz7rKS8lgj3&An^n-dzwd< z${x2w7SrX1`4~JehsULN@h;ZOhFn?*YhXq5AlxVJ7_o%_XV|RFS^{GB=dP||B*YGS zx*r&$c$gx5oI-P)20$nkWfb(O>&sLk;BgBy1BQZm(;D@IoMP^#AWDrd+(iZG#X_@y z|3U@j1{w$7{Og-~wfsW`I^sH&LE0kYD7ha1>FkI8^R@K5UQTU2;fdh1!jLaSV4<=C40Uu(etu*RYp+?eMpe-oPARl=eD^OG+hHne2t)RKehZC znrQQwLAJ-n2k&5YUs|l4gv%s@Yf+R^^H#w2M>(r5 zWa4@&&erCcYX~uoJLmoPv90Mw6%6Rjf=xfN_3-FNpv%s{z`%{(eyc55iFt?=UcWKd z`@XE8rU%a}<|ztYNMhM=-a>Xm%6f}zPp$XE4p*ewjAc#sg7KoixZ3X*#j?|QfNZ7l z;`irnpW$-c76z(IHWHMi`+=J+-ro(524+`m3Ee4(I}k%?&pjN)bV?QHIlGnEfoCVA zI2Gnd!z>n+_t*D*yMtZRQnfHu6btcIr^w5tpTy*US6$QPk+_t}L zOr@&z_s)uz@}V<;J@wesDa7B`o34wm#|x)l^_`sy1*%#U4p3 z$w$ERFl7y%2&*}qPYpxIbLJ)Gj-=R)v~@l<4jihkXpS}<(9iB##*>gt(nA#KaR6?W zvO=#tQgNfS_Tr|9MWb%6gw?Jl@SpaukUcJY2Al{^Uls-VN~!GOh-N`UxW7>ACW7??Bvl4fujh7UX6#p-_8lLpGW_KeybV(0JG z<;iS{n7Ck{xc8MxBp$!`X)eeM|2GL|1GL^3Sihwa-h}8{MAEK|id#H-xiT)EykiN` zu(w?KNq?X@^!%AdB{MQ9;w3|(hLR|C8`;A^x1>j=w7qsHC>wC9%n?(uyUPA7gc|*1 zPZ+0B(n3`PPr7F7N-jhlka=cgYX;MrGzwvda;bQFRumv#CMw|YsUOD9Ut{2?idR2~ zi{yz!up-9gd%1^m%=v1jOBCcY6PO7xoD$`;gWtka&K(B4l|Tyt#Gy;D4;U zj1ZfC->C!#3Dd7(%~>*UzFCksS&M%Vhl}M(>%v-@4#Go~R)m)pnUf-Vu|iPw?nQ96 z&LStomDIj>rRZRMJ7tfwk?wwdlEen>XacOQw#q)`si{l~&qy(kL45e(|)Yullz&}`6~>=eiS4cTk%qUjEeKaZuQ(xMn0lD!*i+u%lYc!GMTjI_WRgu*E7X63MHi z!=c;|+i85Sn^)nQmlfi%HmAaZ%>kX$CG(N5t>Z!ykbHMa@J)iZ|NVYw3@SC2rX&+a_>#g z@3kY=t%4^Vfwva=mo33(gqJ7sjZNZ~i_h&n$-r@Yt?(#oUxjF*ywThkyCJrpB;l>C zc6aREuhz)C`o#1DhmK&>;gw9ct6*Q2a^#b|1{s$61@gB2+cIPvJ~WWg9HL(_k!DyZ zDYU|i`qCM($ z2q>3;79%ootO(|qt)*fxC|uTI6A#(*DvWEWW5p&qQEg$P4j|y@ z{aJJa)uEdH*X_kpW11sn{-KXu!4g!u3Kbz&Sr*PY!ELHDr7>Jo>+8sGDBjWti7byg zmndD<^V56(V27)EYB}?kfP*4`>@LAjO}1_T_JR#DH7H0 ziFk7Pgq{l?mwmT2*D;f2)0Y06)j#>f;GP1-E^p|YS14DH9?5X4=D^DS3v%*6)lN*| zQr@Wu4R9nfT2Csk$TAido=Qw~eA^dtCNu2~7**uGz- zbi~(>wxFFbf%TMeSe_u3Bz|0~d1t)r@Qtc?;bu`E6_pOh)+4k3T&aKP8ud)oOWoDp z^;4&>#q-~j+8R2fLR6drKXwt50IUY*d@6edd^o89ea+zGo8fPqu06{74Do*~rOP6F zP<@;(>60V!mbQ9 zW?xG1@)R>Dl_YG?2E7PHFj%nts@AU8@}Fb_!E!mqlU*--i^`sl_Ysq8 z760Zu`*Q65nM@F7V0sYB4#LBL#?`#}e=l?HDkh%bxn=dmB5dGV+?c=#)II@@*s;mQ zKe(1M?*W|UdC6h|_RnEZkZOFmYgLhv=m?HTm>O^SKWq;j5UNM zHCZyG0A^wFj6&J(macZKG`iz1eWC@Lgl!bd6^RY4c$j-{zxgFTjruB#6)bDDkRh!u z+a%3U4*BXQKS^e4sFl29eB8k`c9@lj+j-_3t%@RQBhaV^)j389|155$ugp=x|^hbKy9& zQ0~0A8MatkGLasW9%vd1IAX9$>jrLn*^_kFgOZ_dcE3LpJ4yO|H?JL0Z?3?Pbu|Dr4sjtBo8<8NHs1^yTUCwi681PY0) zKm{2L{1s3vb~si76obWUo1c$|!$p3-E1;NFc;kpy*G0cEZ1hS#Y3_*NnP2DG(+~b? zuLgROF|FQg`mxJgCrjj$x*-PNA<%HdYpG?HR;`MKCXk2iACx8imw=YIBUC|2GNJ#WJ^&hE)xSmU~K16rPIGOmZ^xA$C^1x&M+Ay?0I-?|&BsJZ~cu>K6 z-R9IBXhQ{ zgwHJP?a4LVYYpThCgdQa)BB{I$Q_*QHprcM09-#b`s)e5*u6m|y>n~p`k>6zsAOkc z$7u7J5d>lbs9G3WWne2_v~|Hgkz^x0o~6dY7-={>XV7z9i=PSN#h%)BIlXBfexx=0 z%?9B+Lff9)fc+2;qchF$2@%QQz%#gdFuS4!f!sZykV}tN*NPwlZsDy=g}DP=Fe#YX zcBuTptGCS*hF<-IQIFf$v9AL{fU*uCjQJIRI($Ln8nIeji9hlvaU}0(aY`Tea-ppB z<#bgcv#0mFr52Uvza2CEFe6$?(w_(JT&54x|FqD<5r9{tKe#~iPrug71p(yS*E7stW7d!4L+z8RGY%Q%cb zzVzHGRjc+Lddr9)du|VYYT>H5TdqqZr{a#peTqLohN^$eY2FNM$vXuh2-q`aVq~$l zSBs}WjW+lyov#-6!1ZVry|@SafpEfYI%WgG1d;^pZnK|VHd1lLQe) zNr7C_hVt@8mRDM5!c~@6=}_KBW*JzE^Yod#hniVfs@^YF)Y01Ppc1jaEAKAu_a#XH z%IQS>E?|A)Y)wF2fO0rVxC@k?=zk_+cEm+Vjc(*Q;(B|v*U7UHKQ6UoQztKtYw(jk z5I!S(*TzG*K&+A#(OOe3rLO)n?zhnA#9Sm%A)VwwyzvEDz7h#H@gmCk)D~lVEJRnL zA}!Un2BxCNkb{yo=Ol#qaYD9+j}+AN&7bmi{XKef&YV<&21Px420vhbaMIUfdqdjk zgd;tq|L0o+54mv07P2v^WY+)vk^lb0^pfZ1^M8lb-UYpjL$k%h#)Eo%A`U5Y3L;u# z5mo0~B#qvfoOJlr?!*HaDN=f1r_RJb2#=(HOa?E~#eMm>)>}MIEi^Z3YmprzmrDs~ zg2Qp()XA+^pT0|9?*5Ey$ih8xdUG|kNAm+YfO}fXQLlOyI(C;-i>p2=i9o%sJ=O?&b!2{01j5~y($xWq36o{OCuaInzl3jX6XCgcyyP&Tyc!@uVQcCG(@ zLS)H9dtob)sK7>tWHnraNG%c#o| zq&!dX>+1|O9zKA>zwN~)c|A6lbG3RH#qQjajV06Dq87ait^yRXL4Xb7kx~Y>NVp?L zFM{gd`|?hzZ37t`Xejo`Jp=1>F6&Ve2Xn+&tcv$&9jh8LywUQq3g#W_oUZ1>niTA)}(@Rr)%w6dtb!&v{r;Yy_T`7-t1dxt|#}%q!uuqQZ}Q))(!3 zy0&w#t~zAPIh5G^B8b`%(}9s_Ln&cp1V|H4+_+s`^!(ZH@iJ2i>Fwsag?f){J%7(E za76@dYbnTLgdUKET^|3^kcEAHF0|)q>yeFhS_RGSL`Qb329|CAFsEVx7^f51!?(w8 zPT(1vg<4>@x8pzW%>Vl($Hslic^DIu8?@yfFz`p~{*69yDlYghGP>1%QYv?f;uHU9 z&!60tw+PE|4;0oOkKx-dud2*cks7?vdE3Q+0v#bDHS_BPb!gjGJJ0nlezA zYLOs5AUXu`Z4QceE_=Bw>%8#t>f#XE6s8m78?gnZI{G*CvtR$M|5a`C_ufpElW&2V zZX~d>B!q;WVe?)#_oNxWx|M*LL+Ydm>YpH0?@#F@94J1#g@5tixHl;ovb@dmhy z6trpq?XB>C{Xg)VevOOM{Y*fwf1t8QeSWy3f<@hriz7<-rq_^BL`HofA|XJn z{3aD)hwb02Ko)C!bonS`d7+`&+e7>nuP~3CmCQFe^xt~V^mNVm@q*0zh{*H-PvA-% z5axpiY^S!C@cj~ZfA*xC>P@FSUKeS($v`J8Jx`vNtY=62shFqpJ3Ps_LFmTO zz~S4ML0^|V4=43CPAaI|f)K*VEfysf13_}JoKWlT-hgR1y zAu#J6i1%Jq_e%{!aDVV}<|IG<#UsJi+2O{Qm)A&uBvT@wvDo9!ySm5ANIA4^H5LTW zxV`I4GZr4yiAq_>atgc6^DArsCvm;%9tU0_q^@Jy&K)^HS`m0DD+cty z-Q<16lc8cj9~4>2UU%=o9?J1=K*ywhEGbi#QhMACen2A6+Z{H@ESG&e%A-(u@nwiu zD~P>vOg3%sLX4msw}AA7)$&pWz0p*7H<7<#p~h%sTyn=_d^PlsV21zb8i%9;jT zZHZGOMYk50(#tTC792Ac8a z-jfrA4I&d=5mFO)BU?H%hdc6K?(VFlKa7dSFr=|K;J*i>K-)9iNmdg9EYUaS^8B_LXVm;(SAaGHQGg90>z-$nPEaH&&F|kb|-FI&n z-#uq00pjyLdkPbjHtH!!57NdSJS%&i7Wyx2-;cmfjg8joSatFpoo~VbjeyG-c+MFX zIt$NNC3^nb{noR}U>qczie2nUiQeVp1yJ)5SB8D~ExE+Q+BbUL8O*R8O1EaF0mMkh zvwu<&_=oenk$(^P@KHzT_Tn9Rob-QEehIzc)@m9(q@y|peu#KzB#}-hLwA9cxac<#pEq0$O}(-P#>%pw1-8IUS7WXoeXEBSL8CXfBn^ZnsF_oDE&t7K;{o?)RM}rqoLc9FO`uNX?9z{ zB=bvd&}@@(&t#_dbw3lhQU3bfw8m_i5IvBI1a>FB3OTt1Sd7IAR=chWK5yJ|oB3@O z(f?Q-D6yb}2!WCu-h(OkWC&=P3~I&hY}*ake2A}v0$w&r{Iq^Y0|Y-S1NGjHUtiVyE1>2YjSt^1EzU#4ntLG1x z`6amh79qJ%tAjwnPl)|_$xNONViwcgI|Q3Ux0kZ~K>opnkMw?hOZ)?d{Ch6+jN2xV zDaX8sllpQgDg^#4&=8^$LCHLPB0wg1Yxwa59f#!Cb+!ke!bNj0`;}RC79JJmNs3l_ zp%wo>uD${&%I=L<1xY1DO27qa5b2HultvIKkyvRFkW`u#X{5UmDQS=nSvsYW6zT5X zh24Gc%lCc%duQ(Kj5=ezd-m)(&-1IN$*qGbKU9#+A4iK=2Ip{~5!2NMk#ObEV{G@^ z#9;_2)@$<%v9?o94FE{p3~184Q*<9(hXIR)~Xd^q355@Ail3V!ITYv&x*feE58x{G!CN-(>MN*(4zUCN!^9=* zxZ|PhBf)(Qd^Fz=fA0ysHjn7i z6Q+s|C$97`t$S0*(=|9h#|c?MQJb`?cD21Mbhdm>^_l_riEWx1Xx7|NK$aU9)JmOA zXpdbKwJ3L&Q~hxU+#mkkcnEz0Zm4*vlVEG2Q{Zr^W6c_h;oJ`D&o0Y;j~WPpmUnP9 z?9Vsa=rm($c7DecWFjL@yBeZye^&cG+S#S8Da|=7brSxRFeT>(S}6NOFkk~XZobp< zflm*sOQLm|#v!6v2JE|0LYd?kN{X0$-AVEez8`XJU5FiaxDKPSDX*@Kt?%|wl|ipi z!$O#kC3=5|@Ga9OOLNdp$WFjzScX`_Iy zZ2o27CQ}N!XR%XTI#wa~)aP%DPnvhAu5}jtyaA29KqMJA)#ovF6#5?&Q>jX??D3LZ zZygKrZ&>}7ycRM~Q!b-NUY4NL zkYU?`1&GtV%Vap{4oJ+p7L^2{-6A<@T3L6tf^^Harl08IERxFm$fO9XL25MiBPOFx z5h7x*e7upS^Hb((Q$M{fRIT*z4z;ym#-!+9%)U|>D3F9u1|h;4DK;^80wgK~Dd$sB z`c8C2>WVu+&j0;6H!}sgfMhaD9N$b?X_br@9HJFNwIQ0MS9*`6%ipoqt)--DcfKl0 z`AI7r0n7uvzo(3H4qjDC9d0dmWetq+B6M7jcSk23U*soovvV)W?ox=8-JH+X-Bcg+ z!!g9^7Yj)!7KC0Zi)0(8w7N`vvd%4_p;4F0S)e2j(KgC?4_v?jb|XUCc09Ws3H$A) zAMgbe8^%u*GZW-11Xrts`~r;o8V4SjJ#<6pvmX?293%&Xm&);nFfqQU8nU$i?5wppt@>LXALQw2M%heMUYc11V%=v!P_-a|x z{>N#YXm`LR&{!bs#Ny9%-Kw?YtG&NfhF45?i&e`z-ql=Tmt;`jR_6uh2Ix2T^=&c3 zgZzJ8)IT<=kllxaeox9m*%y^hl8l3NeGy5GA9gss-xEqKZu`B8+2mlO#QZJ-Z*1x( zu4hVX@0+(2)BVJHE?TZs6yQFK->-98he$7q-r!=XQqDgwYjZa@d_ zn;dYz$btg2Ge&*HR8OMu_q|#(3=0GERFa+~6+Ue?kq*vcg*}cb#y8>ViDHPFEhl+~ zxD_)K`B0h*IE{l0(3M9;E&|+_w#W+8*Ic|%>=Cr@yS~y*p*Jp{Hc*J2wWI+U%!5@` z$;9)p4Sx-Dv2ao2y5}(8m>_ku8rOb8US7W(#v$#n`2u~C1q4X;09n}!2VRT5r&sSH z%t22_*3HbN&hC>~R#@+E{icsyTMliXJzf$Q3#mK>hb6?2UqnVXuf+3|)LA7Ezcyxc zTksJbI!@;_?+%w^G0DI~t$1=a0Mak-TcOPkHGiT-(UOr|+!$M=C|dg)9VQ_HV~Yj> zLJ%VC0UP@TBvPqI?x-y|0&a)4URltV0p9+<9_F8BMvm?hbx|E2{`m2&XSl)^f95)c zl;d~u!%sg{Xs77R<0wZbevw>{y6vNRTPZq!bX< z*#D`|_EQk-@29NX$;i=y)7a(3o;p6u*}vlAj*+Edv#=aR9$J30Wc1<{oSl+eSC%Lk z{+{6y3Y;{>V-EBf*$yxNK!A`0pQyJ^(Cc{nG$dC$G=9OlDw=wC(rlt##%EZx#5Z|h!oy>$TkKFI)CCLDWv zek|TYn9)F3?6N*qpyWPg&mn8FiVP()1gBurXgx2muP(YDi-UKX)TP$4%8qk;7S>|a zDD-~p*<`r^826=JkiFn%{dpnZeV<*jvgRH39Okw6;aIZz%bxY?x><^1GRzbnD129T zz5}eXLt_xwvvTDvW#MW-y$>=eh^udHH2erl`eCJfl6MlgX&x$6c008;;5bQK-m$@{ z<~)lZV~r%8p#DAs-meG0X0onb%QtayZ-YoXc$NvHY*$E?+XeXm^GngUkgDqo_8+YK zzn)j0b`BgGf=TD{XV%#P@Ww6xe`(C#ZKqf!NXQvIi^x9+nr1#gSP4DgF0L{ zRB~e6ytm&A8ni~z$L{U#i2nFK?bXt{g;-r~{l5MArnNsVbZP}dN&Qgt{DRtDv82x) zHK5se%S8b)gMcFv>7K9?!@#N9(oUTIU|$U1WO#bI+c<)apcCmgu{%o+Qo%}y#YJxP z@dubJ4~|)?eOQ}{$x(W_ypZ9yDPg_v7t`3akvZ@6#UAc|>4^Q6LHFWGl$mYcMy8j@ z=PU%!P-?T%9dQQ6O3Qq%hMx*s#MLrAZ4;01&M`PG~Bvt=yS%3Df1RY)c&>X={~t28Nn8&lp+mH(^1f^;rntnX(q zw_wgIp9EJXbdYQ0prVhIccw}&j~MOCQ2@NtSt5q*zjZm=PHtdNjXL4XL4kr~2F|Ic z-Kqni1LvK=(ExXjV&9r^Bgc>ld{5Y8Q;AgJ&|scRx2QL^OYM7H4SiW|^Fa%I#H-6S z?0jPbxICk~HSD@BQR1jJYVCul(!rY)I7QSFYbXaPjU2$AA%f4xXBys)TDy1rI9~O? zfPxiEaHFpnF{+&7()>z3qz-zDaQMbXxaXE^7HQL5eLrLG02)@f z_gp4Ee%yxVzsH&y=W!gtS7)gl0IDzmAZY^aZRUE7IEok#PeMZoB}gq zfay8unUs5V_`gMd4v0&FJPVEpw)%)Yh(rWXjtlTSGL!LpKTW(uLMIP6Nbm` zA@!w@=WgATx#f?1=&}1hy=3Wrt=RfyxlZ2wP^eYqc^|l>D<6pRCD_nwEyS{AzC(eH z$5)&8xj0(-jNeM+58(zILjpt^f}{q-b9aNY%A}rAj14dmotA%>|MuYbd`e`%;pNWv z;V9qxzk{5fQ=wz8n?8-RQT~zmN^FVK6yf;;G+=c&b&3A+c(NPQEJz{iHQMhiVh z5X*Kt>a0z`5N{!@iX5_m*0~3;&*pYf){|ia2v__zARK5$_(m85~v5 zmE}*urk=`D9)4N8I};(uJ`fFreM30-qbtw-T_donEI=SOU(+u z1GJhEo{}EfA>CY+jA%e=D+SHO&X|nG%tnHjQ3_TN1N(TQd3|eLzY5nEzKOqdczYbY zLW1`XVHp>A%_1USM}U;&W+zQqa>JCaIoFu`F>MZCLQkkxN$uzdt!;+ZcM3x^f=I}a zveOw8gKCW91RW2nY7xa?J)ds8#=^2Q(IO(alq5~qHlOv0$&Xifrw7BI&kSroe<3;< z$3>LPLhsK>%3QuRyS?{Wv(I7lhU}-f}Zxrx>9)N9T+F7X#Cx zJzPF-`d-IifJGeAekk@3BFyVD46Aq%*=CSJ1iZRYa3?2p^f|=)Fk1=(144TyPWAms zp3TpWQNmXuL>sG)qwDxCy>6VLnDpvyBTuM*C7Jg`a_X)Im#^-~B>+W_gp5kz~9 z6Yv2`*<+X{kQiZ^D{%{cUX`_j+14!v`-VuI0h-bff3QkU=k2qLE0Dl9)6ryMzzbd; zhGShyMRPwHxsHM`=0+LCGJt;ozk!L=4Unn-II8koIrO{-#k&Y}kV2m|WopDie|_A@ zc)G?8oDRRNd1t8~`KULcAaEJPVHHa{>7RUo!U9rzR>MR_YO-w3NRq_7yA_u1_d>wD zC;cDHTC^CynQ$O17UZuUZ4nFkVD>cQ05Nn4HT$y9kGPOxmh!?#d^;XuLgp4Ih*k zn42-Ng@cI47L7iWBSgdwjWyjvC#*3s4XnXgv}u}6524KwZvx#1oy`tm-b)HwGga(r zt*Bs_3OI$r$!&eHXD%nmRmMe((O?L-mh7pg|e5SE6t_l;Us!zsl> z9qr&@P=fq2RiKtMu=HYnvq+!l(y-=TL;*bJfE*gPpz_Tc|0^Tbq2WwqVq@y2v{>4q z^Gv`k3-Q$?A;E&+5v%{AtVObbWziiv-zc^9Irv`9RR4i* zFlD|f?<0K^Kgy7SB=+r2SB`!lcNds@kI?nS>^wtoXNqPosHp(D#kxu9CO;>{Jx5uo z)do(6rW&gNmEe-`r0d=dpQKf!Z1v2YBLo=dgjWkV9fl1%w4g^zi-&Ka9FUriWTa>? zNqX4t%^ZGcZgqghI}Y9-{HAMc7OJoX%YlYSKH}iKmOEX?4w43fMCCYChdh()JGHuz~?KRFw67U@G#q5#3H!X4r7s@>>XsQ@pUy}B9rz`V4?_hUx z$PrThPI0LfU={8xNvZlmXxwN<%=7sY>Xz`2>cfQx7m2RB({f8?usV~*4+r^O1)mqH z4BfUq^FV6)ONgBrg7tUdz#+c4<6`Sn5$0(yNgGjTPxXBB>gs8%Zn55u;1!?l)t3%n zTi7w$hVT)yqsg-5f%;1p{>b;nV}VWE_7gzT2PbRB%MyXj^)ySip;Ghhv2!?2iLB9g z!(@qG(Kol3|A@Q9KLfAB%)uT(`lt2|ias)OK4G@-36a%_MMcG|}titvzB`NmSJ>1A1a}ANMi{v82`|M8r-^j|8jER0>k_^b%y+t?=c(0+2OH zqhze(`-#s@va;tem0#K%AxQSrYrk>lNeT!Jv~a-Qw484ofRqz&+|;KHGWn+Cx-32< zb#OU3s~tSY_G z*8MUK^N>4oe=fG>4fRTl3Xi-`KD-6M;&`>P2Q24392wVJ{p!1Gc3F-NhLA4tN77=w zY|lH1n(m##JMhjbxyUr6A@!FBDc0D~e;06{QO?aWdz zk~em%T&@F8!208N&CE#V9`l%@aFkVSWd6xcV6Iuh+T-paOAN} zueA{tySku+;MxJLGF`yfqDsLz{=^=Pir@it*#{b zguuD;NLoRX;oEZuEjo@!-n*Etr7Zj7VW!XSwdYBJSbj7Gjv{#VUaJUXNpRDYbP*o_1_S+*))b>3k)rmGRf-vbSG%fZ>Ue z&8RTU{wc)~IBN^4^OX;2D#7MF<`rC(!Hw!o^c~71QmfCU&M0 zoP--k>8Lq?X-MGLul@r(#SqguYZ z){IpC0I5uJ+1Zl5v)B1ip;p2PnvsHka!oGQGhuVSgX3 z_K{-u4=mAhD`zs9e3V#C9V`cdzVkh-A0DJX5tzY(r#eMxc&|jHS+fYJcLf!v5m z=HB|+dk*~-dw5jed&t$mqMNnfadTBg ziT3`f#|k|8oX%b#-)SWxQ#_?(N!_s!<^-HJatdjy1OG9 zEdy2*r~3@$c2hvMakKRs7>3N<1W#&Z&MySpumAmq6zRyv3^yz)Y=a<0dFsAKufB<| z0-FX6FEeoYqvUnNgUYulIILT1V{4+XbUm2$z6Qx!v+57#zXSS4K%@dRsZ?=XlI~dt z&LrUhooi7`h_7hDOPrOMHu7-b6A`7528ZY9+vBL}?EBwz%>E%IVHNU!uteu>oouLF z#R_OjG0O@mk!2iILl|VU!9SrH4Jza+K@SMr9_;`^_^?nEviE_kvCL1B`YT|9ZcaLwJdubtjM#>1tVzV`32c-kJba_ruN1B* zK;f0()cnHe(c9N8D+3eRV#qy7*LcLwu2MpV0S0l`XOj*_r1(7_jRWHoVmMuuSr)&b zui)q=^!Zl7mw@3?;VoI$!<6~Z8X2F8z^!9S>*rSt+>{XjlN(7w&%-v_kTCd>HDejq z4@|ZwQ3sG(V=GMPrBTP%MGK$pV%-I(O}w={P1j7nk5}gOSWKqR{BREJu>V+PXEUE) zGf`%YUr#0Oe)y^Sb5-(1;3zC2wPu2rw!itPo9@qfZmNn(CyZ!p;R|mwqx8}nV!yK# zX=|$VuHx$QG)rrhv`PCsjf`0qJaN~}Xrqy$yq93`v_2R=vkfgn&!Vq6>AHKGNDx7{)z>f!Z3 zH79PUUDfX8ndK3+&Jk^m7u3}*d`KOjn9bvj-k5eem8`Wh4m?$#dfY^N_y^CuEJs(& z{gCYPC#5Xg>hNvq>R1)WUV#d(FVsG41Bs{+o=Rcn}WO)_&qkI#` znk_B!8zwIX3W_z{ukOl7X1iZnYw~w)9oS7kCjrZ1;4TmZ=v?Yk;_wy~GrF86-Rrs@ z1vd^|4bbNQ=a`&Ybr@Z7r~(HxWL;Br!OnYeyeK`=gTL*}=GLRw#N2YDT%t zuSdWnjPChxd)fZzmuI<^Q;b9CRmmY(3W>}iwxNJi46r;N)HI0ECDZ+Fce zBmL5FWK|}6xaT8t6zcuoXjb!R5elL-tue*m{`~kDF`<4GhCIrBQUW zLNwNlkA^1-XDo4d`LrzFqt88dq>0;6U@%-YCp{=@c&6girm zD^ha7m#UC7a3o6v-+n?xm}N*3=XhASiV;KE0~Z1>vElxn%_yFT&o$6cEKwY|MRI9! z;45(TqBOAQak%7tnN9ZPMcw-cj0g;vrp+RZ@oHZImG1P$S{wiJi6Aha`j6&jK?E>6 z(Ih+pMH1IQ$j+}w=#uQOWua&~GP#H+uAZ5E+TD;fid*Uhd4$vvLc0vvZ~*7M%+4NDW%Bs3#VOnh+ z)~FHaJZ~ZMpmI>~3O_%|>Obs_S?=!zN34KSg}$KYbi=9VNw|RMUv~;UV{CA(B=3co zW<#KlK~#LVQO!1` z{!qQWP@8RFj)J{^)s2l>1^&B8FAjCGZhG5@mFLZkS~}xq_ff)8$j-?jD9!1P7=EtP zJ{7K0L27+ZBU417J1UD&n_ZJL9-H*or)TRi;&w9;o~4nTEbRf^kkLe341=(OF@vFxW;4MbB;p0}W0=le07aRvRjcG?n_$C6@nVodON9WkgVC_3h}wYF%ms){0| z`WA^`!`Bm0rKp$%?1h8n-C74}`9N{LI7?lkKR zaRxo(x!p7hgw8>_L8L?-i$9ZXhMUSmK;f(;cNGPBlJ-xjPFjK#$OQP1RzM0y$%oRF zMrfSy7gVbw1xs45EtHCl3JIMsJ=es7w;u2d6v{5_0?WHVbxDbOSz@4AAmdsrW&b$Y z>5M{j^68UC!ca6X3&}?PL<4z37yYkR$e#kIFleWZnenRrOXS)>LLBky+W5w^ot^XG znkDsBu1Zk8w4Im(nzf}%4-LSy*}q`S#*pk4V*k+gcNr6pp$X$g&D)zo`F;5jbe7}m z5siVHM=L#kbAoE{nhJ(@YIa()%_tAmrZf?|_z1_wveyl&b@Q%gP8kd_KCToyUVk$` zV+&lG*KYIV-9GH7h(XR&6IvUT#pm=yCJ_Q)NTZs&;*!TkM(~5YJ_$S9rdww-KRl`? z`5W(#`X-JZqlt67JZ3oB&#t;7(kxgH)6=}v!&U%LtD&N&CulRVNnaT854V1et>QsjWs9MnqR53M8?_2! zLH0y^?>y@WmQF^ITi~V$SA@Tb9v8<7UFT!^gI;rwamSRNva{M&Uk{CLoTKQ(yTRyoJZo001 zN&qHqhQg@FFmymK+P$mU!Z#`Hz&qftfZVtELq&MX!Xh2^`W|5<aQE&vp4sE%@O9z)@`o|Fy zNo0q%zxHp;UHhg&V<_;oL6gjpXx?Yig+)|w01khu?onyi8>aRfeA&gsDQu6IM^wBc zx!NQSvG`1>JA-Np#ya^*7NCbW>~8aTrJqZ{I!9^S)XbA>ty#3}KeiGoPUh!W`HdGb z?iSZl4BP7>?VX!5osa0x!hAM`XCv7UmUyoZ%74rOGf3?-#UCXBBdefu1PdA<=-@NR zFLq18^di`=ork>@;9w~5UF3PjYp`4&rC(yTa2)K=TQTHUl}8t%R_MFuuWy9Grw417U)Yx$v4imX(98gv!diCT|KDXqLwoJ`3I5kr64jeX@GXX11S{dy z1KXChuns&3PtOh}T7iXUqS~HF2$

    f58!^%|?&$6%Wuq5Mme@cep37V_|fu!$I62 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

    EI?2yX&$q|M@6T(B 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 z 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 XUi`h~TYTmO{JVPP#^uUO&QJdjh~$oy