The outputChannel

moon indicating dark mode
sun indicating light mode

Custom Command Palette & Context Menu Commands with Monaco Editor

June 24, 2020

As many of us know, monaco-editor is the underlying editor used in vscode, codesandbox, many awesome deveoper IDE tools!

One of the most vscode-familiar features to monaco is the command palette and right click context menu.

Many of the default options are familiar from vscode.

Assumptions

you already have a monaco editor instance

const editor = monaco.editor.create(document.getElementById("editor"), {
language: "graphql",
})

and something for it to do:

async function doSomethingNeat() {
await doSomething()
}

Command Palette

The command palette is the first step when adding an action. All registered actions are available in the command palette, which is available when you press F1 in an editor context, or when you select command palette from the right click context menu.

Screenshot of a Monaco Editor Command Palette

The minimum you need is to invoke addAction() when using the IStandaloneCodeEditor instance.

editor.addAction({
id: "something-neat",
label: "Something Neat",
run: doSomethingNeat,
})

These are the minimal configurations to have a command palette entry. You can use any option in IActionDescriptor

You can add keybindings to the descriptor as well:

import { KeyCode, KeyMod } from "monaco-editor"
const myAction: monaco.editor.IActionDescriptor = {
id: "something-neat",
label: "Something Neat",
keybindings: [
// eslint-disable-next-line no-bitwise
KeyMod.CtrlCmd | KeyCode.Enter, // Ctrl + Enter or Cmd + Enter
// eslint-disable-next-line no-bitwise
KeyMod.CtrlCmd | KeyCode.KEY_R, // Ctrl + R or Cmd + R
],
run: doSomethingNeat,
}
editor.addAction(myAction)

You’ll need to access the bitwise enum for monaco.KeyMod and monaco.KeyCode

The pipe character is used to seperate multiple commands in a sequence, and the array allows you to add multiple shortcuts to one action descriptor

You may have an eslint rule no-bitwise enabled, the example shows you how to disable it.

Adding your action to the context menu

Now that’s pretty handy, but what if your users arent familiar with pressing F1 to access the full command palette?

What if you want to make an important action available in the right click context as well?

Screenshot of a Monaco Editor Context Menu

You just need to add two more options to our action descriptor from above:

const myAction: monaco.editor.IActionDescriptor = {
id: "something-neat",
label: "Something Neat",
contextMenuOrder: 0, // choose the order
contextMenuGroupId: "operation", // create a new grouping
keybindings: [
// eslint-disable-next-line no-bitwise
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
],
run: doSomethingNeat,
}
editor.addAction(myAction)

contextMenuGroupId or contextMenuOrder seem to be the minimum options needed, though you can use them together for a highly configurable result


The development blog of Rikki Schulte.
Gatsby.js brought me on to maintain developer tools like GraphiQL & the GraphQL LSP
Black Lives Matter!
(twitter) - (github)