Files
phbar/Sources/phbar/Models/PHPaths.swift
T

71 lines
2.4 KiB
Swift

import Foundation
/// Resolves phbar's configuration directory.
///
/// Searches these locations in priority order and returns the first that
/// exists on disk:
///
/// 1. `$XDG_CONFIG_HOME/phbar` only when `XDG_CONFIG_HOME` is set to an
/// absolute path (a relative/empty value is ignored, per the XDG spec).
/// 2. `~/.config/phbar`
/// 3. `~/.phbar`
///
/// If none exist yet (fresh install), the highest-priority candidate is
/// returned so loaders and block commands have a stable root to resolve into.
enum PHPaths {
/// The resolved configuration directory (computed once, cached).
static let configDirectory: URL = resolveConfigDirectory()
/// The resolved config file (computed once, cached).
static let configFile: URL = {
configDirectory.appending(path: "config.toml")
}()
/// The resolved themes directory (computed once, cached).
static let themesDirectory: URL = {
configDirectory.appending(path: "themes")
}()
/// The resolved layouts directory (computed once, cached).
static let layoutsDirectory: URL = {
configDirectory.appending(path: "layouts")
}()
/// Ordered candidate directories, priority high low.
///
/// - Parameter environment: Override the environment lookup (used by tests);
/// defaults to the current process environment.
static func configDirectoryCandidates(
environment: [String: String] = ProcessInfo.processInfo.environment
) -> [URL] {
let home = FileManager.default.homeDirectoryForCurrentUser
var candidates: [URL] = []
if let xdg = environment["XDG_CONFIG_HOME"] {
let trimmed = xdg.trimmingCharacters(in: .whitespaces)
if trimmed.hasPrefix("/") {
candidates.append(URL(fileURLWithPath: trimmed).appending(path: "phbar"))
}
}
candidates.append(home.appending(path: ".config/phbar"))
candidates.append(home.appending(path: ".phbar"))
return candidates
}
/// First existing candidate, or the highest-priority one if none exist.
///
/// - Parameter environment: Override the environment lookup (used by tests);
/// defaults to the current process environment.
static func resolveConfigDirectory(
environment: [String: String] = ProcessInfo.processInfo.environment
) -> URL {
let candidates = configDirectoryCandidates(environment: environment)
for candidate in candidates {
if FileManager.default.fileExists(atPath: candidate.path) {
return candidate
}
}
return candidates[0]
}
}