microsoft / microsoft/monaco-editor
[Bug] `ITextModel.pushEditOperations()` ignores the `cursorStateComputer`
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 46.8k
- Forks
- 4.1k
- Avg merge
- 17h 58m
- Merged PRs (30d)
- 1
Description
Reproducible in vscode.dev or in VS Code Desktop?
- Not reproducible in vscode.dev or VS Code Desktop
Reproducible in the monaco editor playground?
- Not reproducible in the monaco editor playground
Monaco Editor Playground Link
Monaco Editor Playground Code
// JS:
/**
* This demonstrates two Monaco bugs. One of them was fixed in 0.35.0 but present in
* 0.34.1. The other one is still present in the latest version 0.37.0.
*
* THIS ONE IS STILL A BUG AS OF 0.37.0: It should put the cursor at the end after you press
* the button, but it ignores the provided cursor computer.
*
* THIS ONE WAS FIXED IN 0.35.0: Change the line `() => [new monaco.Selection(4, 13, 4, 13)],` to
* `() => null,` (where it says CHANGE THIS). Put your cursor at the end of this SQL query.
* Press the format button. Part of the query is selected. However that doesn't happen if you put
* the cursor anywhere else.
*/
const text = `SELECT * FROM airplanes WHERE 2 < quantity`;
// Hover on each property to see its docs!
const editor = monaco.editor.create(document.getElementById("container"), {
value: text,
language: "sql",
automaticLayout: true,
});
const button = document.querySelector('#format-button')
button.addEventListener('click', () => {const model = editor.getModel();
if (!model) {
return;
}
// Turn every other space into an indented newline.
const formattedValue = editor.getValue().replace(/([^ ]+ +[^ ]+) +/g, '$1\n ');
const endPosition = model.getPositionAt(model.getValueLength());
const cursorIsAtEnd = editor.getSelection()?.equalsRange(monaco.Range.fromPositions(endPosition));
// editor.executeEdits() has the same bug when the computer returns null, but does allow you to actually specify a different computer.
model.pushEditOperations(
[],
[
{
text: formattedValue,
range: {
endColumn: endPosition.column,
endLineNumber: endPosition.lineNumber,
startColumn: 1,
startLineNumber: 1,
},
},
],
// CHANGE THIS
// () => null,
() => [new monaco.Selection(4, 13, 4, 13)],
);
new Promise((resolve) => {
editor.focus(); // Focus so we can see where the cursor goes.
// if (cursorIsAtEnd) { // A hack to fix the cursor position.
// editor.setPosition(model.getPositionAt(model.getValueLength() + 1));
// }
resolve();
});
});
// HTML:
<div>
<div id="container" style="height: 300px"></div>
<button id='format-button'>format</button>
</div>
Reproduction Steps
- Click the editor to put the cursor somewhere. For example, you can put it at row 1 column 1.
- Click the format button.
Actual (Problematic) Behavior
The cursor ends up somewhere unexpected. For example if you put it at row 1 column 1 earlier, it stays there.
Expected Behavior
The cursor jumps to row 4 column 13 (the end of the text)
Additional Context
The playground linked demonstrates two different bugs, but the first bug mentioned in there was fixed in 0.35.0. This bug wasn't.
If it's not a bug, that means the documentation for ITextModel.pushEditOperations() is incorrect as it says you can pass in your own cursor state computer.
This bug does not occur for IStandaloneCodeEditor.executeEdits(), which does use the cursor state computer.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked Monaco Editor playground and reproduce the issue using the provided JavaScript and HTML code. Verify that ITextModel.pushEditOperations() applies the supplied cursor state computer and places the cursor at row 4, column 13, while preserving the documented behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100