[Python] How to achieve advanced autocompletion in React CodeMirror?

Discussão em 'Python' iniciado por Stack, Setembro 27, 2024.

  1. Stack

    Stack Membro Participativo

    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

    Continue reading...

Compartilhe esta Página