From 9a37e35756e2f5b9ce76ffa701c58e7d0d6c76b7 Mon Sep 17 00:00:00 2001 From: kamillobinski Date: Thu, 3 Apr 2025 11:48:11 +0200 Subject: [PATCH 1/4] feat: add set-enabled cli command --- Thock/Engines/AppEngine.swift | 1 + Thock/Services/PipeListenerService.swift | 52 +++++++++++++++++++++--- docs/THOCK-CLI.md | 6 +++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Thock/Engines/AppEngine.swift b/Thock/Engines/AppEngine.swift index ba044bc..c704dd7 100644 --- a/Thock/Engines/AppEngine.swift +++ b/Thock/Engines/AppEngine.swift @@ -22,6 +22,7 @@ final class AppEngine { return AppStateManager.shared.isEnabled } + @discardableResult func setEnabled(_ enabled: Bool) -> Bool { print("Set enabled: \(enabled)") AppStateManager.shared.isEnabled = enabled diff --git a/Thock/Services/PipeListenerService.swift b/Thock/Services/PipeListenerService.swift index 8080cd2..61749fa 100644 --- a/Thock/Services/PipeListenerService.swift +++ b/Thock/Services/PipeListenerService.swift @@ -32,6 +32,11 @@ final class PipeListenerService { startListening() } + func cleanUp() { + try? FileManager.default.removeItem(atPath: pipePath) + print("[PIPE] Pipe cleaned up") + } + private func recreatePipeIfNeeded() { var statInfo = stat() if stat(pipePath, &statInfo) == 0 { @@ -97,8 +102,24 @@ final class PipeListenerService { } } - guard components.first == "set-mode", components.count >= 2 else { - print("[COMMAND] Invalid format") + guard let commandName = components.first else { + print("[COMMAND] Empty command") + return + } + + switch commandName { + case "set-mode": + handleSetModeCommand(components: components) + case "set-enabled": + handleSetEnabledCommand(components: components) + default: + print("[COMMAND] Unknown command '\(commandName)'") + } + } + + private func handleSetModeCommand(components: [String]) { + guard components.count >= 2 else { + print("[COMMAND] Invalid set-mode format") return } @@ -142,8 +163,29 @@ final class PipeListenerService { } } - func cleanUp() { - try? FileManager.default.removeItem(atPath: pipePath) - print("[PIPE] Pipe cleaned up") + private func handleSetEnabledCommand(components: [String]) { + guard components.count == 2 else { + print("[COMMAND] Invalid set-enabled format. Usage: set-enabled true|false") + return + } + + let arg = components[1].lowercased() + let enabled: Bool + + switch arg { + case "true", "1", "yes", "on": + enabled = true + case "false", "0", "no", "off": + enabled = false + default: + print("[COMMAND] Invalid value for set-enabled: '\(arg)'") + return + } + + DispatchQueue.main.async { + AppEngine.shared.setEnabled(enabled) + SettingsEngine.shared.refreshMenu() + print("[COMMAND] Thock is now \(enabled ? "enabled" : "disabled")") + } } } diff --git a/docs/THOCK-CLI.md b/docs/THOCK-CLI.md index 78ed338..289d4a9 100644 --- a/docs/THOCK-CLI.md +++ b/docs/THOCK-CLI.md @@ -86,6 +86,12 @@ thock-cli set-mode "oreo" --brand "everglide" --author "mechvibes" ### Examples +Set enabled/disabled state + +```sh +thock-cli set-enabled "true" +``` + Set a mode with metadata: ```sh From f2b5b06e504a0b394adbc376781ce7b82dd110a6 Mon Sep 17 00:00:00 2001 From: kamillobinski Date: Thu, 3 Apr 2025 12:05:33 +0200 Subject: [PATCH 2/4] fix: support multi-word mode names like 'cute sugarplum' --- Thock/Models/ModeDatabase.swift | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Thock/Models/ModeDatabase.swift b/Thock/Models/ModeDatabase.swift index 8f1fc37..2f1863c 100644 --- a/Thock/Models/ModeDatabase.swift +++ b/Thock/Models/ModeDatabase.swift @@ -245,23 +245,29 @@ struct ModeDatabase { } func getMode(byName name: String, authorName: String, brandName: String) -> Mode? { - func normalize(_ string: String) -> String { + func normalizeKey(_ string: String) -> String { return string.lowercased().replacingOccurrences(of: " ", with: "") } - let normalizedName = normalize(name) - let normalizedAuthorName = normalize(authorName) - let normalizedBrandName = normalize(brandName) + func normalizeModeName(_ string: String) -> String { + return string.lowercased() // preserve spaces! + } + + let normalizedName = normalizeModeName(name) + let normalizedAuthorName = normalizeKey(authorName) + let normalizedBrandName = normalizeKey(brandName) - guard let author = Author.allCases.first(where: { normalize($0.rawValue) == normalizedAuthorName }) else { + guard let author = Author.allCases.first(where: { normalizeKey($0.rawValue) == normalizedAuthorName }) else { return nil } - guard let brand = Brand.allCases.first(where: { normalize($0.rawValue) == normalizedBrandName }) else { + guard let brand = Brand.allCases.first(where: { normalizeKey($0.rawValue) == normalizedBrandName }) else { return nil } - return getMode(byName: normalizedName, author: author, brand: brand) + guard let authorModes = modeStorage[brand]?[author] else { return nil } + + return authorModes.first { normalizeModeName($0.name) == normalizedName } } func getBrand(for mode: Mode) -> Brand? { @@ -272,6 +278,7 @@ struct ModeDatabase { } } } + return nil } From 0d4be9f956d1d4696d5183de94df64deec9b4851 Mon Sep 17 00:00:00 2001 From: kamillobinski Date: Thu, 3 Apr 2025 12:49:24 +0200 Subject: [PATCH 3/4] chore: teach the repo how to document itself --- scripts/generate-modes-doc.sh | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 scripts/generate-modes-doc.sh diff --git a/scripts/generate-modes-doc.sh b/scripts/generate-modes-doc.sh new file mode 100755 index 0000000..547938c --- /dev/null +++ b/scripts/generate-modes-doc.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +SOUNDS_DIR="./Thock/Resources/Sounds" +OUTPUT="./docs/MODES.md" +TMP=$(mktemp) + +# Collect entries +find "$SOUNDS_DIR" -type d -mindepth 3 -maxdepth 3 | while read -r path; do + brand=$(basename "$(dirname "$(dirname "$path")")") + author=$(basename "$(dirname "$path")") + mode=$(basename "$path") + + # Normalize + brand_fmt=$(echo "$brand" | sed 's/_/ /g' | awk '{ for(i=1;i<=NF;++i) $i=toupper(substr($i,1,1)) tolower(substr($i,2)) }1') + author_fmt="$author" + mode_fmt=$(echo "$mode" | sed 's/_/ /g') + + echo "$brand_fmt|$author_fmt|$mode_fmt" >> "$TMP" +done + +# Sort entries +sort "$TMP" -o "$TMP" + +# Output to Markdown +{ + echo "" + echo "" + echo "# Thock Modes" + echo "" + echo "| Brand | Author | Mode |" + echo "|-------|--------|------|" + while IFS='|' read -r brand author mode; do + echo "| $brand | $author | $mode |" + done < "$TMP" + echo "" + echo "_Auto-Generated from folder structure at \`Thock/Resources/Sounds/\`_" + echo "" + echo "

(back to top)

" +} > "$OUTPUT" + +# Cleanup +rm "$TMP" From 9bbc5a8e96ab69b782dac158d84c5d031cd1db04 Mon Sep 17 00:00:00 2001 From: kamillobinski Date: Thu, 3 Apr 2025 12:51:56 +0200 Subject: [PATCH 4/4] chore: the repo speaks - modes.md has been born --- docs/MODES.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/MODES.md diff --git a/docs/MODES.md b/docs/MODES.md new file mode 100644 index 0000000..ae2d064 --- /dev/null +++ b/docs/MODES.md @@ -0,0 +1,35 @@ + + +# Thock Modes + +| Brand | Author | Mode | +|-------|--------|------| +| Alps | tplai | SKCM Blue | +| Cherry Mx | mechvibes | Black ABS | +| Cherry Mx | mechvibes | Black PBT | +| Cherry Mx | mechvibes | Blue ABS | +| Cherry Mx | mechvibes | Blue PBT | +| Cherry Mx | mechvibes | Brown ABS | +| Cherry Mx | mechvibes | Brown PBT | +| Cherry Mx | mechvibes | Red ABS | +| Cherry Mx | mechvibes | Red PBT | +| Cherry Mx | tplai | Black | +| Cherry Mx | tplai | Blue | +| Cherry Mx | tplai | Brown | +| Drop | tplai | Holy Panda | +| Durock | tplai | Alpaca | +| Everglide | mechvibes | Crystal Purple | +| Everglide | mechvibes | Oreo | +| Gateron | tplai | Ink Black | +| Gateron | tplai | Ink Red | +| Gateron | tplai | Turquoise Tealios | +| Kailh | tplai | Box Navy | +| Novelkeys | tplai | Cream | +| Other | tplai | Buckling Spring | +| Other | webdevcody | unknown | +| Topre | mechvibes | Purple Hybrid PBT | +| Topre | tplai | Topre | + +_Auto-Generated from folder structure at `Thock/Resources/Sounds/`_ + +

(back to top)