-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API to configure all keybindings #102
Comments
Just mentioning that the workaround to unbind keyboard shortcuts as mentioned in e.g. #1350 throws an error now. This changed sometime in the last version or two. I had to pass an empty handler:
Here's the error I was getting:
Hope this helps someone else! |
I had the same problem after the update, but also got an error because I passed Edit: @codebykat Reading your comment again while not having a fading migraine I now see that you posted a solution and not a question. So I'm terribly sorry if I hopped in here unsolicited and edited the first part of my comment accordingly 🙇♂️ Edit (number 5362 😅): Turns out my only problem was indeed only the missing command handler (the fix for #1857 made that mandatory) and passing Addition: class CodeEditor {
//...
/**
* CAUTION: Uses an internal API to get an object of the non-exported class ContextKeyExpr.
*/
static get ContextKeyExpr(): Promise<monaco.platform.IContextKeyExprFactory> { // I defined these types myself elsewhere
return new Promise(resolve => {
window.require(["vs/platform/contextkey/common/contextkey"], (x: { ContextKeyExpr: monaco.platform.IContextKeyExprFactory }) => {
resolve(x.ContextKeyExpr);
});
});
}
private patchExistingKeyBindings() {
this.patchKeyBinding("editor.action.quickFix", monaco.KeyMod.Alt | monaco.KeyCode.Enter); // Default is Ctrl+.
this.patchKeyBinding("editor.action.quickOutline", monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_O); // Default is Ctrl+Shift+O
this.patchKeyBinding("editor.action.rename", monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_R, monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_R)); // Default is F2
}
private patchKeyBinding(id: string, newKeyBinding?: number, context?: string): void {
// remove existing one; no official API yet
// the '-' before the commandId removes the binding
// as of >=0.21.0 we need to supply a dummy command handler to not get errors (because of the fix for https://github.com/microsoft/monaco-editor/issues/1857)
this.editor._standaloneKeybindingService.addDynamicKeybinding(`-${id}`, undefined, () => { });
if (newKeyBinding) {
const action = this.editor.getAction(id);
const when = ContextKeyExpr.deserialize(context);
this.editor._standaloneKeybindingService.addDynamicKeybinding(id, newKeyBinding, () => action.run(), when);
}
} |
Thanks @spahnke! This was super helpful in getting my own implementation to work. For other weary travellers, here is my solution. I only needed to change the keyboard shortcuts, not update the context so I bypassed the import { editor } from 'monaco-editor'
import { CommandsRegistry } from 'monaco-editor/esm/vs/platform/commands/common/commands'
export const updateKeyBinding = (
editor: editor.ICodeEditor,
id: string,
newKeyBinding?: number,
) => {
editor._standaloneKeybindingService.addDynamicKeybinding(`-${id}`, undefined, () => {})
if (newKeyBinding) {
const { handler, when } = CommandsRegistry.getCommand(id) ?? {}
if (handler) {
editor._standaloneKeybindingService.addDynamicKeybinding(id, newKeyBinding, handler, when)
}
}
} and here are the types I created. import { IDisposable, editor as editorBase, IEditorAction } from 'monaco-editor'
declare module 'monaco-editor' {
export namespace editor {
export interface StandaloneKeybindingService {
// from: https://github.com/microsoft/vscode/blob/df6d78a/src/vs/editor/standalone/browser/simpleServices.ts#L337
// Passing undefined with `-` prefixing the commandId, will unset the existing keybinding.
// eg `addDynamicKeybinding('-fooCommand', undefined, () => {})`
// this is technically not defined in the source types, but still works. We can't pass `0`
// because then the underlying method exits early.
// See: https://github.com/microsoft/vscode/blob/df6d78a/src/vs/base/common/keyCodes.ts#L414
addDynamicKeybinding(
commandId: string,
keybinding: number | undefined,
handler: editorBase.ICommandHandler,
when?: ContextKeyExpression,
): IDisposable
}
export interface ICodeEditor {
_standaloneKeybindingService: StandaloneKeybindingService
}
}
} |
Hey guys! I'm a bit unsure about how to change the Command Pallet to Using @keegan-lillo's approach, I have Sorry for the confusion 🙏 |
@fractalhq You're almost there! Monaco has some very clever (yet not super obvious) ways of doing keybindings where it uses the binary representation of the number to describe the keybinding. To add modifier keys, you use a bitwise OR. updateKeyBinding(editor, 'CommandPalette', KeyMod.CtrlCmd | KeyCode.KEY_P) Internally it looks like this: /**
* Binary encoding strategy:
* ```
* 1111 11
* 5432 1098 7654 3210
* ---- CSAW KKKK KKKK
* C = bit 11 = ctrlCmd flag
* S = bit 10 = shift flag
* A = bit 9 = alt flag
* W = bit 8 = winCtrl flag
* K = bits 0-7 = key code
* ```
*/
export const enum KeyMod {
CtrlCmd = (1 << 11) >>> 0,
Shift = (1 << 10) >>> 0,
Alt = (1 << 9) >>> 0,
WinCtrl = (1 << 8) >>> 0,
}
so when we OR them together you get:
|
I have a similar issue like #685 I want to change the show suggestion command to Tab. and I'm able to do so. but I do not want to show suggestions when the line is empty. and if there is no direct way to achieve this, what is the workaround? A working code snippet will be much helpful |
Hi! Here is my code, so far:
I'm only missing some way of changing |
You can use the existing editor.addCommand(monaco.KeyCode.Space, () => editor.trigger('', 'hideSuggestWidget', null), 'suggestWidgetVisible'); |
@spahnke Working perfectly, thanks! |
I found this solution (not working with Ctrl+P 😢) const removeKeybinding = (editor, id) => {
editor._standaloneKeybindingService.addDynamicKeybinding(`-${id}`, undefined, () => {})
}
const addKeybinding = (editor, id, newKeyBinding) => {
if (newKeyBinding) {
const action = editor.getAction(id)
const ContextKeyExpr = new Promise(resolve => {
window.require(['vs/platform/contextkey/common/contextkey'], x => {
resolve(x.ContextKeyExpr)
})
})
ContextKeyExpr.then(ContextKeyExprClass => {
editor._standaloneKeybindingService.addDynamicKeybinding(id, newKeyBinding, () => action.run(), undefined)
});
}
}
removeKeybinding(editor, 'editor.action.quickCommand')
addKeybinding(editor, 'editor.action.quickCommand', monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter) Edit: To use Ctrl + Shift + P with chrome, use this: window.addEventListener('keydown', function(event) {
if (event.keyCode === 80 && (event.ctrlKey || event.metaKey) && !event.altKey && (!event.shiftKey || window.chrome || window.opera)) {
event.preventDefault();
if (event.stopImmediatePropagation) {
event.stopImmediatePropagation();
} else {
event.stopPropagation();
}
editor.trigger('ctrl-shift-p', 'editor.action.quickCommand', null)
return;
}
}, true); |
Since 0.34.1, |
Can you please provide a small example of how it works? |
@r0b3r4 for example, we have this snippet running when we initialize our app, here we configure ...
// editor.defineTheme(...);
// do some other things
...
editor.addKeybindingRules([
{
// disable show command center
keybinding: KeyCode.F1,
command: null,
},
{
// disable show error command
keybinding: KeyCode.F8,
command: null,
},
{
// disable toggle debugger breakpoint
keybinding: KeyCode.F9,
command: null,
},
]); |
@akphi This is just awesome, thanks! |
Many VS Code language extensions include keybindings like:
In
monaco-editor
, there doesn't appear to be any way to do the same. You can intercept the.
key, but thetrigger
andcommand
APIs on the standalone editor don't recognize^acceptSelectedSuggestion
.Is there a way to configure keybindings similar to VS Code extensions?
Would it be reasonable to expose the settings API in
monaco-editor
, and add API for loading settings from JSON strings, perhaps?The text was updated successfully, but these errors were encountered: