Implement optional hover tooltip with function documentation

This commit is contained in:
Alexandre G.-Raymond 2023-11-05 13:00:54 +01:00
parent 0ecc6c196f
commit 353333653f
No known key found for this signature in database
GPG Key ID: 97BA9F51695B5C7B
7 changed files with 90 additions and 2 deletions

View File

@ -26,7 +26,6 @@ export function Autocomplete({ doc }) {
<pre
className="cursor-pointer"
onMouseDown={(e) => {
console.log('ola!');
navigator.clipboard.writeText(example);
e.stopPropagation();
}}

View File

@ -9,6 +9,7 @@ import _CodeMirror from '@uiw/react-codemirror';
import React, { useCallback, useMemo } from 'react';
import strudelTheme from '../themes/strudel-theme';
import { strudelAutocomplete } from './Autocomplete';
import { strudelTooltip } from './Tooltip';
import {
highlightExtension,
flashField,
@ -33,6 +34,7 @@ export default function CodeMirror({
keybindings,
isLineNumbersDisplayed,
isAutoCompletionEnabled,
isTooltipEnabled,
isLineWrappingEnabled,
fontSize = 18,
fontFamily = 'monospace',
@ -94,6 +96,10 @@ export default function CodeMirror({
_extensions.push(autocompletion({ override: [] }));
}
if (isTooltipEnabled) {
_extensions.push(strudelTooltip);
}
_extensions.push([keymap.of({})]);
if (isLineWrappingEnabled) {
@ -101,7 +107,7 @@ export default function CodeMirror({
}
return _extensions;
}, [keybindings, isAutoCompletionEnabled, isLineWrappingEnabled]);
}, [keybindings, isAutoCompletionEnabled, isTooltipEnabled, isLineWrappingEnabled]);
const basicSetup = useMemo(() => ({ lineNumbers: isLineNumbersDisplayed }), [isLineNumbersDisplayed]);

View File

@ -0,0 +1,69 @@
import { createRoot } from 'react-dom/client';
import { hoverTooltip } from '@codemirror/view';
import jsdoc from '../../../../doc.json';
import { Autocomplete } from './Autocomplete';
const getDocLabel = (doc) => doc.name || doc.longname;
let ctrlDown = false;
// Record Control key event to trigger or block the tooltip depending on the state
window.addEventListener(
'keyup',
function (e) {
if (e.key == 'Control') {
ctrlDown = false;
}
},
true,
);
window.addEventListener(
'keydown',
function (e) {
if (e.key == 'Control') {
ctrlDown = true;
}
},
true,
);
export const strudelTooltip = hoverTooltip(
(view, pos, side) => {
// Word selection from CodeMirror Hover Tooltip example https://codemirror.net/examples/tooltip/#hover-tooltips
let { from, to, text } = view.state.doc.lineAt(pos);
let start = pos,
end = pos;
while (start > from && /\w/.test(text[start - from - 1])) {
start--;
}
while (end < to && /\w/.test(text[end - from])) {
end++;
}
if ((start == pos && side < 0) || (end == pos && side > 0)) {
return null;
}
let word = text.slice(start - from, end - from);
// Get entry from Strudel documentation
let entry = jsdoc.docs.filter((doc) => getDocLabel(doc) === word)[0];
if (!entry) {
return null;
}
if (!ctrlDown) {
return null;
}
return {
pos: start,
end,
above: false,
arrow: true,
create(view) {
let dom = document.createElement('div');
dom.className = 'strudel-tooltip';
createRoot(dom).render(<Autocomplete doc={entry} />);
return { dom };
},
};
},
{ hoverTime: 10 },
);

View File

@ -28,3 +28,7 @@
footer {
z-index: 0 !important;
}
.strudel-tooltip {
padding: 5px;
}

View File

@ -385,6 +385,7 @@ function SettingsTab({ scheduler }) {
keybindings,
isLineNumbersDisplayed,
isAutoCompletionEnabled,
isTooltipEnabled,
isLineWrappingEnabled,
fontSize,
fontFamily,
@ -457,6 +458,11 @@ function SettingsTab({ scheduler }) {
onChange={(cbEvent) => settingsMap.setKey('isAutoCompletionEnabled', cbEvent.target.checked)}
value={isAutoCompletionEnabled}
/>
<Checkbox
label="Enable tooltips on Ctrl and hover"
onChange={(cbEvent) => settingsMap.setKey('isTooltipEnabled', cbEvent.target.checked)}
value={isTooltipEnabled}
/>
<Checkbox
label="Enable line wrapping"
onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)}

View File

@ -126,6 +126,7 @@ export function Repl({ embedded = false }) {
fontFamily,
isLineNumbersDisplayed,
isAutoCompletionEnabled,
isTooltipEnabled,
isLineWrappingEnabled,
panelPosition,
isZen,
@ -335,6 +336,7 @@ export function Repl({ embedded = false }) {
keybindings={keybindings}
isLineNumbersDisplayed={isLineNumbersDisplayed}
isAutoCompletionEnabled={isAutoCompletionEnabled}
isTooltipEnabled={isTooltipEnabled}
isLineWrappingEnabled={isLineWrappingEnabled}
fontSize={fontSize}
fontFamily={fontFamily}

View File

@ -7,6 +7,7 @@ export const defaultSettings = {
keybindings: 'codemirror',
isLineNumbersDisplayed: true,
isAutoCompletionEnabled: false,
isTooltipEnabled: false,
isLineWrappingEnabled: false,
theme: 'strudelTheme',
fontFamily: 'monospace',
@ -26,6 +27,7 @@ export function useSettings() {
isZen: [true, 'true'].includes(state.isZen) ? true : false,
isLineNumbersDisplayed: [true, 'true'].includes(state.isLineNumbersDisplayed) ? true : false,
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,
isTooltipEnabled: [true, 'true'].includes(state.isTooltipEnabled) ? true : false,
isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false,
fontSize: Number(state.fontSize),
panelPosition: state.activeFooter !== '' ? state.panelPosition : 'bottom',