profile
viewpoint

Ask questionsRegistering/Providing custom Commands/CodeActions

I am creating an editor which uses some language server implementation in JS. It provides two methods: getCodeActions(...): Command[] and executeCommand(...): .... The first one gets the possible code actions on a position. This is essentially what the CodeActionprovider#provideCodeActions method does. The latter gets the TextEdits when a command is actually executed (and applies them to the workspace using applyEdit). There is no pendant in the public monaco API for that.

As provideCodeActions can also return CodeAction[], it is possible to compute the TextEdits while providing the code actions. However, as this happens on basically every key press, this could get really heavy.

I've tried using non-public API. In this approach, I'm registering the commands and the handlers as soon as the editor is initialized:

(editor as any)._commandService.addCommand({ 
		id: "command-id", 
		handler: (_: any, ...args: any[]) => {
			return myLspService.executeCommand("command-id", args);
		},
});

As this is a private API this feels very hacky. Is there a better solution for this? If not, what is the recommended way of doing this?

I think the easiest way for Monaco's API consumers would be to extend the CodeActionProvider to something like this:

export interface CodeActionProvider {
	provideCodeActions(
		model: editor.ITextModel, 
		range: Range, 
		context: CodeActionContext,
		token: CancellationToken
	 ): (Command | CodeAction)[] | Thenable<(Command | CodeAction)[]>;
	executeCommand(
		model: editor.ITextModel, 
		command: string, 
		args: any[], 
		token: CancellationToken
	): CodeAction[] | Thenable<CodeAction[]>; // or return void | Thenable<void> and apply the command using model.pushEditOperations()
}
microsoft/monaco-editor

Answer questions ToonvanStrijp

@jrieken, @nikeee can you explain me how I add conditions to the command when using:

(editor as any)._commandService.addCommand({ 
		id: "command-id", 
		handler: (_: any, ...args: any[]) => {
			return myLspService.executeCommand("command-id", args);
		},
});
useful!

Related questions

Monarch: How do you add "@keywords" key to "language object"? (undocumented) hot 3
How to get the line count including line wraps hot 2
Error: Cannot find module 'monaco-editor/esm/vs/editor/contrib/gotoSymbol/goToCommands' hot 2
Removing the tooltip on the read-only editor that says &#39;cannot edit in read-only editor&#39; hot 1
Monaco paste event hot 1
Error: Cannot find module 'monaco-editor/esm/vs/editor/contrib/goToDefinition/goToDefinitionCommands' hot 1
TypeScript declaration preview from extra lib results in error hot 1
Editor props/extends the actual width of the parent that is a flexbox item hot 1
Problem with insane.js while using monaco-editor@0.18.0 hot 1
Change the language of an existing editor hot 1
javascript/typescript typedefs lost when webworker times out hot 1
Can't scroll in firefox hot 1
How to add simple custom language support? hot 1
monaco-editor polute the global variables, making incompatible with other JS libraries, such as CodeMirror, RequireJS, SeaJS, etc. hot 1
Highlight merge conflicts in monaco like in VSCode hot 1
Github User Rank List