diff --git a/CHANGELOG.org b/CHANGELOG.org index ca5a5ff..a9cc839 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -3,22 +3,31 @@ All notable changes to this project will be documented in this file. This change ** Unreleased -[Unreleased]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.2...HEAD +[Unreleased Commits]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.5...HEAD -** 0.2.2 +** 0.2.5 - 2019-04-26 +*** Added +- ~goku -d~ or ~goku --dry-run~ for testing configs. +- ~goku -c~ or ~goku --config~ for testing files in other place. +*** Fixed +- rewrite some functions the clojure way. + +[commits in 0.2.5]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.2...0.2.5 + +** 0.2.2 - 2019-04-21 *** Added - user can now specify ~.edn~ config file path with env variable ~GOKU_EDN_CONFIG_FILE~. -[0.2.2]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.1...0.2.2 +[commits in 0.2.2]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.1...0.2.2 -** 0.2.1 +** 0.2.1 - 2019-03-15 *** Added - support optional arguments in tempaltes, user can now omit arguments from the tail -[0.2.1]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.0...0.2.1 +[commits in 0.2.1]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.2.0...0.2.1 -** 0.2.0 +** 0.2.0 - 2019-03-12 *** Added - multiple profile support - QWER as right command control option shift @@ -27,19 +36,19 @@ All notable changes to this project will be documented in this file. This change - some macos functionaly keys are set as consumer key, make them can be used in to defination. -[0.2.0]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.16...0.2.0 +[commits in 0.2.0]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.16...0.2.0 ** 0.1.16 - 2019-01-16 *** Added - user can now specify not already defined conditions using keyword -[0.1.16]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.15...0.1.16 +[commits in 0.1.16]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.15...0.1.16 ** 0.1.15 - 2019-01-14 *** Fixed - can't read already defined :layers in :layers pre-defination -[0.1.15]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.14...0.1.15 +[commits in 0.1.15]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.14...0.1.15 ** 0.1.14 - 2018-12-22 *** Added @@ -48,28 +57,28 @@ All notable changes to this project will be documented in this file. This change *** Fixed - error when running with brew service caused by new version of joker (v0.10.2) -[0.1.14]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.13...v0.1.14 +[commits in 0.1.14]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.13...v0.1.14 ** 0.1.13 - 2018-12-07 *** Added - add command to open log file - use [[https://github.com/candid82/joker][joker]] to check edn file syntax, (add joker as dependency via homebrew) -[0.1.13]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.12...v0.1.13 +[commits in 0.1.13]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.12...v0.1.13 ** 0.1.12 - 2018-12-07 *** Added - error message when goku can't find the "Goku" profile - now we support ~{:held }~ ~{:dealyed {:invoked } {:dealyed }}~ in simlayer keys (not simlayer defination) #15 -[0.1.12]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.11...v0.1.12 +[commits in 0.1.12]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.11...v0.1.12 ** 0.1.11 - 2018-10-17 *** Fixed - error while parsing ~{:any :key_code}~ as section in rule - more friendly error message, simply removed the stacktrace of the AssertionError -[0.1.11]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.10...v0.1.11 +[commits in 0.1.11]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.10...v0.1.11 ** 0.1.10 - 2018-10-14 *** Fixed @@ -77,7 +86,7 @@ All notable changes to this project will be documented in this file. This change *** Added - now user can override ~to_if_alone~ when defining ~:layers~ -[0.1.10]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.9...v0.1.10 +[commits in 0.1.10]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.9...v0.1.10 ** 0.1.9 - 2018-10-02 *** Fixed @@ -87,7 +96,7 @@ now predefined input sources is ~:input-sources~ instead of ~:input_sources~ now the brew service log file located at ~~/Library/Logs/goku.log~, contains both stderr and stdout. -[0.1.9]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.8...v0.1.9 +[commits in 0.1.9]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.8...v0.1.9 ** 0.1.8 - 2018-09-24 *** Added @@ -145,13 +154,13 @@ both stderr and stdout. [:i "open -a iTunes.app" :chromes]]}]} #+end_src -[0.1.8]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.7...v0.1.8 +[commits in 0.1.8]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.7...v0.1.8 ** 0.1.7 - 2018-09-19 *** Fixed - use keyword defined in :input-sources to as key -[0.1.7]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.6...v0.1.7 +[commits in 0.1.7]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.6...v0.1.7 ** 0.1.6 - 2018-09-15 *** Fixed @@ -160,20 +169,20 @@ both stderr and stdout. - can install through brew now, ~brew install yqrashawn/goku/goku~ - ~gokuw~ as watch script, ~brew services start goku~ as service -[0.1.6]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.3...v0.1.6 +[commits in 0.1.6]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.3...v0.1.6 ** 0.1.3 - 2018-09-11 *** Fixed - seems the previous release version is not usable, the $HOME variable is always /Users/.travis, fixed that. -[0.1.3]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.2...v0.1.3 +[commits in 0.1.3]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.2...v0.1.3 ** 0.1.2 - 2018-09-10 *** Fixed - typo in rules, seems I spell all "cancel" wrong. -[0.1.2]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.1...v0.1.2 +[commits in 0.1.2]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.1...v0.1.2 ** 0.1.1 - 2018-09-07 *** Added @@ -184,7 +193,7 @@ both stderr and stdout. - karabiner error while using ~:mission_control~ - multiple devices condition bug -[0.1.1]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.0...v0.1.1 +[commits in 0.1.1]: https://github.com/yqrashawn/GokuRakuJoudo/compare/v0.1.0...v0.1.1 ** 0.1.0 - 2018-09-07 *** Added diff --git a/README.md b/README.md index 9be8428..2139169 100644 --- a/README.md +++ b/README.md @@ -69,26 +69,29 @@ significantly as you can create new rules as little as few characters. ## Usage -Make sure you have a profile named "Default" in Karabiner GUI tool. +Make sure you have a profile named "Default" in Karabiner GUI tool. You can +specify your own profile name [using `:profiles` +keyword](https://github.com/yqrashawn/GokuRakuJoudo/blob/master/examples.org#profiles-wip). ![img](./resources/images/karabiner-profile.jpg) Goku reads `karabiner.edn` file which holds your Karabiner config. This file -should be placed inside \`~/.config/\` directory on your mac. If you use a dots -dir to hold your config files, you can symlink \`karabiner.edn\` and Goku will -pick up the changes too. Starting on version 0.2.2, you can specify your config -file path using environment variable `GOKU_EDN_CONFIG_FILE`. +should be placed inside `~/.config/` directory on your mac. Starting from +version 0.2.2, you can specify your config file path using environment variable +`GOKU_EDN_CONFIG_FILE`. Goku provides two commands: `goku`: Will update karabiner.json once. `gokuw`: Will keep watching your `karabiner.edn` and on saving, will update your -configuration. +`karabiner.json` configuration. Run command `brew services start goku` to use it as a service (runs `gokuw` in -background). When Goku is ran as service, the logs are kept inside +background). When Goku is ranning as service, the logs are kept inside `~/Library/Logs/goku.log`. +Try `goku -h` to find out more. + diff --git a/project.clj b/project.clj index 76b9241..c80cc7a 100644 --- a/project.clj +++ b/project.clj @@ -8,7 +8,7 @@ :dependencies [[org.clojure/clojure "1.8.0"] [prismatic/schema "1.1.9"] [org.clojure/tools.logging "0.4.1"] - [org.clojure/tools.cli "0.3.7"] + [org.clojure/tools.cli "0.4.2"] [me.raynes/fs "1.4.6"] [cheshire "5.8.0"] [environ "1.1.0"]] diff --git a/src/karabiner_configurator/core.clj b/src/karabiner_configurator/core.clj index 9031780..32d0830 100644 --- a/src/karabiner_configurator/core.clj +++ b/src/karabiner_configurator/core.clj @@ -25,6 +25,16 @@ (if (nn? conf) (assoc-conf-data key conf))) +(defn check-edn-syntax + "Call joker to check syntax of karabiner.edn" + [path] + (shell/sh "/usr/local/opt/joker/bin/joker" "--lint" path)) + +(defn exit [status & [msg]] + (if msg (println msg)) + (if (not (env :is-dev)) (System/exit status))) + +;; paths (defn json-config-file-path "Return karabiner.json file location" [] @@ -45,13 +55,8 @@ (defn log-file [] (str (System/getenv "HOME") "/Library/Logs/goku.log")) - -(defn check-edn-syntax - "Call joker to check syntax of karabiner.edn" - [path] - (shell/sh "/usr/local/opt/joker/bin/joker" "--lint" path)) - ;; main logic + (defn parse-edn "Init conf data and return new rules based on karabiner.edn (main section in edn file)" [conf] @@ -75,10 +80,9 @@ (profiles/parse-rules (rules/parse-mains main)))) (defn update-to-karabiner-json - "Update karabiner.json depend on parsed karabiner.edn - + "Update karabiner.json depend on parsed karabiner.edn. `customized-profiles` {:profile1 {,,,} :profile2 {,,,}}" - [customized-profiles] + [customized-profiles & [dry-run dry-run-all]] (let [karabiner-config (load-json (json-config-file-path)) user-profiles (into {} @@ -94,38 +98,47 @@ "Can't find profile named \"%s\" in karabiner.json, please create a profile named \"%s\" using the Karabiner-Elements.app." profile-name-str profile-name-str)))) - (spit - (json-config-file-path) - (json/generate-string - (assoc - karabiner-config - :profiles - (mapv - (fn [[profile-k profile-v]] - (if-let [customized-profile (profile-k customized-profiles)] - (assoc profile-v :complex_modifications (:complex_modifications customized-profile)) - profile-v)) - user-profiles)) - {:pretty true})))) + (when dry-run + (doseq [[profile-k profile-v] user-profiles] + (when-let [customized-profile (profile-k customized-profiles)] + (println (json/generate-string + (assoc profile-v :complex_modifications (:complex_modifications customized-profile)) + {:pretty true})))) + (exit 1)) + (let [result-config (assoc + karabiner-config + :profiles + (mapv + (fn [[profile-k profile-v]] + (if-let [customized-profile (profile-k customized-profiles)] + (assoc profile-v :complex_modifications (:complex_modifications customized-profile)) + profile-v)) + user-profiles))] + (when dry-run-all + (println (json/generate-string + result-config + {:pretty true})) + (exit 1)) + (spit + (json-config-file-path) + (json/generate-string + result-config + {:pretty true}))))) ;; actions (defn parse "Root function to parse karabiner.edn and update karabiner.json." - [path] + [path & [dry-run dry-run-all]] (let [edn-syntax-err (:err (check-edn-syntax path))] (if (> (count edn-syntax-err) 0) (do (println "Syntax error in config:") (println edn-syntax-err) - (if (not (env :is-dev)) (System/exit 1))))) - (update-to-karabiner-json (parse-edn (load-edn path)))) + (exit 1)))) + (update-to-karabiner-json (parse-edn (load-edn path)) dry-run dry-run-all)) (defn open-log-file [] (shell/sh "open" (log-file))) - ;; cli stuff -(def cli-opts - [["-h" "--help"] - ["-l" "--log"]]) (defn help-message [options-summary] (->> ["GokuRakuJoudo -- karabiner configurator" @@ -139,49 +152,73 @@ "" "Usage: run goku without arg to process config once" "" - "-l, --log, log to open the log file" - "-h, --help, help to show this message"] + "-l, --log, to open the log file" + "-d, --dry-run, to spit the new config of modified profiles into stdout instead of update karabiner.json" + "-A, --dry-run-all, to spit the new whole config into stdout instead of update karabiner.json" + "-c, --config PATH, to specify edn config file from command line" + "-h, --help, to show this message"] (string/join \newline))) (defn error-msg [errors] (str "The following errors occurred while parsing your command:\n" (string/join \newline errors))) +(defn abs-path [path] + (if (= (first path) \~) + (.getPath (fs/expand-home path)) + path)) + +(def cli-opts + [["-h" "--help"] + ["-l" "--log"] + ["-c" "--config PATH" "Config PATH" + :parse-fn abs-path + :validate [(fn [path] + (let [path (abs-path path)] + (and (fs/exists? path) + (fs/file? path) + (fs/readable? path)))) "Make sure the file is exits and readable"]] + ["-d" "--dry-run"] + ["-A" "--dry-run-all"]]) + (defn validate-args [args] (let [{:keys [options arguments summary errors]} (cli/parse-opts args cli-opts)] (cond - (or (:help options) (= "help" (first arguments))) - {:action "help" - :ok true - :exit-message (help-message summary) :ok? true} + ;; error errors {:action "errors" :ok? false :exit-message (error-msg errors)} - (or (:log options) (= "log" (first arguments))) - {:action "log" + ;; help + (:help options) + {:action "help" :ok? true - :exit-message "open log file"} + :exit-message (help-message summary)} + ;; run (= (count arguments) 0) {:action "run" :ok? true + :dry-run-all (:dry-run-all options) + :dry-run (:dry-run options) + :config (:config options) :exit-message "Done!"} + ;; log + (:log options) + {:action "log" + :ok? true + :exit-message "open log file"} :else {:action "default" :ok? true :exit-message (help-message summary)}))) -(defn exit [status & [msg]] - (if msg (println msg)) - (if (not (env :is-dev)) (System/exit status))) - ;; main (defn -main [& args] - (let [{:keys [action options exit-message ok?]} (validate-args args)] + (let [{:keys [action options exit-message ok? config dry-run dry-run-all]} (validate-args args)] (if exit-message (case action - "run" (do (parse (edn-config-file-path)) + "run" (do (parse (or config (edn-config-file-path)) dry-run dry-run-all) (exit (if ok? 0 1) exit-message)) "log" (do (open-log-file) (exit 0)) @@ -197,3 +234,8 @@ ;; (-main "-l") ;; (-main "--log") ;; (-main "log") +;; (-main "--config" "./") +;; (-main "-c" "./") +;; (-main "-dc" "./") +;; (-main "-dc" "~/.config/karabiner.edn") +;; (-main "-d")