Skip to content

Commit eae004b

Browse files
authored
Merge pull request #3582 from processing/cm6-autocomplete
[Cm 5-> 6 conversion] autocomplete
2 parents 4f358b4 + 9f04f17 commit eae004b

File tree

7 files changed

+158
-1047
lines changed

7 files changed

+158
-1047
lines changed

client/modules/IDE/components/Editor/codemirror.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useRef, useEffect } from 'react';
22
import { EditorView, lineNumbers as lineNumbersExt } from '@codemirror/view';
3-
import { closeBrackets } from '@codemirror/autocomplete';
3+
import { autocompletion, closeBrackets } from '@codemirror/autocomplete';
44

55
// TODO: Check what the v6 variants of these addons are.
66
// import 'codemirror/addon/search/searchcursor';
@@ -13,7 +13,8 @@ import { debounce } from 'lodash';
1313
import {
1414
getFileMode,
1515
createNewFileState,
16-
updateFileStates
16+
updateFileStates,
17+
AUTOCOMPLETE_OPTIONS
1718
} from './stateUtils';
1819
import { useEffectWithComparison } from '../../hooks/custom-hooks';
1920
import tidyCodeWithPrettier from './tidier';
@@ -141,6 +142,18 @@ export default function useCodeMirror({
141142
reconfigureEffect
142143
});
143144
}, [autocloseBracketsQuotes]);
145+
useEffect(() => {
146+
const reconfigureEffect = (fileState) =>
147+
fileState.autocompleteCpt.reconfigure(
148+
autocompleteHinter ? autocompletion(AUTOCOMPLETE_OPTIONS) : []
149+
);
150+
updateFileStates({
151+
fileStates: fileStates.current,
152+
cmView: cmView.current,
153+
file,
154+
reconfigureEffect
155+
});
156+
}, [autocompleteHinter]);
144157

145158
// Initializes the files as CodeMirror states.
146159
function initializeDocuments() {
@@ -160,6 +173,7 @@ export default function useCodeMirror({
160173
linewrap,
161174
lineNumbers,
162175
autocloseBracketsQuotes,
176+
autocomplete: autocompleteHinter,
163177
onUpdateLinting,
164178
onViewUpdate
165179
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { LanguageSupport } from '@codemirror/language';
2+
import { javascript } from '@codemirror/lang-javascript';
3+
import { p5Hinter } from '../../../../utils/p5-hinter';
4+
5+
function testCompletions(context) {
6+
const word = context.matchBefore(/\w*/);
7+
if (word.from === word.to && !context.explicit) return null;
8+
9+
function addDomNodeInfo(item) {
10+
const itemCopy = { ...item };
11+
12+
if (item.p5DocPath) {
13+
// TODO: Use the option below to add the p5 link for *all* hints.
14+
// https://codemirror.net/docs/ref/#autocomplete.autocompletion^config.addToOptions
15+
itemCopy.info = () => {
16+
const domNode = document.createElement('a');
17+
domNode.href = `https://p5js.org/reference/p5/${item.p5DocPath}`;
18+
domNode.role = 'link';
19+
domNode.target = '_blank';
20+
domNode.onclick = (event) => event.stopPropagation();
21+
domNode.innerHTML = `
22+
<span class="hint-hidden">open ${item.label} reference</span>
23+
<span aria-hidden="true">&#10132;</span>
24+
`;
25+
return {
26+
dom: domNode,
27+
destroy: () => {
28+
// Cleanup logic if needed
29+
domNode.remove();
30+
}
31+
};
32+
};
33+
}
34+
35+
return itemCopy;
36+
}
37+
38+
const hinterWithDomNodes = p5Hinter.map(addDomNodeInfo);
39+
40+
return {
41+
from: word.from,
42+
options: hinterWithDomNodes
43+
};
44+
}
45+
46+
export default function p5JavaScript() {
47+
const jsLang = javascript();
48+
return new LanguageSupport(jsLang.language, [
49+
jsLang.extension,
50+
jsLang.language.data.of({
51+
autocomplete: testCompletions
52+
})
53+
]);
54+
}

client/modules/IDE/components/Editor/stateUtils.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import {
2121
defaultHighlightStyle
2222
} from '@codemirror/language';
2323
import { highlightSelectionMatches } from '@codemirror/search';
24-
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
24+
import {
25+
autocompletion,
26+
closeBrackets,
27+
closeBracketsKeymap
28+
} from '@codemirror/autocomplete';
2529
import {
2630
defaultKeymap,
2731
history,
@@ -36,7 +40,6 @@ import {
3640
abbreviationTracker
3741
} from '@emmetio/codemirror6-plugin';
3842

39-
import { javascript } from '@codemirror/lang-javascript';
4043
import { css } from '@codemirror/lang-css';
4144
import { html } from '@codemirror/lang-html';
4245
import { json } from '@codemirror/lang-json';
@@ -47,6 +50,7 @@ import { HTMLHint } from 'htmlhint';
4750
import { CSSLint } from 'csslint';
4851
import { emmetConfig } from '@emmetio/codemirror6-plugin';
4952

53+
import p5JavaScript from './p5JavaScript';
5054
import tidyCodeWithPrettier from './tidier';
5155

5256
// ----- TODOS -----
@@ -83,7 +87,7 @@ function getFileLanguage(fileName) {
8387

8488
switch (fileMode) {
8589
case 'javascript':
86-
return javascript;
90+
return p5JavaScript;
8791
case 'css':
8892
return css;
8993
case 'html':
@@ -255,6 +259,12 @@ function getFileEmmetConfig(fileName) {
255259
const extraKeymaps = [{ key: 'Tab', run: insertTab, shift: indentLess }];
256260
const emmetKeymaps = [{ key: 'Tab', run: expandAbbreviation }];
257261

262+
export const AUTOCOMPLETE_OPTIONS = {
263+
tooltipClass: () => 'CodeMirror-hints',
264+
optionClass: () => 'CodeMirror-hint',
265+
closeOnBlur: false
266+
};
267+
258268
/**
259269
* Creates a new CodeMirror editor state with configurations,
260270
* extensions, and keymaps tailored to the file type and settings.
@@ -265,13 +275,15 @@ export function createNewFileState(filename, document, settings) {
265275
const {
266276
linewrap,
267277
lineNumbers,
278+
autocomplete,
268279
autocloseBracketsQuotes,
269280
onUpdateLinting,
270281
onViewUpdate
271282
} = settings;
272283
const lineNumbersCpt = new Compartment();
273284
const lineWrappingCpt = new Compartment();
274285
const closeBracketsCpt = new Compartment();
286+
const autocompleteCpt = new Compartment();
275287

276288
// Depending on the file mode, we have a different tidier function.
277289
const mode = getFileMode(filename);
@@ -294,6 +306,9 @@ export function createNewFileState(filename, document, settings) {
294306
lineNumbersCpt.of(lineNumbers ? lineNumbersExt() : []),
295307
lineWrappingCpt.of(linewrap ? EditorView.lineWrapping : []),
296308
closeBracketsCpt.of(autocloseBracketsQuotes ? closeBrackets() : []),
309+
autocompleteCpt.of(
310+
autocomplete ? autocompletion(AUTOCOMPLETE_OPTIONS) : []
311+
),
297312

298313
// Everything below here should always be on.
299314
history(),
@@ -352,7 +367,13 @@ export function createNewFileState(filename, document, settings) {
352367
}
353368

354369
const cmState = EditorState.create(stateOptions);
355-
return { cmState, lineNumbersCpt, lineWrappingCpt, closeBracketsCpt };
370+
return {
371+
cmState,
372+
lineNumbersCpt,
373+
lineWrappingCpt,
374+
closeBracketsCpt,
375+
autocompleteCpt
376+
};
356377
}
357378

358379
/**

0 commit comments

Comments
 (0)