eval at cursor

This commit is contained in:
Bobby Towers 2023-04-15 15:10:09 -07:00
parent 588be7b5cb
commit ceac29690f
3 changed files with 472 additions and 7 deletions

View file

@ -0,0 +1,415 @@
; This is the Calva evaluation results output window.
; TIPS: The keyboard shortcut `ctrl+alt+o o` shows and focuses this window
; when connected to a REPL session.
; Please see https://calva.io/output/ for more info.
; Happy coding! ♥️
; Jacking in...
; Connecting using "Babashka" project type.
; You can make Calva auto-select this.
; - See https://calva.io/connect-sequences/
;
; Starting Jack-in Terminal: pushd c:\Users\porko\Documents\GitHub\scittle & bb --nrepl-server 54728 & popd
; Using host:port 127.0.0.1:54728 ...
; Hooking up nREPL sessions ...
; Connected session: clj
; TIPS:
; - You can edit the contents here. Use it as a REPL if you like.
; - `alt+enter` evaluates the current top level form.
; - `ctrl+enter` evaluates the current form.
; - `alt+up` and `alt+down` traverse up and down the REPL command history
; when the cursor is after the last contents at the prompt
; - Clojure lines in stack traces are peekable and clickable.
cljuser>  ; Use `alt+enter` to evaluate
; Jack-in done.
cljuser> 
"(map inc (range 8))"
cljuser> 
19
cljuser> 
(0)
cljuser> 
; : Could not resolve symbol: cm user
cljuser> 
"here is a string with newlines"
cljuser> 
"here\n is a string\n with newlines"
cljuser> 
"here is a string with newlines"
cljuser> 
"(map inc (range 8))"
cljuser> 
(\) \) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
(\( \m \a \p \space \i \n \c \space \( \r \a \n \g \e \space \8 \) \))
cljuser> 
; : Could not resolve symbol: open-parens user
cljuser> 
false
cljuser> 
true
cljuser> 
(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
false
cljuser> 
true
cljuser> 
2
cljuser> 
[(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
[(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
nil
cljuser> 
[(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
false
cljuser> 
false
cljuser> 
[(\space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
[(\e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
()
cljuser> 
[(\e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
[(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 0]
cljuser> 
true
cljuser> 
true
cljuser> 
[(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
[(\space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
[(\e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 3]
cljuser> 
[(\g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 4]
cljuser> 
[(\8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
[(\space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 2]
cljuser> 
[(\space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
[(\e \g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
[(\g \n \a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
[(\n \a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
[(\a \r \( \space \c \n \i \space \p \a \m \() 0 1]
cljuser> 
true
cljuser> 
false
cljuser> 
false
cljuser> 
[(\space \c \n \i \space \p \a \m \() 1 1]
cljuser> 
true
cljuser> 
(\( \r \a \n \g \e \space \8 \))
cljuser> 
()
cljuser> 
"fart"
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
18
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
true
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
()
cljuser> 
(\( \r \a \n \g \e \space \8 \))
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_2__7886 0x5159d5b4 "sci.impl.fns$fun$arity_2__7886@5159d5b4"]>
cljuser> 
#<SciVar@5cfbb2c3:
#object[sci.impl.fns$fun$arity_1__7879 0x3b25be5f "sci.impl.fns$fun$arity_1__7879@3b25be5f"]>
cljuser> 
1
cljuser> 
(0 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
#<SciVar@5cfbb2c3:
#object[sci.impl.fns$fun$arity_1__7879 0x2a6731c2 "sci.impl.fns$fun$arity_1__7879@2a6731c2"]>
cljuser> 
; : java.lang.Character cannot be cast to java.lang.Number user
cljuser> 
#<SciVar@5cfbb2c3:
#object[sci.impl.fns$fun$arity_1__7879 0x49d5797b "sci.impl.fns$fun$arity_1__7879@49d5797b"]>
cljuser> 
1
cljuser> 
(0 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
; : java.lang.Character cannot be cast to java.lang.Number user
cljuser> 
(0 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
(\( \m \a \p \space \i \n \c \space \( \r \a \n \g \e \space \8 \))
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
(0 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_2__7886 0x7b6273de "sci.impl.fns$fun$arity_2__7886@7b6273de"]>
cljuser> 
; : clojure.lang.PersistentVector cannot be cast to java.lang.Number user
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_2__7886 0x691320a7 "sci.impl.fns$fun$arity_2__7886@691320a7"]>
cljuser> 
; : clojure.lang.PersistentVector cannot be cast to java.lang.Number user
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_1__7879 0x550fb3d7 "sci.impl.fns$fun$arity_1__7879@550fb3d7"]>
cljuser> 
; : Wrong number of args (2) passed to: sci.impl.fns/fun/arity-1--7879 user
cljuser> 
; : Wrong number of args (2) passed to: sci.impl.fns/fun/arity-1--7879 user
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_1__7879 0x223194de "sci.impl.fns$fun$arity_1__7879@223194de"]>
cljuser> 
; : Wrong number of args (2) passed to: sci.impl.fns/fun/arity-1--7879 user
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_1__7879 0x4af3318 "sci.impl.fns$fun$arity_1__7879@4af3318"]>
cljuser> 
; : Wrong number of args (2) passed to: sci.impl.fns/fun/arity-1--7879 user
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_2__7886 0x1941d1ca "sci.impl.fns$fun$arity_2__7886@1941d1ca"]>
cljuser> 
(["(" 0]
[["(" 0] \)]
[[["(" 0] \)] \8]
[[[["(" 0] \)] \8] \space]
[[[[["(" 0] \)] \8] \space] \e]
[[[[[["(" 0] \)] \8] \space] \e] \g]
[[[[[[["(" 0] \)] \8] \space] \e] \g] \n]
[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a]
[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r]
[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(]
[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(] \space]
[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(] \space] \c]
[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(] \space]
\c]
\n]
[[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(] \space]
\c]
\n]
\i]
[[[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(] \space]
\c]
\n]
\i]
\space]
[[[[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(] \space]
\c]
\n]
\i]
\space]
\p]
[[[[[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(]
\space]
\c]
\n]
\i]
\space]
\p]
\a]
[[[[[[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(]
\space]
\c]
\n]
\i]
\space]
\p]
\a]
\m]
[[[[[[[[[[[[[[[[[[["(" 0] \)] \8] \space] \e] \g] \n] \a] \r] \(]
\space]
\c]
\n]
\i]
\space]
\p]
\a]
\m]
\(])
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
#<SciVar@7eff9d7d:
#object[sci.impl.fns$fun$arity_2__7886 0x7f53a803 "sci.impl.fns$fun$arity_2__7886@7f53a803"]>
cljuser> 
#<SciVar@5cfbb2c3:
#object[sci.impl.fns$fun$arity_1__7879 0x79bec427 "sci.impl.fns$fun$arity_1__7879@79bec427"]>
cljuser> 
1
cljuser> 
(0 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
19
cljuser> 
(-1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
(-1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
(\) \8 \space \e \g \n \a \r \( \space \c \n \i \space \p \a \m \()
cljuser> 
18
cljuser> 
\)
cljuser> 
-1
cljuser> 
(-1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1)
cljuser> 
(-1 -1 -1 -1 -1 -1 -1 -1)
cljuser> 
8
cljuser> 
(\) \8 \space \e \g \n \a \r)
cljuser> 
(\r \a \n \g \e \space \8 \))
cljuser> 
(\( \r \a \n \g \e \space \8 \))
cljuser> 
"(range 8)"
cljuser> 
"(range 8)"
cljuser> 
"(range 8)"
cljuser> 
#<SciVar@7d35902f:
#object[sci.impl.fns$fun$arity_1__7879 0x5d4dcb1e "sci.impl.fns$fun$arity_1__7879@5d4dcb1e"]>
cljuser> 
")8 egnar( cni pam("
cljuser> 
"(range 8)"
cljuser> 
; : No reader function for tag js user
cljuser> 
; : No reader function for tag js user
cljuser> 

View file

@ -16,10 +16,27 @@
(.dispatch cm #js{:changes #js{:from 0 :to end :insert text} (.dispatch cm #js{:changes #js{:from 0 :to end :insert text}
:selection #js{:anchor cursor-pos :head cursor-pos}}))) :selection #js{:anchor cursor-pos :head cursor-pos}})))
(defn parse-char [level pos]
(case pos
\( (inc level)
\) (dec level)
level))
(defn form-at-cursor
"Takes the string of characters before cursor pos."
[s]
(let [run (rest (reductions parse-char 0 s))]
(->> s
(take (inc (count (take-while #(not= 0 %) run))))
reverse
(apply str))))
(form-at-cursor (reverse (take 18 "(map inc (range 8)")))
(defn eval-at-cursor [viewer] (defn eval-at-cursor [viewer]
(let [cursor-pos (some-> cm .-state .-selection .-main .-head) (let [cursor-pos (some-> cm .-state .-selection .-main .-head)
code (first (str/split (str (some-> cm .-state .-doc str)) #" => "))] code (first (str/split (str (some-> cm .-state .-doc str)) #" => "))]
(let [region (str "(do " (.-doc (.-state viewer)) " )") (let [region (form-at-cursor (reverse (take cursor-pos code)))
region (if (nil? region) nil (eval-string region))] region (if (nil? region) nil (eval-string region))]
(if (nil? region) nil (reset! last-result region))) (if (nil? region) nil (reset! last-result region)))
(update-editor! (str (subs code 0 cursor-pos) (update-editor! (str (subs code 0 cursor-pos)
@ -27,9 +44,8 @@
(:result @last-result) (:result @last-result)
(reset! eval-tail (subs code cursor-pos (count code)))) (reset! eval-tail (subs code cursor-pos (count code))))
cursor-pos) cursor-pos)
(.dispatch cm (.dispatch cm #js{:selection #js{:anchor cursor-pos :head cursor-pos}}))
#js{:selection #js{:anchor cursor-pos true)
:head cursor-pos}})))
(defn eval-top-level [viewer] (defn eval-top-level [viewer]
(let [region (str "(do " (.-doc (.-state viewer)) " )") (let [region (str "(do " (.-doc (.-state viewer)) " )")
@ -66,11 +82,44 @@
{:key "ArrowRight" :run clear-eval}]))) {:key "ArrowRight" :run clear-eval}])))
(def cm (def cm
(let [doc (str/trim " (let [doc "(map inc (range 8))"]
(map inc (range 8))
")]
(js/cm.EditorView. #js {:doc doc (js/cm.EditorView. #js {:doc doc
:extensions #js [js/cm.basicSetup, (js/lc.clojure), (.highest js/cs.Prec extension)] :extensions #js [js/cm.basicSetup, (js/lc.clojure), (.highest js/cs.Prec extension)]
:parent (js/document.querySelector "#app")}))) :parent (js/document.querySelector "#app")})))
(set! (.-cm_instance js/globalThis) cm) (set! (.-cm_instance js/globalThis) cm)
(let [code "(map inc (range 8)"
cursor-pos 18
s '(\space \c \n \i \space \p \a \m \()
open-parens 1
closed-parens 1]
[(rest s)
(inc open-parens) closed-parens]
(drop (count s) code)
)
;; god dammit this doesn't work and I have no idea why!
;; I stepped through it (above) and it works -
;; output is `(\( \r \a \n \g \e \space \8 \))`
;; but in the loop (below), it gives the empty list.
;; figure this out tomorrow
(let [code "(map inc (range 8)"
cursor-pos 18]
(loop [s (reverse (take cursor-pos code))
open-parens 0
closed-parens 0]
(cond
(= open-parens closed-parens)
(drop (count s) code)
(= \) (first s)) (recur (rest s) open-parens (inc closed-parens))
(= \( (first s)) (recur (rest s) (inc open-parens) closed-parens)
:else (recur (rest s) open-parens closed-parens))
))

View file

@ -48,5 +48,6 @@
</div> </div>
<div id="reagent"> <div id="reagent">
</div> </div>
<div id="debug"></div>
</body> </body>
</html> </html>