If a user types in a Monaco editor using their keyboard, Monaco is capable of autoclosing brackets, so typing the character '(' will produce '()'. Is there a way to cause this to happen programmatically?
const editor = monaco.editor.create(document.getElementById("container"), {
"const x = ",
language: "javascript",
automaticLayout: true,
matchBrackets: "always",
autoClosingBrackets: "always",
});
const model = editor.getModel();
editor.trigger('keyboard', 'type', { text: "(", forceMoveMarkers: true });
This results in the text const x = (
being typed, instead of the desired const x = ()
.
Stepping through monaco/vscode internals I have reached a point where I suspect the autoclose behavior should be happening - editor.trigger
eventually calls typeWithInterceptors, which calls an _isAutoclosingOvertype method, I assume to determine if it needs to autoclose. This looks for an autoclosing config for the configured language - in this case javascript - but it is empty, so _isAutoclsoingOvertype
returns false. So I am wondering if there is an initialization step that I'm not doing, but I can't find anything in the documentation to support this.
Following your debug pointers, I found the exact point that generates the
difference between the programatic type and real typing,
which is here in the source code
at the call to _getAutoClosingPairClose
, and its cause is the difference in
the values of config.autoClosingPairs
at that point. The problem is that the property is initialized
asynchronously, as part of the language configuration initialization, which can be verified by the fact that
a simple delay (setTimeout
of typically less that a second) of the simulated type event gets the autocomplete working.
One can set an event handler that fires after the language configuration was finalized, using model.onDidChangeLanguageConfiguration:
model.onDidChangeLanguageConfiguration(()=>{
editor.trigger('keyboard', 'type', { text: "(", forceMoveMarkers: true });
});
Runnable example:
const editor = monaco.editor.create(document.getElementById("container"), {
value: "const x = ",
language: "javascript",
automaticLayout: true,
matchBrackets: "always",
autoClosingBrackets: "always",
});
const model = editor.getModel();
model.onDidChangeLanguageConfiguration(()=>{
editor.setPosition(new monaco.Position(1, editor.getValue().length+1));
editor.trigger('keyboard', 'type', { text: "(", forceMoveMarkers: true })
});
<div id="container" style="height: 10vh;border:1px solid black"></div>
<!-- script setup based on https://stackoverflow.com/a/63179814/16466946 -->
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/editor/editor.main.min.css" />
<script>var require = { paths: { 'vs': "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs"} }</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/loader.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/editor/editor.main.nls.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/editor/editor.main.min.js"></script>