Skip to content

Commit

Permalink
fix ^:hide-source lookup, Mafs expansion, support for adding viewers
Browse files Browse the repository at this point in the history
  • Loading branch information
mhuebert committed Jul 22, 2023
1 parent d69fc56 commit 2c4375b
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 79 deletions.
4 changes: 2 additions & 2 deletions editor2/src/main/maria/editor/code/NodeView.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
(let [ref (h/use-callback (fn [el] (when el (mount-code-view! el this))))
hide-source? (if-some [hide-source (:hide-source (h/use-deref !ui-state))]
hide-source
(str/includes? (.. CodeView -state -doc (lineAt 1) -text) "^:hide-source"))
(str/includes? (.. CodeView -state -doc (line 1) -text) "^:hide-source"))
classes (v/classes ["absolute top-0 right-1 z-10"
"w-6 h-6"
"inline-flex items-center justify-center"
Expand Down Expand Up @@ -271,7 +271,7 @@
(lang/syntaxHighlighting styles/code-highlight-style)
(lang/syntaxHighlighting lang/defaultHighlightStyle)

(eval-region/extension ^:clj {:on-enter #(do (commands/code:eval-string! this %)
(eval-region/extension ^:clj {:on-enter #(do (commands/code:eval-result! this %)
true)})
keymaps/code-keymap
(.of cm.view/keymap cmd/historyKeymap)
Expand Down
25 changes: 16 additions & 9 deletions editor2/src/main/maria/editor/code/commands.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@
(str/blank? (first text))))))

(js
(defn code:insert-another-code-block [{:keys [state]
(defn code:insert-another-code-block [{:as CodeView CodeState :state
{:keys [ProseView getPos]} :NodeView}]
(let [insert-pos (+ (getPos) (code:length state) 1)
(let [insert-pos (+ (getPos) (code:length CodeState) 1)
{{:keys [code_block]} :nodes} schema]
(.dispatch ProseView
(doto (.. ProseView -state -tr)
Expand Down Expand Up @@ -242,14 +242,21 @@
(sci.ns/sci-find-ns @(j/get ProseView :!sci-ctx) 'user))))


(j/defn code:eval-string!
([NodeView source] (code:eval-string! nil NodeView source))
(j/defn code:eval-form-in-NodeView
[NodeView form]
(let [ctx @(j/get-in NodeView [:ProseView :!sci-ctx])
ns (code:ns NodeView)]
(try (sci/eval-form-sync ctx ns form)
(catch js/Error e ^:clj {:error e}))))

(j/defn code:eval-result!
([NodeView source] (code:eval-result! nil NodeView source))
([opts NodeView source]
(let [opts (-> opts
(update :ns #(or % (code:ns NodeView)))
(assoc :clojure.core/eval-file (j/get NodeView :id)))
(assoc :clojure.core/eval-file (str "eval_" (j/get NodeView :id))))
ctx @(j/get-in NodeView [:ProseView :!sci-ctx])
_ (assert "code:eval-string! requires sci context")
_ (assert "sci context not found")
result (try (sci/eval-string ctx opts source)
(catch js/Error e ^:clj {:error e}))]
(if (a/await? result)
Expand All @@ -261,7 +268,7 @@
(set-result! NodeView result)))))

(defn code:eval-block! [this]
(code:eval-string! this (code:block-str this))
(code:eval-result! this (code:block-str this))
true)


Expand All @@ -276,7 +283,7 @@
((fn continue [i]
(when-not (j/get ProseView :isDestroyed)
(when-let [NodeView (nth NodeViews i nil)]
(let [value (code:eval-string! NodeView (code:block-str NodeView))]
(let [value (code:eval-result! NodeView (code:block-str NodeView))]
(if (a/await? value)
(p/do value (continue (inc i)))
(continue (inc i))))))
Expand All @@ -286,7 +293,7 @@

#_(defn code:eval-current-region [{:as this {:keys [state]} :CodeView}]
(when-let [source (u/guard (eval-region/current-selection-str state) (complement str/blank?))]
(code:eval-string! this source))
(code:eval-result! this source))
true)

(defn code:copy-current-region [{:keys [state]}]
Expand Down
5 changes: 3 additions & 2 deletions editor2/src/main/maria/editor/code/completions.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@
})
(catch js/Error e
(js/console.error e)
(prn :s-var s-var)
(prn :meta (meta s-var))))))
(prn ::s-var s-var)
(prn :meta (meta s-var))
(prn :meta-name (:name (meta s-var)))))))
syms))}]
results)))))

Expand Down
9 changes: 7 additions & 2 deletions editor2/src/main/maria/editor/code/sci.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
[maria.editor.code.docs]
[maria.editor.code.repl]
[maria.editor.views]
[maria.editor.views]
[promesa.core :as p]
[re-db.reactive]
[re-db.sci-config]
Expand Down Expand Up @@ -55,6 +54,11 @@

(defn await? [x] (and (instance? js/Promise x) (a/await? x)))

(defn eval-form-sync [ctx ns form]
(ctx/with-ctx ctx
(sci/binding [sci/ns (sci.ns/sci-the-ns ctx ns)]
(sci/eval-form ctx form))))

(defn eval-string*
[{:as ctx :keys [last-ns]} opts s]
(let [rdr (sci/reader s)
Expand Down Expand Up @@ -163,4 +167,5 @@
maria.editor.code.repl user
shapes.core user})
(sci/add-class! 'Math js/Math)
(assoc :last-ns (volatile! @sci/ns))))
(assoc :last-ns (volatile! @sci/ns)
:!viewers (atom nil))))
151 changes: 100 additions & 51 deletions editor2/src/main/maria/editor/code/show_values.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[maria.editor.code.repl :as repl]
[maria.editor.icons :as icons]
[maria.editor.util]
[maria.ui :as ui]
[maria.ui :refer [defview]]
[maria.editor.views :as views]
[nextjournal.clojure-mode.node :as n]
Expand Down Expand Up @@ -102,6 +103,7 @@
{:title "Print to console"
:on-click #(do (js/console.error error)
(some-> (sci/stacktrace error) seq pprint))} (icons/command-line:mini "w-5 h-5")]]
#_[:pre (ui/pprinted (ex-data error))]
(when-let [stack (seq (sci/stacktrace error))]
[:div.p-2
[show-stacktrace opts stack]])])
Expand Down Expand Up @@ -241,6 +243,7 @@
(def show-map (partial show-coll "{" "}"))
(def show-set (partial show-coll "#{" "}"))
(def show-list (partial show-coll "(" ")"))
(def show-vector (partial show-coll \[ \]))

(defview show-function [_ f]
(let [[showing toggle!] (h/use-state false)]
Expand Down Expand Up @@ -292,67 +295,93 @@
(when-some [f (views (type x))]
(f opts x))))

(defn reagent-eval
"Evaluates reagent form within namespace of current cell"
[opts form]
(commands/code:eval-form-in-NodeView (:NodeView opts)
`(~'reagent.core/as-element [(fn [] ~form)])))

(defn handles-keys
"Specify keywords indicating what kind of values a viewer handles.
Helpful for adding viewers before or after other viewers."
[ks f]
(with-meta f {::keys ks}))

(def builtin-viewers
"Ordered list of viewers functions"
(flatten (list
(fn [_ x]
(when (= x ::loading)
loader))


(fn [opts x]
(when (cells/cell? x)
(show-cell opts x)))

(fn [opts x]
(when (and (vector? x)
(:portal.viewer/reagent? (meta x)))
(let [ctx (j/get-in (:NodeView opts) [:ProseView :!sci-ctx])]
(sci/eval-form @ctx (list 'reagent.core/as-element x)))))

(fn [opts x]
(when (react/isValidElement x)
x))

(fn [opts x] (when (:hiccup (meta x))
(v/x x)))

(by-type {js/Number (show-inline "text-number")
Symbol (show-inline "text-variableName" str)
js/String show-str
js/Boolean (show-inline "text-bool" pr-str)
Keyword (show-inline "text-keyword" str)
MapEntry show-map-entry
Var show-var
js/Function show-function
js/Promise show-promise
PersistentArrayMap show-map
PersistentHashMap show-map
TransientHashMap show-map
PersistentTreeSet show-set
PersistentHashSet show-set
List show-list
LazySeq show-list
shapes/Shape show-shape
sci.lang/Namespace show-ns})

(fn [opts x] (when (satisfies? IWatchable x)
(show-watchable opts x)))

(fn [opts x] (when (vector? x) (show-coll \[ \] opts x)))
(fn [opts x] (when (map? x) (show-map opts x)))
(fn [opts x] (when (set? x) (show-set opts x)))
(fn [opts x] (when (seq? x) (show-list opts x)))
(fn [opts x] (when (fn? x) (show-function opts x)))
(fn [opts x] (when (var? x) (show-var opts x)))
(fn [opts x] (when (nil? x) (punctuate "nil")))
(fn [opts x] (when (symbol? x) (show-str opts x)))

(fn [opts x] (when (instance? js/Error x) (show-error opts x)))
(fn [opts x] (when (instance? js/Promise x) (show-promise opts x)))
(fn [opts x] (when (object? x) (show-map opts (js->clj x :keywordize-keys true))))
(handles-keys #{:react-element}
(fn [opts x]
(when (react/isValidElement x)
x)))

(handles-keys #{:hiccup}
(fn [opts x] (when (:hiccup (meta x))
(v/x x))))

(handles-keys #{:number
:symbol
:var
:keyword
:map-entry
:string
:boolean
:map
:function
:promise
:namespace
:vector
:set
:list
:error}
(by-type {js/Number (show-inline "text-number")
Symbol (show-inline "text-variableName" str)
js/String show-str
js/Boolean (show-inline "text-bool" pr-str)
Keyword (show-inline "text-keyword" str)
MapEntry show-map-entry
Var show-var
sci.lang/Var show-var
js/Function show-function
MetaFn show-function
js/Promise show-promise
PersistentArrayMap show-map
PersistentHashMap show-map
TransientHashMap show-map
PersistentTreeSet show-set
PersistentHashSet show-set
List show-list
LazySeq show-list
shapes/Shape show-shape
sci.lang/Namespace show-ns
APersistentVector show-vector
Subvec show-vector
RedNode show-vector
js/Error show-error}))

(handles-keys #{:cljs.core/IWatchable}
(fn [opts x] (when (satisfies? IWatchable x)
(show-watchable opts x))))
(handles-keys #{:seq}
(fn [opts x] (when (seq? x) (show-list opts x))))
(handles-keys #{:nil}
(fn [opts x] (when (nil? x) (punctuate "nil"))))
(handles-keys #{:object}
(fn [opts x] (when (object? x) (show-map opts (js->clj x :keywordize-keys true)))))
#_(fn [x] (clerk.sci-viewer/inspect x)))))

(defn add-viewers
[ctx key viewers]
(update-in ctx [::viewers (repl/current-ns-name ctx)]
(update-in ctx [::ns-viewers (repl/current-ns-name ctx)]
(fn [x]
(-> x
(->> (filterv #(not= key (first %))))
Expand All @@ -361,7 +390,27 @@
(defn get-viewers [ctx]
;; added-viewers are added in front of builtin viewers,
;; most recently added viewer takes precedence
(into builtin-viewers
(into (or @(:!viewers ctx) builtin-viewers)
(mapcat second)
(get-in ctx [::viewers (repl/current-ns-name ctx)])))

(get-in ctx [::ns-viewers (repl/current-ns-name ctx)])))

(defn add-global-viewers!
"Adds viewers to the global list of viewers, before/after the given viewer-key.
See builtin-viewers to see what viewer-keys can be referred to"
[ctx where viewer-key added-viewers]
{:pre [(#{:before :after} where)]}
(let [!viewers (:!viewers ctx)
viewers (or @!viewers builtin-viewers)
i (reduce (fn [not-found i]
(if (contains? (::keys (meta (nth viewers i))) viewer-key)
(reduced i)
not-found))
::not-found
(range (count viewers)))
i (case where :before i :after (inc i))]
(if (= ::not-found i)
(js/console.warn (str "Viewer not found: " viewer-key))
(reset! !viewers (concat (take i viewers)
added-viewers
(drop i viewers))))
ctx))
32 changes: 19 additions & 13 deletions editor2/src/main/maria/editor/extensions/emmy.cljs
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
(ns maria.editor.extensions.emmy
(:require [emmy.viewer.sci]
[emmy.portal.css :refer [inject!]]
[emmy.portal.css :refer [inject!] :rename {inject! inject-css!}]
[emmy.viewer.css :refer [css-map]]
[promesa.core :as p]
[sci.ctx-store :as ctx]
[shadow.lazy :as lazy]))
[emmy.mafs]
[maria.editor.extensions.reagent :as ext.reagent]
[maria.editor.code.show-values :as show]
[sci.ctx-store :refer [get-ctx]]))

(defn show-emmy [opts x]
(when (vector? x)
(let [m (meta x)]
(cond (= emmy.mafs/default-viewer (:nextjournal.clerk/viewer m))
(show/reagent-eval opts (emmy.viewer/expand x))

(:portal.viewer/reagent? m)
(show/reagent-eval opts x)))))

(defn install! []
;; capture bound sci context
(let [ctx (ctx/get-ctx)]
;; first install reagent (necessary for viewers)
(p/let [install! (lazy/load (lazy/loadable maria.editor.extensions.reagent/install!))]
(ctx/with-ctx ctx
(install!)
(doseq [href (apply concat (vals css-map))]
(inject! href))
(emmy.viewer.sci/install!)))))
(show/add-global-viewers! (get-ctx) :before :vector [show-emmy])
(ext.reagent/install!)
(doseq [href (apply concat (vals css-map))]
(inject-css! href))
(emmy.viewer.sci/install!))

0 comments on commit 2c4375b

Please sign in to comment.