| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- (ns frontend.modules.shortcut.data-helper
- (:require [borkdude.rewrite-edn :as rewrite]
- [clojure.string :as str]
- [frontend.config :as cfg]
- [frontend.db :as db]
- [frontend.handler.file :as file]
- [frontend.modules.shortcut.config :as config]
- [frontend.state :as state]
- [frontend.util :as util]
- [lambdaisland.glogi :as log])
- (:import [goog.ui KeyboardShortcutHandler]))
- (defonce default-binding
- (->> (vals config/default-config)
- (into {})
- (map (fn [[k {:keys [binding]}]]
- {k binding}))
- (into {})))
- (defn- mod-key [shortcut]
- (str/replace shortcut #"(?i)mod"
- (if util/mac? "meta" "ctrl")))
- (defn shortcut-binding
- [id]
- (let [shortcut (get (state/shortcuts) id
- (get default-binding id))]
- (cond
- (nil? shortcut)
- (log/error :shortcut/binding-not-found {:id id})
- (false? shortcut)
- (do
- (log/debug :shortcut/disabled {:id id})
- false)
- :else
- (->>
- (if (string? shortcut)
- [shortcut]
- shortcut)
- (mapv mod-key)))))
- ;; returns a vector to preserve order
- (defn binding-by-category [name]
- (let [dict (->> (vals config/default-config)
- (apply merge)
- (map (fn [[k _]]
- {k {:binding (shortcut-binding k)}}))
- (into {}))]
- (->> (config/category name)
- (mapv (fn [k] [k (k dict)])))))
- (defn shortcut-map
- ([handler-id]
- (shortcut-map handler-id nil))
- ([handler-id state]
- (let [raw (get config/default-config handler-id)
- handler-m (->> raw
- (map (fn [[k {:keys [fn]}]]
- {k fn}))
- (into {}))
- before (-> raw meta :before)]
- (cond->> handler-m
- state (reduce-kv (fn [r k handle-fn]
- (assoc r k (partial handle-fn state)))
- {})
- before (reduce-kv (fn [r k v]
- (assoc r k (before v)))
- {})))))
- (defn decorate-namespace [k]
- (let [n (name k)
- ns (namespace k)]
- (keyword (str "shortcut." ns) n)))
- (defn desc-helper []
- (->> (vals config/default-config)
- (apply merge)
- (map (fn [[k {:keys [desc]}]]
- {(decorate-namespace k) desc}))
- (into {})))
- (defn category-helper []
- (->> config/category
- (map (fn [[k v]]
- {k (:doc (meta v))}))
- (into {})))
- (defn decorate-binding [binding]
- (-> binding
- (str/replace "mod" (if util/mac? "cmd" "ctrl"))
- (str/replace "alt" (if util/mac? "opt" "alt"))
- (str/replace "shift+/" "?")
- (str/lower-case)))
- (defn binding-for-display [k binding]
- (cond
- (false? binding)
- (cond
- (and util/mac? (= k :editor/kill-line-after))
- "disabled (system default: ctrl+k)"
- (and util/mac? (= k :editor/beginning-of-block))
- "disabled (system default: ctrl+a)"
- (and util/mac? (= k :editor/end-of-block))
- "disabled (system default: ctrl+e)"
- (and util/mac? (= k :editor/backward-kill-word))
- "disabled (system default: opt+delete)"
- :else
- "disabled")
- (string? binding)
- (decorate-binding binding)
- :else
- (->> binding
- (map decorate-binding)
- (str/join " | "))))
- (defn remove-shortcut [k]
- (let [repo (state/get-current-repo)
- path (cfg/get-config-path)]
- (when-let [content (db/get-file-no-sub path)]
- (let [result (try
- (rewrite/parse-string content)
- (catch js/Error e
- (println "Parsing config file failed: ")
- (js/console.dir e)
- {}))
- new-result (rewrite/update
- result
- :shortcuts
- #(dissoc (rewrite/sexpr %) k))]
- (state/set-config! repo new-result)
- (let [new-content (str new-result)]
- (file/set-file-content! repo path new-content))))))
- (defn get-group
- "Given shortcut key, return handler group
- eg: :editor/new-line -> :shortcut.handler/block-editing-only"
- [k]
- (->> config/default-config
- (filter (fn [[_ v]] (contains? v k)))
- (map key)
- (first)))
- (defn potential-confilct? [k]
- (if-not (shortcut-binding k)
- false
- (let [handler-id (get-group k)
- shortcut-m (shortcut-map handler-id)
- bindings (->> (shortcut-binding k)
- (map mod-key)
- (map KeyboardShortcutHandler/parseStringShortcut)
- (map js->clj))
- rest-bindings (->> (map key shortcut-m)
- (remove #{k})
- (map shortcut-binding)
- (filter vector?)
- (mapcat identity)
- (map mod-key)
- (map KeyboardShortcutHandler/parseStringShortcut)
- (map js->clj))]
- (some? (some (fn [b] (some #{b} rest-bindings)) bindings)))))
|