feat: load optional XDG TOML configuration with session overrides

This commit is contained in:
2026-10-11 14:41:11 +02:00
parent 0dce073287
commit 722a225da5
16 changed files with 461 additions and 89 deletions
+21 -10
View File
@@ -2,12 +2,12 @@ import Foundation
enum PlayerCommand {
case help
case launch(URL?, newInstance: Bool)
case launch(URL?, newInstance: Bool, noConfig: Bool)
static let usage = """
Usage: terebi [--new-instance] [FILE | YOUTUBE_URL]
terebi [--new-instance] --url YOUTUBE_URL
terebi [--new-instance] -- FILE
Usage: terebi [--new-instance] [--no-config] [FILE | YOUTUBE_URL]
terebi [--new-instance] [--no-config] --url YOUTUBE_URL
terebi [--new-instance] [--no-config] -- FILE
terebi --help
Open one local media file or YouTube video and start playback, resuming saved
@@ -15,6 +15,7 @@ enum PlayerCommand {
Quote paths and URLs containing spaces or shell metacharacters.
--new-instance Launch a separate player, leaving existing playback untouched.
--no-config Use built-in settings instead of config.toml on a fresh launch.
--url URL Open a YouTube video URL.
-- Treat the following argument as a filename, even with a leading '-'.
-h, --help Show this help without launching the player.
@@ -26,13 +27,23 @@ enum PlayerCommand {
static func parse(_ arguments: [String], directory: URL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath, isDirectory: true)) throws -> PlayerCommand {
var inputs = arguments
let newInstance = inputs.first == "--new-instance"
if newInstance { inputs.removeFirst() }
if inputs.isEmpty { return .launch(nil, newInstance: newInstance) }
var newInstance = false
var noConfig = false
while let option = inputs.first, option == "--new-instance" || option == "--no-config" {
if option == "--new-instance" {
guard !newInstance else { throw ArgumentError("--new-instance may only be supplied once.") }
newInstance = true
} else {
guard !noConfig else { throw ArgumentError("--no-config may only be supplied once.") }
noConfig = true
}
inputs.removeFirst()
}
if inputs.isEmpty { return .launch(nil, newInstance: newInstance, noConfig: noConfig) }
if inputs == ["--help"] || inputs == ["-h"] { return .help }
if inputs.first == "--url" {
guard inputs.count == 2 else { throw ArgumentError("--url requires exactly one YouTube URL.") }
return .launch(try YouTubeResolver.validateURL(inputs[1]), newInstance: newInstance)
return .launch(try YouTubeResolver.validateURL(inputs[1]), newInstance: newInstance, noConfig: noConfig)
}
let filenameOnly = inputs.first == "--"
if filenameOnly {
@@ -52,7 +63,7 @@ enum PlayerCommand {
}
file = url
} else {
return .launch(try YouTubeResolver.validateURL(input), newInstance: newInstance)
return .launch(try YouTubeResolver.validateURL(input), newInstance: newInstance, noConfig: noConfig)
}
} else {
let base = directory.hasDirectoryPath ? directory : URL(fileURLWithPath: directory.path, isDirectory: true)
@@ -62,7 +73,7 @@ enum PlayerCommand {
FileManager.default.isReadableFile(atPath: file.path) else {
throw ArgumentError("File does not exist or is not a readable regular file.")
}
return .launch(file.standardizedFileURL, newInstance: newInstance)
return .launch(file.standardizedFileURL, newInstance: newInstance, noConfig: noConfig)
}
private struct ArgumentError: LocalizedError {