1
1
import { 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' ;
2
3
import { EditorView , drawSelection , keymap } from '@codemirror/view' ;
3
4
import { EditorState } from '@codemirror/state' ;
4
5
import { syntaxHighlighting , defaultHighlightStyle , foldGutter } from '@codemirror/language' ;
6
+ import { compileString } from 'squint-cljs' ;
5
7
6
8
let theme = EditorView . theme ( {
7
9
".cm-content" : { whitespace : "pre-wrap" ,
@@ -23,14 +25,79 @@ let theme = EditorView.theme({
23
25
"&.cm-focused .cm-cursor" : { visibility : "visible" }
24
26
} ) ;
25
27
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
+
26
91
let extensions = [ theme , foldGutter ( ) ,
27
92
syntaxHighlighting ( defaultHighlightStyle ) ,
28
93
drawSelection ( ) ,
29
94
keymap . of ( complete_keymap ) ,
30
- ...default_extensions
95
+ ...default_extensions ,
96
+ eval_ext ( { modifier : "Meta" } ) ,
97
+ squintExtension ( { modifier : "Meta" } )
31
98
] ;
32
99
33
- let state = EditorState . create ( { doc : `(comment
100
+ let doc = `(comment
34
101
(fizz-buzz 1)
35
102
(fizz-buzz 3)
36
103
(fizz-buzz 5)
@@ -43,9 +110,48 @@ let state = EditorState.create( {doc: `(comment
43
110
15 "fizzbuzz"
44
111
3 "fizz"
45
112
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 ,
47
125
extensions : extensions } ) ;
126
+
48
127
let editorElt = document . querySelector ( '#editor' ) ;
49
128
let editor = new EditorView ( { state : state ,
50
129
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