-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathfunctionTooltips.ts
105 lines (92 loc) · 2.73 KB
/
functionTooltips.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { Tooltip, showTooltip, EditorView } from '@codemirror/view';
import { StateField, EditorState } from '@codemirror/state';
import { syntaxTree } from '@codemirror/language';
export type TooltipDirectionary = Record<
string,
{ syntax: string; description: string }
>;
function getCursorTooltips(
state: EditorState,
dict: TooltipDirectionary
): readonly Tooltip[] {
const tree = syntaxTree(state);
const pos = state.selection.main.head;
const node = tree.resolveInner(state.selection.main.head, -1);
const parent = node.parent;
if (!parent) return [];
if (parent.type.name !== 'Parens') return [];
if (!parent.prevSibling) return [];
if (parent.prevSibling.type.name !== 'Keyword') return [];
const keywordString = state.doc
.slice(parent.prevSibling.from, parent.prevSibling.to)
.toString()
.toLowerCase();
const dictItem = dict[keywordString];
if (dictItem) {
return [
{
pos: pos,
above: true,
arrow: true,
create: () => {
const dom = document.createElement('div');
dom.addEventListener('click', (e) => {
const target = e.target as HTMLElement;
const link = target.closest('a');
if (link) {
e.preventDefault();
window.electron.openExternal(link.href);
}
});
dom.className = 'cm-tooltip-cursor';
dom.innerHTML = `
<div style="max-width:700px;">
<p><strong>${dictItem.syntax}</strong></p>
<div class="code-tooltip">${dictItem.description}</div>
</div>
`;
return { dom };
},
},
];
}
return [];
}
const functionTooltipField = (dict: TooltipDirectionary) => {
return StateField.define<readonly Tooltip[]>({
create(state) {
return getCursorTooltips(state, dict);
},
update(tooltips, tr) {
if (!tr.docChanged && !tr.selection) return tooltips;
return getCursorTooltips(tr.state, dict);
},
provide: (f) => showTooltip.computeN([f], (state) => state.field(f)),
});
};
const functionTooltipBaseTheme = EditorView.baseTheme({
'.cm-tooltip.cm-tooltip-cursor': {
backgroundColor: '#66b',
color: 'white',
border: 'none',
padding: '2px 7px',
borderRadius: '4px',
'& .cm-tooltip-arrow:before': {
borderTopColor: '#66b',
},
'& .cm-tooltip-arrow:after': {
borderTopColor: 'transparent',
},
},
'.code-tooltip a': {
color: 'white',
textDecoration: 'underline',
},
'.code-tooltip a:hover': {
color: 'white',
textDecoration: 'none',
},
});
export function functionTooltip(dict: TooltipDirectionary) {
return [functionTooltipField(dict), functionTooltipBaseTheme];
}