@@ -37,6 +37,7 @@ const INDENTATION_AMOUNT = 2;
37
37
38
38
emmet ( CodeMirror ) ;
39
39
40
+ /** This is a custom React hook that manages CodeMirror state. */
40
41
export default function useCodeMirror ( {
41
42
theme,
42
43
lineNumbers,
@@ -56,7 +57,9 @@ export default function useCodeMirror({
56
57
fontSize,
57
58
onUpdateLinting
58
59
} ) {
60
+ // The codemirror instance.
59
61
const cmInstance = useRef ( ) ;
62
+ // The current codemirror files.
60
63
const docs = useRef ( ) ;
61
64
62
65
function onKeyUp ( ) {
@@ -89,6 +92,7 @@ export default function useCodeMirror({
89
92
const fileId = useRef ( ) ;
90
93
fileId . current = file . id ;
91
94
95
+ // When the file changes, update the file content and save status.
92
96
function onChange ( ) {
93
97
setUnsavedChanges ( true ) ;
94
98
hideRuntimeErrorWarning ( ) ;
@@ -100,6 +104,8 @@ export default function useCodeMirror({
100
104
}
101
105
const debouncedOnChange = debounce ( onChange , 1000 ) ;
102
106
107
+ // When the container component enters the DOM, we want this function
108
+ // to be called so we can setup the CodeMirror instance with the container.
103
109
function setupCodeMirrorOnContainerMounted ( container ) {
104
110
cmInstance . current = CodeMirror ( container , {
105
111
theme : `p5-${ theme } ` ,
@@ -169,13 +175,15 @@ export default function useCodeMirror({
169
175
[ `${ metaKey } -.` ] : 'toggleComment' // Note: most adblockers use the shortcut ctrl+.
170
176
} ) ;
171
177
178
+ // Setup the event listeners on the CodeMirror instance.
172
179
cmInstance . current . on ( 'change' , debouncedOnChange ) ;
173
180
cmInstance . current . on ( 'keyup' , onKeyUp ) ;
174
181
cmInstance . current . on ( 'keydown' , onKeyDown ) ;
175
182
176
183
cmInstance . current . getWrapperElement ( ) . style [ 'font-size' ] = `${ fontSize } px` ;
177
184
}
178
185
186
+ // When settings change, we pass those changes into CodeMirror.
179
187
useEffect ( ( ) => {
180
188
cmInstance . current . getWrapperElement ( ) . style [ 'font-size' ] = `${ fontSize } px` ;
181
189
} , [ fontSize ] ) ;
@@ -192,7 +200,8 @@ export default function useCodeMirror({
192
200
cmInstance . current . setOption ( 'autoCloseBrackets' , autocloseBracketsQuotes ) ;
193
201
} , [ autocloseBracketsQuotes ] ) ;
194
202
195
- const initializeDocuments = ( ) => {
203
+ // Initializes the files as CodeMirror documents.
204
+ function initializeDocuments ( ) {
196
205
docs . current = { } ;
197
206
files . forEach ( ( currentFile ) => {
198
207
if ( currentFile . name !== 'root' ) {
@@ -202,12 +211,13 @@ export default function useCodeMirror({
202
211
) ;
203
212
}
204
213
} ) ;
205
- } ;
214
+ }
206
215
207
- useEffect ( ( ) => {
208
- initializeDocuments ( ) ;
209
- } , [ files ] ) ;
216
+ // When the files change, reinitialize the documents.
217
+ useEffect ( initializeDocuments , [ files ] ) ;
210
218
219
+ // When the file changes, we change the file mode and
220
+ // make the CodeMirror call to swap out the document.
211
221
useEffectWithComparison (
212
222
( _ , prevProps ) => {
213
223
const fileMode = getFileMode ( file . name ) ;
@@ -226,10 +236,6 @@ export default function useCodeMirror({
226
236
}
227
237
cmInstance . current . focus ( ) ;
228
238
229
- if ( ! prevProps ?. unsavedChanges ) {
230
- setTimeout ( ( ) => setUnsavedChanges ( false ) , 400 ) ;
231
- }
232
-
233
239
for ( let i = 0 ; i < cmInstance . current . lineCount ( ) ; i += 1 ) {
234
240
cmInstance . current . removeLineClass (
235
241
i ,
@@ -241,6 +247,7 @@ export default function useCodeMirror({
241
247
[ file . id ]
242
248
) ;
243
249
250
+ // Remove the CM listeners on component teardown.
244
251
function teardownCodeMirror ( ) {
245
252
cmInstance . current . off ( 'keyup' , onKeyUp ) ;
246
253
cmInstance . current . off ( 'change' , debouncedOnChange ) ;
0 commit comments