I’m trying to implement a code editor on my react site, I need to implement a pretty good autocompletion for Python. I ran into a problem, which is that I haven’t figured out how to add some ready-made solutions here (to be honest, I haven’t even found any yet). Speaking of my own attempts, I tried to solve this by adding my provider: autocompletion({ override: [customCompletionProvider] }),
.
Also its code:
const customCompletionProvider = (context) => {
const word = context.matchBefore(/w*/);
const code = context.state.doc.toString();
// detect variables in code
const variableDeclarationPattern = /(w+)s*=s*(.+)/g;
let match;
while ((match = variableDeclarationPattern.exec(code)) !== null) {
const [_, varName, varValue] = match;
if (/['"]/.test(varValue)) variables[varName] = "str";
else if (/[.*]/.test(varValue)) variables[varName] = "list";
else if (/(.*)/.test(varValue)) variables[varName] = "tuple";
else if (/{.*}/.test(varValue)) variables[varName] = "dict";
else if (/[-+]?d+/.test(varValue)) variables[varName] = "int";
else if (/[-+]?d*.d+/.test(varValue)) variables[varName] = "float";
}
// method call through dot? =>
const dotMatch = context.matchBefore(/w+.w*/);
if (dotMatch) {
const [variable, methodStart] = dotMatch.text.split(".");
if (variables[variable]) {
const methods = getMethodsForType(variables[variable]);
return {
from: dotMatch.from + variable.length + 1,
options: methods.map((method) => ({
label: method,
type: "method",
})),
};
}
}
const letterMatch = context.matchBefore(/[a-z]|[A-Z]/);
console.log(letterMatch);
if (!letterMatch) {
return null;
}
const basicSuggestions = [
{ label: "print", type: "function" },
{ label: "len", type: "function" },
{ label: "str", type: "type" },
{ label: "int", type: "type" },
{ label: "list", type: "type" },
{ label: "dict", type: "type" },
{ label: "tuple", type: "type" },
{ label: "def", type: "function" },
{ label: "class", type: "class" },
{ label: "async", type: "keyword" },
{ label: "return", type: "keyword" },
{ label: "yield", type: "keyword" },
];
return {
from: word.from,
options: basicSuggestions.filter((suggestion) =>
suggestion.label.startsWith(word.text)
),
};
};
Besides the fact that my version doesn’t work very well, to put it mildly, it also overrides the basic autocompletion, which I wouldn’t want to lose.
Also code of component:
<CodeMirror
value={value}
height="330px"
width="1000px"
extensions={[
python(),
indentUnit.of(" "),
autocompletion({ override: [customCompletionProvider] }),
onUpdateExtension,
]}
onChange={onChange}
theme={Theme}
/>;
Also i’m using onUpdateExtension:
const onUpdateExtension = EditorView.updateListener.of((update) => {
if (update.docChanged) {
const { state } = update.view;
const doc = state.doc.toString();
const lastChar = doc[doc.length - 1];
if (lastChar === ".") {
startCompletion(update.view);
}
}
});
PS: my main goal is to add hints for variable methods, right after typing the dot