microsoft / microsoft/monaco-editor
[Bug] Inline Completions doesn't respect word wrapping when rendering (ghost text) parts of an inline suggestion as additional lines (using view line)
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
monaco.languages.registerInlineCompletionsProvider("javascript", {
freeInlineCompletions(completions) {
console.log('free', completions)
},
handleItemDidShow(completions, item, updatedInsertText) {
console.log('show', completions, item, updatedInsertText)
},
handlePartialAccept(completions, item, acceptedChars) {
console.log('partial', completions, item, acceptedChars);
},
provideInlineCompletions(model, position, context, token) {
const allTokens = monaco.editor.tokenize(model.getValue(), 'javascript');
const tokens = position.lineNumber - 2 >= 0 ? allTokens[position.lineNumber -2] : [];
console.log(context)
if (tokens.length === 0) {
return {
items: []
}
}
console.log(position, allTokens)
for (let i = 0; i < tokens.length; i++) {
const low = tokens[i].offset;
const high = i +1 < tokens.length ? tokens[i+1].offset-1 : model.getLineContent(position.lineNumber).length-1;
const isInrange = position.column - 2 >= low && position.column - 2 <= high;
if (tokens[i].type.includes("comment")) {
return {
items: [{
insertText: 'File(1,2,\n3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,)',
command: {
id: 'test',
title: 'Invoke Cmd'
},
range: monaco.Range.fromPositions({
lineNumber: position.lineNumber,
column: 1
}, {
lineNumber: position.lineNumber,
column: model.getLineMaxColumn(position.lineNumber)
})
}],
enableForwardStability: true,
};
}
}
return {
items: [],
enableForwardStability: true
};
}
})
const value = /* set from `myEditor.getModel()`: */ `// k
`;
// Hover on each property to see its docs!
const myEditor = monaco.editor.create(document.getElementById("container"), {
value,
language: "javascript",
automaticLayout: true,
scrollbar: {
horizontal: "hidden"
},
wordWrap: "on",
wordWrapColumn: 10,
inlineSuggest: {
enabled: true,
mode: 'prefix',
keepOnBlur: true
}
});
Reproduction Steps
- Create a monaco editor instance with a wordWrap set to on or set to wordWrapColumn but then also set the wordWrapColumn to a number
- Register a inline completions provider for the language used when creating an editor. If the language was a custom one then you may need to register the language using monaco.languages.register. For the reproduction of bug, using "javascript" is okay
- In your inline completions provider, implement provideInlineCompletions and returns a suggestion that has a new line character somewhere in between the insertText and the line after \n has a lot of characters such that it cannot be fit into the current width of the editor
- Make sure to enable the inline completions when creating editor using inlineSuggest option in editor options
- Now play the code in the playground and trigger an inline completion depending on how you set it up and get that suggestion with new lines to show up
- You will notice that the line after \n in the suggestion which has a lot of characters would only partially be visible in the small width editor and overflown parts would be hidden
Actual (Problematic) Behavior
Monaco's inline completion provider renders a inline completion suggestion using a combination of decoration and view zone which has the view lines. The first line is typically rendered as a decoration and any additional lines in the suggestion introduced by "\n" is rendered as a view line inside a view zone. If the additional line is very large in number of characters and editor has a fixed width or small width, it overflows the editor and is hidden. When you accept the suggestion fully, the whole suggestion is inserted and word wrapped according to how word wrapping is configured during the creation of editor. However this only happens when a suggestion is accepted. The rendering of "additional lines" in the suggestion as a ghost text should take wrapping into the account
In the example below, i have an insert Text 'File(1,2,\n3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,3,34,)'. When this appears as a ghost text, anything after first "\n" is rendered using a view line inside a view zone and it would overflow the editor's width if it is small enough. The rendering here should respect word wrap options configured for the editor. Those are respected when you accepted the suggestion but not when it is rendered
Expected Behavior
Word wrapping should be respected when rendering additional lines in the suggestion appearing as a ghost text so it doesn't overflow the editor and becomes invisible
Additional Context
No response
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 Monaco Editor Playground link and the inline completions provider's provideInlineCompletions reproduction, using wordWrap and wordWrapColumn with a multiline suggestion. Verify how additional ghost-text lines are rendered in the narrow editor, then confirm that long lines wrap instead of overflowing or being hidden while the accepted suggestion retains the expected wrapping.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- devtools, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100