microsoft / microsoft/monaco-editor

[Bug] `ITextModel.pushEditOperations()` ignores the `cursorStateComputer`

Open
#3,893 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug editor-core
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?
Monaco Editor Playground Link

https://microsoft.github.io/monaco-editor/playground.html?source=v0.38.0#XQAAAALTCAAAAAAAAABBqQkHQ5NjdSNGhUhUxNEwRL2GMUhw6pCZJCDWJJhyCaKVgxNeM8iCx0E9E4a-mKwIul4QAk9NFy7MudALOtvLWko4s3KgoVWxe8qTre1eDzQUZp_qF4Zg57dt7B7fo5-tdXoLRWpOaCINVGYwPvTOmab6-dYYXCV_N236iAtG6eYe7h18DePOoFqObf2gZ5JAjW023fXQSc_b13d3tjaF1Ql03WcPwoZ-LUY-iFbPQLZmNOzTVjc-qj7AP4feXYqsP03-NFPU9Cd5LIGYowVz0MYqkDOycLMUPWJFochl2RpwphNkXcwpF8zUpAPBJI4QZ65ulALzWkbUw8GLCRRb_doVXuJy_fTQT2N_FT4RtTI2OiUKxKCSE6BcIaCiBydS6XReT-pbXNsABxbXpr8qaFcqgyE1C3XYL2ZY5KkbVQIrZMTejO98tzipBPSflvcvgbVJoouFrIeDvtxOM1lGIq5c-ocrjQu_zoHXjf_xWz7Hstj8aEf6vvKFzEGzbJpvYJEt6LUGDMuNVJthlZh8cWgeWP1lzt36lbQg8FMujh5sfXF5uorwSYlUN47WjpKO-3iRajV7LwozFDPn74M60SMxkdSjB1u7VbWWyZyFQicC9opzohvdfvPnrTHBXkiKX7_Q8vtp4EN_JCkf6sDEmD4pNK4PNXt1zM9PQQFWLRRBsnwZnI2la4AkNKppF6cfjTAMqP-VEuUf3k49oEbZ2SjMe4pBxMDRf036XwjQULoGcj0NuZR9vteUKzlzYa-GlUrmr8cZXAlMxU6EnjLoq3PFV_AslHRERn6O-PTat4SQLLOL-MMCAAsfuRGJTbIXWVwBlAdONIn4ZKUvYvn4skg7W8HPC3Ppac8X_5OhLSuzDy-fEKrwxHDAi6f5vrqk9Q5ulrecK7BIV7n_4-zlkuA33_qn65cZawKHfIuWC3vJTbg2AQkAVXbmA4jH5CHV7oJYkfg0dlmmREp20IwuXJW7FD5BTEIgk9kfAQwlB57na3IUs-1r3labOoB8l28Qz8f_eKlBThDpyiBTZ9QG5hliC4R3cniERfbAx69mv8bY18mzlWkgZwvzPt4rBwCBtAqRS3YzgsEFmm04dQR1PCdIFhpB68ky1Q3r6w_vxJ3kd81b7xiZHK6xbPRjsxd-XBp9llFBvqkwKa3V8FDwZWtJ-7hHLZJi6x4P41H4wtri08Os0UAhaVF9xDONm21vRYUF-xlxdDBS3qcoBV_FqpahxaV50kZACasMXqY0o859d7xyyPEQZmb3LG7HTqWCfE1n3r4Lgi_dBvVr40mAEGFFJwU8W_kfK3CjdR1aNifw0SpQNs_vdyh2VHJ3x1fpdufTRZcFDIEISGFje_cYIS9W7StmoKNytHMko639UUkHBW_UvXTTmPFDfu8KHdL6mg-a8lzIx8xX1mZMFGj3lH4ktFIgtywcBXK8p8ySGxohmGKURkwL-AzrKMIXcauhgOceUo73BKFneuq9QzmgDow1zhKixM9dco_zBNL6bfT0Gy1vlLpPPGv65QNikD0Plbjeu7tl2Y01BpfcGeyYJmf_TyVtAA

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
  1. Click the editor to put the cursor somewhere. For example, you can put it at row 1 column 1.
  2. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.