简体   繁体   中英

How do I insert text into a Monaco Editor?

I have a monaco code editor embedded in my app.

How do I programmatically insert text on a particular line?

var editor = monaco.editor.create(document.getElementById("container"), {
    value: "// First line\nfunction hello() {\n\talert('Hello world!');\n}\n// Last line",
    language: "javascript",

    lineNumbers: false,
    roundedSelection: false,
    scrollBeyondLastLine: false,
    readOnly: false,
    theme: "vs-dark",
});
// how do I do this?
editor.insertText("FOO");

A more robust solution would be to use the Selection API instead of Position

var selection = editor.getSelection();
var id = { major: 1, minor: 1 };             
var text = "XXX";
var op = {identifier: id, range: selection, text: text, forceMoveMarkers: true};
editor.executeEdits("my-source", [op]);

If there is already a pre-selected text in the editor, the insert will replace it, which is in my opinion, the correct behavior.

Using the executeEdits API

var line = editor.getPosition();
var range = new monaco.Range(line.lineNumber, 1, line.lineNumber, 1);
var id = { major: 1, minor: 1 };             
var text = "FOO";
var op = {identifier: id, range: range, text: text, forceMoveMarkers: true};
editor.executeEdits("my-source", [op]);

To insert text at the cursor, there is this very simple way. I use it a lot to make Snippet toolbars:

editor.trigger('keyboard', 'type', {text: "test"});

It will replace the text if text is selected.

And you can also add multiple line text this way:

editor.trigger('keyboard', 'type', {text: `text on
multiple
line`});

A more natural solution (as mentioned above) can be the to use the executeEdits method that comes with monaco and use a specific range with line numbers and column numbers, because in the examples they are always using the first line:

const startLineNumber = 15 // Line number in which the content will start being typed
const startColumn = 5 // Column number in which the content will start being typed
const endLineNumber = 18 // Line number in which the text will finish
const endColumn = 25 
const text = "This is the new text" // The content going to be added


const range = new monaco.edito.Range(startLineNumber, startColumn, endLineNumber, endColumn); // It will go to the specific position of the editor

const id = { major: 1, minor: 1 }; // Required generic id

const editOperation = {identifier: id, range: range, text: text, forceMoveMarkers: true}; // The operation going to be performed

monaco.editor.executeEdits("custom-code", [ editOperation ]); // Runs the instruction

The good part of the code above is that it can add, delete, update and replace existing code, so it will be very efficient and the end user will see it like if he/she was typing.

I've had issues implementing this with react and typescript so hopefully this could help someone.

import Editor, { Monaco, OnMount } from '@monaco-editor/react';
import { editor, languages } from 'monaco-editor';

...

const CustomEditor: React.FC = () => {

    const [monacoInstance, setMonacoInstance] = React.useState<editor.IStandaloneCodeEditor | null>(null);

    const insertText = (text: string) => {
        if (monacoInstance) {
            const selection = monacoInstance.getSelection();
            const id = { major: 1, minor: 1 };
            const op = {
                identifier: id,
                range: {
                    startLineNumber: selection?.selectionStartLineNumber || 1,
                    startColumn: selection?.selectionStartColumn || 1,
                    endLineNumber: selection?.endLineNumber || 1,
                    endColumn: selection?.endColumn || 1,
                },
                text,
                forceMoveMarkers: true,
            };
            monacoInstance.executeEdits('my-source', [op]);
        }
    };

    const editorMount: OnMount = (editorL: editor.IStandaloneCodeEditor) => {
        setMonacoInstance(editorL);
    };

...

        <Editor
            onMount={editorMount}

...

        <StyledButton // styled comp
            onClick={() => {insertText('inserted text');}}
        >
            insert text
        </StyledButton>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM