60 lines
1.8 KiB
Swift
60 lines
1.8 KiB
Swift
import Foundation
|
|
import TOML
|
|
|
|
extension PHTheme {
|
|
/// Load theme from the config directory (~/.config/phbar/themes/).
|
|
/// If the file doesn't exist or fails to parse, defaults are used (non-fatal).
|
|
static func load(_ theme: String?) throws -> PHTheme {
|
|
guard let theme else { return try loadFromBundle() }
|
|
|
|
let url = FileManager.default.homeDirectoryForCurrentUser.appending(
|
|
path: ".config/phbar/themes/\(theme).toml"
|
|
)
|
|
|
|
if FileManager.default.fileExists(atPath: url.relativePath) {
|
|
return try load(from: url)
|
|
} else {
|
|
return try loadFromBundle()
|
|
}
|
|
}
|
|
|
|
/// Load the bundled theme.
|
|
/// If the file doesn't exist or fails to parse, the execution is interrupted.
|
|
static private func loadFromBundle() throws -> PHTheme {
|
|
guard
|
|
let defaultConfig = Bundle.module.url(
|
|
forResource: "theme",
|
|
withExtension: "toml"
|
|
)?.resolvingSymlinksInPath()
|
|
else {
|
|
throw phbar.Error("Failed to load theme file")
|
|
}
|
|
return try load(from: defaultConfig)
|
|
}
|
|
|
|
/// Load theme from a file at URL.
|
|
/// If the file doesn't exist or fails to parse, the execution is interrupted.
|
|
static private func load(from url: URL) throws -> PHTheme {
|
|
do {
|
|
let data = try Data(contentsOf: url)
|
|
guard let contents = String(data: data, encoding: .utf8), !contents.isEmpty else {
|
|
throw phbar.Error("the file is empty")
|
|
}
|
|
return try load(from: contents)
|
|
} catch {
|
|
throw phbar.Error("Failed to load theme file", underlyingError: error)
|
|
}
|
|
}
|
|
|
|
/// Load theme from a TOML string.
|
|
/// If the content fails to parse, the execution is interrupted.
|
|
static private func load(from contents: String) throws -> PHTheme {
|
|
do {
|
|
let decoder = TOMLDecoder()
|
|
return try decoder.decode(PHTheme.self, from: contents)
|
|
} catch {
|
|
throw phbar.Error("Failed to parse theme file", underlyingError: error)
|
|
}
|
|
}
|
|
}
|