From 751663bc638358aa2d567c4735e7f1d1d243dd3c Mon Sep 17 00:00:00 2001 From: Bobby Towers Date: Sat, 15 Apr 2023 03:29:08 -0700 Subject: [PATCH] omg it works --- resources/public/cljs/codemirror.cljs | 113 +++++++++++++++++--------- resources/public/codemirror.html | 2 - 2 files changed, 73 insertions(+), 42 deletions(-) diff --git a/resources/public/cljs/codemirror.cljs b/resources/public/cljs/codemirror.cljs index 25e727b..3cffe40 100644 --- a/resources/public/cljs/codemirror.cljs +++ b/resources/public/cljs/codemirror.cljs @@ -1,57 +1,90 @@ -(require '[clojure.string :as str]) +(require '[clojure.string :as str] + '[reagent.core :as r] + '[reagent.dom :as rdom]) (declare cm) +(defn eval-string [s] + (when-some [code (not-empty (str/trim s))] + (try {:result (js/scittle.core.eval_string code)} + (catch js/Error e + {:error (str (.-message e))})))) + (defn eval-me [] (js/scittle.core.eval_string (-> cm .-state .-doc .toString))) +(defonce !viewer (atom "")) +(defonce last-result (atom "")) +(defonce eval-tail (atom nil)) + +(defn myval [] + (some-> cm .-state .-doc str)) + +;; export function to use from JavaScript: +(set! (.-myval js/window) myval) + +(defn update-editor! [text cursor-pos] + (let [end (count (some-> cm .-state .-doc str))] + (.dispatch cm #js{:changes #js{:from 0 :to end :insert text} + :selection #js{:anchor cursor-pos :head cursor-pos}}))) + +(defn eval-at-cursor [viewer] + (let [cursor-pos (some-> cm .-state .-selection .-main .-head) + code (first (str/split (str (some-> cm .-state .-doc str)) #" => "))] + (let [region (str "(do " (.-doc (.-state viewer)) " )") + region (if (nil? region) nil (eval-string region))] + (if (nil? region) nil (reset! last-result region))) + (update-editor! (str (subs code 0 cursor-pos) + (when-not (= "" (:result @last-result)) " => ") + (:result @last-result) + (reset! eval-tail (subs code cursor-pos (count code)))) + cursor-pos) + (.dispatch cm + #js{:selection #js{:anchor cursor-pos + :head cursor-pos}}))) + +(defn eval-top-level [viewer] + (let [region (str "(do " (.-doc (.-state viewer)) " )") + region (if (nil? region) nil (eval-string region))] + (if (nil? region) nil (reset! last-result region))) + true) + +(defn eval-cell [viewer] + (reset! last-result (eval-string (str "(do " (.-doc (.-state viewer)) " )"))) + true) + +(defn clear-eval [] + (when (not= "" @last-result) + (reset! last-result "") + (let [code (-> cm + (some-> .-state .-doc str) + str + (str/split #" => ") + first + (str @eval-tail)) + cursor-pos (some-> cm .-state .-selection .-main .-head)] + (update-editor! code (min cursor-pos (count code)))))) + (def extension (.of js/cv.keymap - (clj->js [{:key "Mod-Enter" - :run (fn [] - (prn :hoeooo) - (eval-me))} - #_{:key (str modifier "-Enter") - :shift (partial eval-top-level on-result) - :run (partial eval-at-cursor on-result)}]))) + (clj->js [{:key (str "Alt-Enter") + :run #(eval-cell %)} + {:key "Mod-Enter" + :run #(eval-top-level %)} + {:key "Shift-Enter" + :run #(eval-at-cursor %)} + {:key "Escape" :run clear-eval} + {:key "ArrowLeft" :run clear-eval} + {:key "ArrowRight" :run clear-eval}]))) + (def cm (let [doc (str/trim " -(require '[reagent.core :as r] - '[reagent.dom :as rdom] - '[re-frame.core :as rf]) - -(rf/reg-event-fx ::click (fn [{:keys [db]} _] {:db (update db :clicks (fnil inc 0))})) -(rf/reg-sub ::clicks (fn [db] (:clicks db))) - -(defn my-component [] - (let [clicks (rf/subscribe [::clicks])] - [:div - [:p \"Clicks: \" @clicks] - [:p [:button {:on-click #(rf/dispatch [::click])} - \"Click me!\"]]])) - -(rdom/render [my-component] (.getElementById js/document \"reagent\")) +(map inc (range 8)) ")] (js/cm.EditorView. #js {:doc doc :extensions #js [js/cm.basicSetup, (js/lc.clojure), (.highest js/cs.Prec extension)] :parent (js/document.querySelector "#app") - #_#_:dispatch (fn [tr] (-> cm (.update #js [tr])) (eval-me)) - }))) + #_#_:dispatch (fn [tr] (-> cm (.update #js [tr])) (eval-me))}))) (set! (.-eval_me js/globalThis) eval-me) (set! (.-cm_instance js/globalThis) cm) -(defn linux? [] - (some? (re-find #"(Linux)|(X11)" js/navigator.userAgent))) - -(defn mac? [] - (and (not (linux?)) - (some? (re-find #"(Mac)|(iPhone)|(iPad)|(iPod)" js/navigator.platform)))) - -(let [elt (js/document.getElementById "evalMe") - txt (.-innerText elt) - mod-symbol (if (mac?) - "⌘" - "⌃") - txt (str txt " " mod-symbol"-⏎")] - (set! (.-innerHTML elt) txt)) - (eval-me) diff --git a/resources/public/codemirror.html b/resources/public/codemirror.html index 5d0f1a7..205f957 100644 --- a/resources/public/codemirror.html +++ b/resources/public/codemirror.html @@ -44,11 +44,9 @@ -

Using @nextjournal/lang-clojure directly from npm in HTML!

-