Introduce keyword :fn to commands

Allows commands to invoke namespaces that previously caused circular
dependency issues
pull/8524/head
Gabriel Horner 2023-01-28 01:07:38 -05:00 committed by Tienson Qin
parent 92bec506ec
commit bcaec408e6
6 changed files with 104 additions and 64 deletions

View File

@ -58,6 +58,7 @@
frontend.handler.common common-handler
frontend.handler.common.file file-common-handler
frontend.handler.common.plugin plugin-common-handler
frontend.handler.common.developer dev-common-handler
frontend.handler.config config-handler
frontend.handler.events events
frontend.handler.global-config global-config-handler

View File

@ -13,6 +13,7 @@
[frontend.handler.image :as image-handler]
[frontend.handler.notification :as notification]
[frontend.handler.page :as page-handler]
[frontend.handler.common.developer :as dev-common-handler]
[frontend.mixins :as mixins]
[frontend.state :as state]
[frontend.ui :as ui]
@ -293,7 +294,7 @@
(ui/menu-link
{:key "(Dev) Show block data"
:on-click (fn []
(state/pub-event! [:dev/show-entity-data [:block/uuid block-id]]))}
(dev-common-handler/show-entity-data [:block/uuid block-id]))}
"(Dev) Show block data"
nil))
@ -302,7 +303,7 @@
{:key "(Dev) Show block AST"
:on-click (fn []
(let [block (db/pull [:block/uuid block-id])]
(state/pub-event! [:dev/show-content-ast (:block/content block) (:block/format block)])))}
(dev-common-handler/show-content-ast (:block/content block) (:block/format block))))}
"(Dev) Show block AST"
nil))])))

View File

@ -6,6 +6,7 @@
[frontend.handler.notification :as notification]
[frontend.handler.page :as page-handler]
[frontend.handler.route :as route-handler]
[frontend.handler.common.developer :as dev-common-handler]
[frontend.state :as state]
[frontend.ui :as ui]
[frontend.util :as util]
@ -162,13 +163,14 @@
(when developer-mode?
{:title "(Dev) Show page data"
:options {:on-click (fn []
(state/pub-event! [:dev/show-entity-data (:db/id page)]))}})
(dev-common-handler/show-entity-data (:db/id page)))}})
(when developer-mode?
{:title "(Dev) Show page AST"
:options {:on-click (fn []
(let [page (db/pull '[:block/format {:block/file [:file/content]}] (:db/id page))]
(state/pub-event! [:dev/show-content-ast (get-in page [:block/file :file/content])
(:block/format page)])))}})]
(dev-common-handler/show-content-ast
(get-in page [:block/file :file/content])
(:block/format page))))}})]
(flatten)
(remove nil?))))))

View File

@ -0,0 +1,66 @@
(ns frontend.handler.common.developer
"Common fns for developer related functionality"
(:require [frontend.db :as db]
[cljs.pprint :as pprint]
[frontend.state :as state]
[frontend.handler.notification :as notification]
[frontend.ui :as ui]
[logseq.graph-parser.mldoc :as gp-mldoc]))
;; Fns used between menus and commands
(defn show-entity-data
[& pull-args]
(let [pull-data (with-out-str (pprint/pprint (apply db/pull pull-args)))]
(println pull-data)
(notification/show!
[:div
[:pre.code pull-data]
[:br]
(ui/button "Copy to clipboard"
:on-click #(.writeText js/navigator.clipboard pull-data))]
:success
false)))
(defn show-content-ast
[content format]
(let [ast-data (-> (gp-mldoc/->edn content (gp-mldoc/default-config format))
pprint/pprint
with-out-str)]
(println ast-data)
(notification/show!
[:div
;; Show clipboard at top since content is really long for pages
(ui/button "Copy to clipboard"
:on-click #(.writeText js/navigator.clipboard ast-data))
[:br]
[:pre.code ast-data]]
:success
false)))
;; Public Commands
(defn ^:export show-block-data []
;; Use editor state to locate most recent block
(if-let [block-uuid (:block-id (first (state/get-editor-args)))]
(show-entity-data [:block/uuid block-uuid])
(notification/show! "No block found" :error)))
(defn ^:export show-block-ast []
(if-let [{:block/keys [content format]} (:block (first (state/get-editor-args)))]
(show-content-ast content format)
(notification/show! "No block found" :error)))
(defn ^:export show-page-data []
;; Use editor state to locate most recent page.
;; Consider replacing with navigation history if it's more useful
(if-let [page-id (get-in (first (state/get-editor-args))
[:block :block/page :db/id])]
(show-entity-data page-id)
(notification/show! "No page found" :error)))
(defn ^:export show-page-ast []
(let [page-data (db/pull '[:block/format {:block/file [:file/content]}]
(get-in (first (state/get-editor-args))
[:block :block/page :db/id]))]
(if (get-in page-data [:block/file :file/content])
(show-content-ast (get-in page-data [:block/file :file/content]) (:block/format page-data))
(notification/show! "No page found" :error))))

View File

@ -8,7 +8,6 @@
[clojure.core.async.interop :refer [p->c]]
[clojure.set :as set]
[clojure.string :as string]
[cljs.pprint :as pprint]
[datascript.core :as d]
[frontend.commands :as commands]
[frontend.components.diff :as diff]
@ -66,7 +65,6 @@
[promesa.core :as p]
[rum.core :as rum]
[logseq.graph-parser.config :as gp-config]
[logseq.graph-parser.mldoc :as gp-mldoc]
[cljs-bean.core :as bean]
["@sentry/react" :as Sentry]
[frontend.modules.instrumentation.sentry :as sentry-event]))
@ -921,33 +919,6 @@
(when (and command (not (string/blank? content)))
(shell-handler/run-cli-command-wrapper! command content)))
(defmethod handle :dev/show-entity-data [[_ & pull-args]]
(let [pull-data (with-out-str (pprint/pprint (apply db/pull pull-args)))]
(println pull-data)
(notification/show!
[:div
[:pre.code pull-data]
[:br]
(ui/button "Copy to clipboard"
:on-click #(.writeText js/navigator.clipboard pull-data))]
:success
false)))
(defmethod handle :dev/show-content-ast [[_ content format]]
(let [ast-data (-> (gp-mldoc/->edn content (gp-mldoc/default-config format))
pprint/pprint
with-out-str)]
(println ast-data)
(notification/show!
[:div
;; Show clipboard at top since content is really long for pages
(ui/button "Copy to clipboard"
:on-click #(.writeText js/navigator.clipboard ast-data))
[:br]
[:pre.code ast-data]]
:success
false)))
(defn run!
[]
(let [chan (state/get-events-chan)]

View File

@ -1,6 +1,5 @@
(ns frontend.modules.shortcut.config
(:require [frontend.components.commit :as commit]
[frontend.handler.notification :as notification]
[frontend.extensions.srs.handler :as srs]
[frontend.extensions.pdf.utils :as pdf-utils]
[frontend.handler.config :as config-handler]
@ -19,7 +18,6 @@
[frontend.modules.shortcut.dicts :as dicts]
[frontend.modules.shortcut.before :as m]
[frontend.state :as state]
[frontend.db :as db]
[frontend.util :refer [mac?] :as util]
[frontend.commands :as commands]
[frontend.config :as config]
@ -33,10 +31,14 @@
;; almost everywhere else they are not which could cause needless conflicts
;; with other config keys
;; To add a new entry to this map, first add it here and then
;; a description for it in frontend.modules.shortcut.dicts/all-default-keyboard-shortcuts.
;; :inactive key is for commands that are not active for a given platform or feature condition
;; Avoid using single letter shortcuts to allow chords that start with those characters
;; To add a new entry to this map, first add it here and then a description for
;; it in frontend.modules.shortcut.dicts/all-default-keyboard-shortcuts.
;; A shortcut is a map with the following keys:
;; * :binding - A string representing a keybinding. Avoid using single letter
;; shortcuts to allow chords that start with those characters
;; * :fn - Fn or a qualified keyword that represents a fn
;; * :inactive - Optional boolean to disable a shortcut for certain conditions
;; e.g. a given platform or feature condition
(def ^:large-vars/data-var all-default-keyboard-shortcuts
;; BUG: Actually, "enter" is registered by mixin behind a "when inputing" guard
;; So this setting item does not cover all cases.
@ -426,7 +428,7 @@
:fn plugin-config-handler/open-replace-plugins-modal}
:ui/clear-all-notifications {:binding false
:fn notification/clear-all!}
:fn :frontend.handler.notification/clear-all!}
:editor/toggle-open-blocks {:binding "t o"
:fn editor-handler/toggle-open!}
@ -439,38 +441,19 @@
:dev/show-block-data {:binding false
:inactive (not (state/developer-mode?))
:fn (fn []
;; Use editor state to locate most recent block
(if-let [block-uuid (:block-id (first (state/get-editor-args)))]
(state/pub-event! [:dev/show-entity-data [:block/uuid block-uuid]])
(notification/show! "No block found" :error)))}
:fn :frontend.handler.common.developer/show-block-data}
:dev/show-block-ast {:binding false
:inactive (not (state/developer-mode?))
:fn (fn []
(if-let [{:block/keys [content format]} (:block (first (state/get-editor-args)))]
(state/pub-event! [:dev/show-content-ast content format])
(notification/show! "No block found" :error)))}
:fn :frontend.handler.common.developer/show-block-ast}
:dev/show-page-data {:binding false
:inactive (not (state/developer-mode?))
:fn (fn []
;; Use editor state to locate most recent page.
;; Consider replacing with navigation history if it's more useful
(if-let [page-id (get-in (first (state/get-editor-args))
[:block :block/page :db/id])]
(state/pub-event! [:dev/show-entity-data page-id])
(notification/show! "No page found" :error)))}
:fn :frontend.handler.common.developer/show-page-data}
:dev/show-page-ast {:binding false
:inactive (not (state/developer-mode?))
:fn (fn []
(let [page-data (db/pull '[:block/format {:block/file [:file/content]}]
(get-in (first (state/get-editor-args))
[:block :block/page :db/id]))]
(if (seq page-data)
(state/pub-event! [:dev/show-content-ast (get-in page-data [:block/file :file/content]) (:block/format page-data)])
(notification/show! "No page found" :error))))}})
:fn :frontend.handler.common.developer/show-page-ast}})
(let [keyboard-shortcuts
{::keyboard-shortcuts (set (keys all-default-keyboard-shortcuts))
@ -479,11 +462,27 @@
(str "Keys for keyboard shortcuts must be the same "
(data/diff (::keyboard-shortcuts keyboard-shortcuts) (::dicts/keyboard-shortcuts keyboard-shortcuts)))))
(defn- resolve-fn
"Converts a keyword fn to the actual fn. The fn to be resolved needs to be
marked as ^:export for advanced mode"
[keyword-fn]
(fn []
(if-let [resolved-fn (some-> (find-ns-obj (namespace keyword-fn))
(aget (munge (name keyword-fn))))]
(resolved-fn)
(throw (ex-info (str "Unable to resolve " keyword-fn " to a fn") {})))))
(defn build-category-map [ks]
(->> (select-keys all-default-keyboard-shortcuts ks)
(remove (comp :inactive val))
;; Convert keyword fns to real fns
(map (fn [[k v]]
[k (if (keyword? (:fn v))
(assoc v :fn (resolve-fn (:fn v)))
v)]))
(into {})))
;; This is the only var that should be publicly expose :fn functionality
(defonce ^:large-vars/data-var config
(atom
{:shortcut.handler/date-picker