monaco-editor icon indicating copy to clipboard operation
monaco-editor copied to clipboard

[Bug] Inline Completions doesn't respect word wrapping when rendering (ghost text) parts of an inline suggestion as additional lines (using view line)

Open akshar2401 opened this issue 1 year ago • 0 comments

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.46.0-dev-20231214#XQAAAALVCAAAAAAAAABBqQkHQ5NjdMjwa-jY7SIQ9S7DNlzs5W-mwj0fe1ZCDRFc9ws9XQE0SJE1jc2VKxhaLFIw9vEWSxW3yscxEzaY9pFi8P_6bKVy3lY60hFpWPMUOO_jYSVTqzFY4uAS1kNQSAEumREFdPhvHweapw18pA60AvnbnqfkAVl1MfKAk4gGXrSC2Hq4o_fMmhaJ2FfRSQYJIXWaTDA4OIwJx6MXaMYjOZcB6LaWDAhR0h9qZymdbOrnqhiADBNwmekrO_bMwxkuv6uKOl7VJl1n_X1OdPzuvDgiF4RVz75xpntYS6oGkKT4bFFbDOE-hUCLeXJ1eth09Nqppg7xNT9cCzHnTV2_cnnI4w9pSS3ojXSpjR5817l7EYPIeHHvofI02ZF9X2rskNoWFGa-myp2k6KR8rZMVXqzFaCeorzl7VACo34SsSs3D3eZxMblwbtfktJ9vTnhtWc2ktWKee2ca0_Pgbk4WaHJQbo6oxq3PhXrC3azi5MC5x9ELedAKdW7LaP4r4nPFq4A_ix-T1T3ciRF2P_iSR8Zt0jBYxzRgVTHC3GsmLyL7zNmvkjB4GFqHGdv6ozC_BNl2ThNSJjWEUO7Ybpg1VXUAWqnaaGTKoOkSUlxhJ8iCzYGIIwHF-VymnyBlrOWWxikNDei4FyOojdEhXywxWIIsn7eQWjze-njF7CdNFmsSGgMNkhZYtTFESvmJSz5tvKvSvo16z1WPFrkyRny2vnb3G48R95uJYMM9M8LZEA2GOCCuScPjcNVf8qG1CpXiaTDGRZbfIFxV5fPMts-0NndDONtYNzEbcEeBQ3GuFi4FAM_Sv8GwKPp-37EuUhQ9NsuoZZRbIK23XzvQ-2eJvJc7ZfALkQUY2tYF9_sGtMBaOU6arKI8KMODjGfv0AyZBMHP8FXp6WqsTcA7mwBVLmd6AKHhbsbe-I0ZN-E95BXDM_KOkQ0k3Wlx7osyIphAYcUoDiX-ssPgIuAqmBPCPkJSuxcOIYnuJNZSjuvxHffluCcVKBG2fvpfDCUXRV5slpKpXIZjvV6n_VyXWf0iBvgA_qWOQwTlD0c7RvAMAy1BnM313C38hw6IkVXel70D7w9bsZXLpX8fbApoABDeZDHAWppaQYilvtrkzOhdgFdFa1JqvAomBwKgaY33Tbo3O1iG1hLwpxgOUjsgRvFQ00Flh3hhIovCw1NIp8zCDR3lQPJxxvilriw23hAMswzIBeoYYUFB-fhCvOzbPtYf_3WXvk

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

  1. Create a monaco editor instance with a wordWrap set to on or set to wordWrapColumn but then also set the wordWrapColumn to a number
  2. 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
  3. 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
  4. Make sure to enable the inline completions when creating editor using inlineSuggest option in editor options
  5. 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
  6. 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

InlineCompletionWrappingBug

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

akshar2401 avatar May 02 '24 13:05 akshar2401