@neo4j-cypher/react-codemirror 2.0.0-next.6 → 2.0.0-next.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/CypherEditor.d.ts +32 -1
- package/dist/CypherEditor.js +45 -9
- package/dist/CypherEditor.js.map +1 -1
- package/dist/e2e_tests/configuration.spec.d.ts +1 -0
- package/dist/e2e_tests/configuration.spec.js +73 -0
- package/dist/e2e_tests/configuration.spec.js.map +1 -0
- package/dist/e2e_tests/e2eUtils.js +9 -1
- package/dist/e2e_tests/e2eUtils.js.map +1 -1
- package/dist/e2e_tests/sanityChecks.spec.js +0 -9
- package/dist/e2e_tests/sanityChecks.spec.js.map +1 -1
- package/dist/e2e_tests/signatureHelp.spec.js +16 -15
- package/dist/e2e_tests/signatureHelp.spec.js.map +1 -1
- package/dist/e2e_tests/snippets.spec.d.ts +1 -0
- package/dist/e2e_tests/snippets.spec.js +63 -0
- package/dist/e2e_tests/snippets.spec.js.map +1 -0
- package/dist/e2e_tests/syntaxValidation.spec.js +3 -3
- package/dist/e2e_tests/syntaxValidation.spec.js.map +1 -1
- package/dist/lang-cypher/autocomplete.js +9 -3
- package/dist/lang-cypher/autocomplete.js.map +1 -1
- package/dist/lang-cypher/createCypherTheme.js +29 -1
- package/dist/lang-cypher/createCypherTheme.js.map +1 -1
- package/dist/lang-cypher/signatureHelp.js +36 -20
- package/dist/lang-cypher/signatureHelp.js.map +1 -1
- package/dist/neo4jSetup.js +35 -1
- package/dist/neo4jSetup.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/CypherEditor.tsx +102 -10
- package/src/e2e_tests/configuration.spec.tsx +97 -0
- package/src/e2e_tests/e2eUtils.ts +11 -1
- package/src/e2e_tests/sanityChecks.spec.tsx +0 -14
- package/src/e2e_tests/signatureHelp.spec.tsx +16 -19
- package/src/e2e_tests/snippets.spec.tsx +94 -0
- package/src/e2e_tests/syntaxValidation.spec.tsx +3 -3
- package/src/lang-cypher/autocomplete.ts +15 -4
- package/src/lang-cypher/createCypherTheme.ts +30 -1
- package/src/lang-cypher/signatureHelp.ts +57 -28
- package/src/neo4jSetup.tsx +51 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EditorState, StateField } from '@codemirror/state';
|
|
2
2
|
import { showTooltip, Tooltip } from '@codemirror/view';
|
|
3
3
|
import { signatureHelp } from '@neo4j-cypher/language-support';
|
|
4
|
+
import { SignatureInformation } from 'vscode-languageserver-types';
|
|
4
5
|
import { CypherConfig } from './langCypher';
|
|
5
6
|
|
|
6
7
|
function getTriggerCharacter(query: string, caretPosition: number) {
|
|
@@ -16,6 +17,61 @@ function getTriggerCharacter(query: string, caretPosition: number) {
|
|
|
16
17
|
return triggerCharacter;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
const createSignatureHelpElement =
|
|
21
|
+
({
|
|
22
|
+
signature,
|
|
23
|
+
activeParameter,
|
|
24
|
+
}: {
|
|
25
|
+
signature: SignatureInformation;
|
|
26
|
+
activeParameter: number;
|
|
27
|
+
}) =>
|
|
28
|
+
() => {
|
|
29
|
+
const parameters = signature.parameters;
|
|
30
|
+
const doc = signature.documentation.toString();
|
|
31
|
+
const dom = document.createElement('div');
|
|
32
|
+
dom.className = 'cm-signature-help-panel';
|
|
33
|
+
|
|
34
|
+
const contents = document.createElement('div');
|
|
35
|
+
contents.className = 'cm-signature-help-panel-contents';
|
|
36
|
+
dom.appendChild(contents);
|
|
37
|
+
|
|
38
|
+
const signatureLabel = document.createElement('div');
|
|
39
|
+
signatureLabel.className = 'cm-signature-help-panel-name';
|
|
40
|
+
signatureLabel.appendChild(document.createTextNode(`${signature.label}(`));
|
|
41
|
+
|
|
42
|
+
parameters.forEach((param, index) => {
|
|
43
|
+
if (typeof param.documentation === 'string') {
|
|
44
|
+
const span = document.createElement('span');
|
|
45
|
+
span.appendChild(document.createTextNode(param.documentation));
|
|
46
|
+
if (index !== parameters.length - 1) {
|
|
47
|
+
span.appendChild(document.createTextNode(', '));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (index === activeParameter) {
|
|
51
|
+
span.className = 'cm-signature-help-panel-current-argument';
|
|
52
|
+
}
|
|
53
|
+
signatureLabel.appendChild(span);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
signatureLabel.appendChild(document.createTextNode(')'));
|
|
58
|
+
|
|
59
|
+
contents.appendChild(signatureLabel);
|
|
60
|
+
|
|
61
|
+
const separator = document.createElement('div');
|
|
62
|
+
separator.className = 'cm-signature-help-panel-separator';
|
|
63
|
+
|
|
64
|
+
contents.appendChild(separator);
|
|
65
|
+
|
|
66
|
+
const description = document.createElement('div');
|
|
67
|
+
description.className = 'cm-signature-help-panel-description';
|
|
68
|
+
description.appendChild(document.createTextNode(doc));
|
|
69
|
+
|
|
70
|
+
contents.appendChild(description);
|
|
71
|
+
|
|
72
|
+
return { dom };
|
|
73
|
+
};
|
|
74
|
+
|
|
19
75
|
function getSignatureHelpTooltip(
|
|
20
76
|
state: EditorState,
|
|
21
77
|
config: CypherConfig,
|
|
@@ -44,17 +100,6 @@ function getSignatureHelpTooltip(
|
|
|
44
100
|
signatures[activeSignature].documentation !== undefined
|
|
45
101
|
) {
|
|
46
102
|
const signature = signatures[activeSignature];
|
|
47
|
-
const parameters = signature.parameters;
|
|
48
|
-
let doc = signature.documentation.toString();
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
activeParameter >= 0 &&
|
|
52
|
-
activeParameter <
|
|
53
|
-
(signatures[activeSignature].parameters?.length ?? 0)
|
|
54
|
-
) {
|
|
55
|
-
doc =
|
|
56
|
-
parameters[activeParameter].documentation.toString() + '\n\n' + doc;
|
|
57
|
-
}
|
|
58
103
|
|
|
59
104
|
result = [
|
|
60
105
|
{
|
|
@@ -62,23 +107,7 @@ function getSignatureHelpTooltip(
|
|
|
62
107
|
above: true,
|
|
63
108
|
strictSide: true,
|
|
64
109
|
arrow: true,
|
|
65
|
-
create: (
|
|
66
|
-
const div = document.createElement('div');
|
|
67
|
-
const methodName = document.createElement('div');
|
|
68
|
-
const argPlusDescription = document.createElement('div');
|
|
69
|
-
const separator = document.createElement('hr');
|
|
70
|
-
const lineBreak = document.createElement('br');
|
|
71
|
-
|
|
72
|
-
div.append(
|
|
73
|
-
...[methodName, separator, lineBreak, argPlusDescription],
|
|
74
|
-
);
|
|
75
|
-
div.className = 'cm-tooltip-signature-help';
|
|
76
|
-
|
|
77
|
-
methodName.innerText = signature.label;
|
|
78
|
-
argPlusDescription.innerText = doc;
|
|
79
|
-
|
|
80
|
-
return { dom: div };
|
|
81
|
-
},
|
|
110
|
+
create: createSignatureHelpElement({ signature, activeParameter }),
|
|
82
111
|
},
|
|
83
112
|
];
|
|
84
113
|
}
|
package/src/neo4jSetup.tsx
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
acceptCompletion,
|
|
3
3
|
autocompletion,
|
|
4
|
+
clearSnippet,
|
|
4
5
|
closeBrackets,
|
|
5
6
|
closeBracketsKeymap,
|
|
7
|
+
closeCompletion,
|
|
6
8
|
completionKeymap,
|
|
9
|
+
nextSnippetField,
|
|
10
|
+
prevSnippetField,
|
|
11
|
+
snippetKeymap,
|
|
7
12
|
} from '@codemirror/autocomplete';
|
|
8
13
|
import {
|
|
9
14
|
defaultKeymap,
|
|
@@ -22,11 +27,13 @@ import {
|
|
|
22
27
|
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
|
|
23
28
|
import { EditorState, Extension, StateCommand } from '@codemirror/state';
|
|
24
29
|
import {
|
|
30
|
+
Command,
|
|
25
31
|
crosshairCursor,
|
|
26
32
|
drawSelection,
|
|
27
33
|
dropCursor,
|
|
28
34
|
EditorView,
|
|
29
35
|
highlightSpecialChars,
|
|
36
|
+
KeyBinding,
|
|
30
37
|
keymap,
|
|
31
38
|
rectangularSelection,
|
|
32
39
|
} from '@codemirror/view';
|
|
@@ -55,7 +62,7 @@ const insertTab: StateCommand = (cmd) => {
|
|
|
55
62
|
};
|
|
56
63
|
|
|
57
64
|
export const basicNeo4jSetup = (): Extension[] => {
|
|
58
|
-
const keymaps = [
|
|
65
|
+
const keymaps: KeyBinding[] = [
|
|
59
66
|
closeBracketsKeymap,
|
|
60
67
|
defaultKeymap,
|
|
61
68
|
searchKeymap,
|
|
@@ -125,5 +132,48 @@ export const basicNeo4jSetup = (): Extension[] => {
|
|
|
125
132
|
|
|
126
133
|
extensions.push(keymap.of(keymaps));
|
|
127
134
|
|
|
135
|
+
extensions.push(
|
|
136
|
+
snippetKeymap.of([
|
|
137
|
+
{
|
|
138
|
+
key: 'Tab',
|
|
139
|
+
run: acceptCompletionOrGotoNextSnippet,
|
|
140
|
+
shift: acceptCompletionOrGotoPrevSnippet,
|
|
141
|
+
},
|
|
142
|
+
{ key: 'Escape', run: closeCompletionsOrClearSnippets },
|
|
143
|
+
]),
|
|
144
|
+
);
|
|
145
|
+
|
|
128
146
|
return extensions;
|
|
129
147
|
};
|
|
148
|
+
|
|
149
|
+
// The logic to check if there's a completion open is surprisingly complex
|
|
150
|
+
// https://github.com/codemirror/autocomplete/blob/5ad2ebc861f2f61cdc943fc087a5bfb756a7d0fa/src/view.ts#L31
|
|
151
|
+
// For example it respects an interaction delay, so we can't just check if the completion is open
|
|
152
|
+
// instead we just run the acceptCompletion command which returns true if a completion was accepted
|
|
153
|
+
// in that case we know that we shouldn't move to the next snippet field
|
|
154
|
+
const acceptCompletionOrGotoNextSnippet: Command = (view: EditorView) => {
|
|
155
|
+
const didCompletion = acceptCompletion(view);
|
|
156
|
+
if (didCompletion) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return nextSnippetField(view);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const acceptCompletionOrGotoPrevSnippet: Command = (view: EditorView) => {
|
|
164
|
+
const didCompletion = acceptCompletion(view);
|
|
165
|
+
if (didCompletion) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return prevSnippetField(view);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const closeCompletionsOrClearSnippets: Command = (view: EditorView) => {
|
|
173
|
+
const closedCompletions = closeCompletion(view);
|
|
174
|
+
if (closedCompletions) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return clearSnippet(view);
|
|
179
|
+
};
|