11import { default_extensions , complete_keymap } from '@nextjournal/clojure-mode' ;
2+ import { extension as eval_ext , cursor_node_string , top_level_string } from '@nextjournal/clojure-mode/extensions/eval-region' ;
23import { EditorView , drawSelection , keymap } from '@codemirror/view' ;
34import { EditorState } from '@codemirror/state' ;
45import { syntaxHighlighting , defaultHighlightStyle , foldGutter } from '@codemirror/language' ;
6+ import { compileString } from 'squint-cljs' ;
57
68let theme = EditorView . theme ( {
79 ".cm-content" : { whitespace : "pre-wrap" ,
@@ -23,14 +25,79 @@ let theme = EditorView.theme({
2325 "&.cm-focused .cm-cursor" : { visibility : "visible" }
2426} ) ;
2527
28+ let evalCode = async function ( code ) {
29+ let js = compileString ( `(do ${ code } )` , { repl : true ,
30+ context : 'return' ,
31+ "elide-exports" : true } )
32+ let result ;
33+ try {
34+ result = { value : await eval ( `(async function() { ${ js } })()` ) } ;
35+ }
36+ catch ( e ) {
37+ result = { error : true , ex : e } ;
38+ }
39+ if ( result . error ) {
40+ document . getElementById ( "result" ) . innerText = result . ex ;
41+ } else {
42+ document . getElementById ( "result" ) . innerText = '' + JSONstringify ( result . value ) ;
43+ }
44+ }
45+
46+ let evalCell = ( opts ) => {
47+ let code = opts . state . doc . toString ( ) ;
48+ evalCode ( code ) ;
49+ return true ;
50+ }
51+
52+ let evalToplevel = function ( opts ) {
53+ let state = opts . state ;
54+ let code = top_level_string ( state ) ;
55+ evalCode ( code ) ;
56+ return true ;
57+ }
58+
59+ function JSONstringify ( json ) {
60+ json = JSON . stringify ( json , function ( key , value ) {
61+ if ( ! value ) return value ;
62+ if ( typeof value === 'string' ) return value ;
63+ if ( Array . isArray ( value ) || value . constructor === Object ) return value ;
64+ if ( value [ Symbol . iterator ] ) {
65+ return [ ...value ] ;
66+ }
67+ if ( typeof value === 'object' ) {
68+ return `#object[${ value . constructor . name } ]` ;
69+ } else {
70+ return value ;
71+ }
72+ } ) ;
73+ return json ;
74+ }
75+
76+ let evalAtCursor = function ( opts ) {
77+ let state = opts . state ;
78+ let code = cursor_node_string ( state ) ;
79+ evalCode ( code ) ;
80+ return true ;
81+ }
82+
83+ let squintExtension = ( opts ) => {
84+ return keymap . of ( [ { key : "Alt-Enter" , run : evalCell } ,
85+ { key : opts . modifier + "-Enter" ,
86+ run : evalAtCursor ,
87+ shift : evalToplevel
88+ } ] ) }
89+
90+
2691let extensions = [ theme , foldGutter ( ) ,
2792 syntaxHighlighting ( defaultHighlightStyle ) ,
2893 drawSelection ( ) ,
2994 keymap . of ( complete_keymap ) ,
30- ...default_extensions
95+ ...default_extensions ,
96+ eval_ext ( { modifier : "Meta" } ) ,
97+ squintExtension ( { modifier : "Meta" } )
3198 ] ;
3299
33- let state = EditorState . create ( { doc : `(comment
100+ let doc = `(comment
34101 (fizz-buzz 1)
35102 (fizz-buzz 3)
36103 (fizz-buzz 5)
@@ -43,9 +110,48 @@ let state = EditorState.create( {doc: `(comment
43110 15 "fizzbuzz"
44111 3 "fizz"
45112 5 "buzz"
46- n))` ,
113+ n))
114+
115+ (require '["https://esm.sh/[email protected] $default" :as confetti]) 116+
117+ (do
118+ (js-await (confetti))
119+ (+ 1 2 3))
120+ ` ;
121+
122+ evalCode ( doc ) ;
123+
124+ let state = EditorState . create ( { doc : doc ,
47125 extensions : extensions } ) ;
126+
48127let editorElt = document . querySelector ( '#editor' ) ;
49128let editor = new EditorView ( { state : state ,
50129 parent : editorElt ,
51- extensions : extensions } ) ;
130+ extensions : extensions } )
131+
132+ let keys = { "ArrowUp" : "↑" ,
133+ "ArrowDown" : "↓" ,
134+ "ArrowRight" : "→" ,
135+ "ArrowLeft" : "←" ,
136+ "Mod" : "Ctrl" }
137+
138+ let macKeys = { "Alt" : "⌥" ,
139+ "Shift" : "⇧" ,
140+ "Enter" : "⏎" ,
141+ "Ctrl" : "⌃" ,
142+ "Mod" : "⌘" }
143+
144+ let mac ;
145+
146+ if ( / ^ ( M a c ) | ( i P h o n e ) | ( i P a d ) | ( i P o d ) $ / . test ( window . navigator . platform . substring ( 0 , 3 ) ) ) {
147+ mac = true ;
148+ Object . assign ( keys , macKeys ) ;
149+ }
150+
151+ document . querySelectorAll ( ".mod,.alt,.ctrl" ) . forEach ( node => {
152+ let k = node . innerHTML ;
153+ let symbol = keys [ k ] ;
154+ if ( symbol ) {
155+ node . innerHTML = symbol ;
156+ }
157+ } ) ;
0 commit comments