From 61133bf7ec8089d6f3e631a69f35a198cc8c644b Mon Sep 17 00:00:00 2001 From: Soc Sieng Date: Mon, 28 Oct 2024 23:20:55 +1100 Subject: [PATCH] feat: add option to specify arbitrary configuration file --- README.md | 14 +++++----- .../Configuration/ConfigLoader.swift | 26 +++++++++++++------ Sources/SendKeysLib/Sender.swift | 22 +++++++++++----- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index bc844a0..6ca6e58 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,9 @@ _Activates the Notes application and sends keystrokes piped from `stdout` of the Follows a similar convention to `--characters`. (e.g. `f12:command,shift`). - `--keyboard-layout `: Use alternate keyboard layout. Defaults to `qwerty`. `colemak` and `dvorak` are also supported, pull requests for other common keyboard layouts may be considered. If a specific keyboard layout is not - supported, a custom layout can be defined in the [`~/.sendkeysrc.yml`](./examples/.sendkeysrc.yml) configuration file - (`send.remap`). + supported, a custom layout can be defined in using the `--config` option or using the + [`.sendkeysrc.yml`](./examples/.sendkeysrc.yml) configuration file (`send.remap`). +- `--config `: Configuration file to load settings from. ## Installation @@ -338,12 +339,13 @@ application name, followed by the bundle id. ## Configuration -Common arguments can be stored in the [`~/.sendkeysrc.yml`](./examples/.senkeysrc.yml) configuration file. Configuration -values are applied in the following priority order: +Common arguments can be stored in a [`.sendkeysrc.yml`](./examples/.senkeysrc.yml) configuration file. Configuration +values are applied and merged in the following priority order: 1. Command line arguments -2. Configuration file -3. CLI default values +2. Configuration file defined with `--config` option +3. Configuration file defined in `~/.sendkeysrc.yml` +4. Default values ## Prerequisites diff --git a/Sources/SendKeysLib/Configuration/ConfigLoader.swift b/Sources/SendKeysLib/Configuration/ConfigLoader.swift index dc76a07..e956e9b 100644 --- a/Sources/SendKeysLib/Configuration/ConfigLoader.swift +++ b/Sources/SendKeysLib/Configuration/ConfigLoader.swift @@ -1,18 +1,28 @@ import Foundation import Yams +let defaultConfigFiles = [ + NSString("~/.sendkeysrc.yml").expandingTildeInPath, + NSString("~/.sendkeysrc.yaml").expandingTildeInPath, +] + struct ConfigLoader { - static func loadConfig() -> AllConfiguration { - let defaultConfigFiles = [ - NSString("~/.sendkeysrc.yml").expandingTildeInPath, NSString("~/.sendkeysrc.yaml").expandingTildeInPath, - ] + static func loadConfig(_ file: String? = nil) -> AllConfiguration { + var config = AllConfiguration() + + let configFiles = + if file != nil { + [file!] + } else { + defaultConfigFiles + } - for configFile in defaultConfigFiles { - if FileManager.default.fileExists(atPath: configFile) { + for configFile in configFiles { + if !configFile.isEmpty && FileManager.default.fileExists(atPath: configFile) { if let contents = FileManager.default.contents(atPath: configFile) { do { let decoder = YAMLDecoder() - return try decoder.decode(AllConfiguration.self, from: contents) + config = config.merge(with: try decoder.decode(AllConfiguration.self, from: contents)) } catch { print("Unable to read \(configFile): \(error)") } @@ -20,6 +30,6 @@ struct ConfigLoader { } } - return AllConfiguration() + return config } } diff --git a/Sources/SendKeysLib/Sender.swift b/Sources/SendKeysLib/Sender.swift index b3098c6..4e35f14 100644 --- a/Sources/SendKeysLib/Sender.swift +++ b/Sources/SendKeysLib/Sender.swift @@ -44,6 +44,11 @@ public struct Sender: ParsableCommand { @Option(name: .shortAndLong, help: "Character sequence to use to terminate execution (e.g. f12:command).") var terminateCommand: String? + @Option( + name: NameSpecification([.customLong("config")]), + help: "Configuration file to load settings from (yaml format).") + var configurationFile: String? + @Option(name: .long, help: "Keyboard layout to use for sending keystrokes.") var keyboardLayout: KeyMappings.Layouts? @@ -69,12 +74,17 @@ public struct Sender: ParsableCommand { let app: NSRunningApplication? = try activator.find() let keyPresser: KeyPresser - self.config = self.config - .merge(with: ConfigLoader.loadConfig().send) - .merge( - with: SendConfig( - activate: activate, animationInterval: animationInterval, delay: delay, initialDelay: initialDelay, - keyboardLayout: keyboardLayout, targeted: targeted, terminateCommand: terminateCommand)) + // load from home directory by default + self.config = self.config.merge(with: ConfigLoader.loadConfig().send) + + if !(configurationFile ?? "").isEmpty { + self.config = self.config.merge(with: ConfigLoader.loadConfig(configurationFile!).send) + } + + self.config = self.config.merge( + with: SendConfig( + activate: activate, animationInterval: animationInterval, delay: delay, initialDelay: initialDelay, + keyboardLayout: keyboardLayout, targeted: targeted, terminateCommand: terminateCommand)) let activate = activate ?? self.config.activate! let targeted = targeted ?? self.config.targeted!