上一篇:使用Theia——创建语言支持

命令和快捷键

  Theia可以通过多种不同的方式进行扩展。命令允许packages提供可以被其它包调用的唯一命令,还可以向这些命令添加快捷键和上下文,使得它们只能在某些特定的条件下被调用(如窗口获取焦点、当前选项等)。

在Theia中添加命令

CommandContribution类,如:

java-commands.ts


@injectable()
export class JavaCommandContribution implements CommandContribution {
...
    registerCommands(commands: CommandRegistry): void {
        commands.registerCommand(SHOW_JAVA_REFERENCES, {
            execute: (uri: string, position: Position, locations: Location[]) =>
                commands.executeCommand(SHOW_REFERENCES.id, uri, position, locations)
        });
        commands.registerCommand(APPLY_WORKSPACE_EDIT, {
            execute: (changes: WorkspaceEdit) =>
                !!this.workspace.applyEdit && this.workspace.applyEdit(changes)
        });
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.


  每一个contribution需要提供一个唯一的命令id,以及一个命令处理程序(由回调函数执行)。


  将contribution绑定到CommandContribution。


  然后将contribution的类注入到适当的模块中(确保类被标记为@injectable()),像这样:


java-frontend-module.ts


export default new ContainerModule(bind => {
    bind(CommandContribution).to(JavaCommandContribution).inSingletonScope();
    ...
});
  • 1.
  • 2.
  • 3.
  • 4.



CommandRegistry,通过get commandIds()

添加快捷键



  默认情况下不需要给命令添加快捷键,因为它可以通过许多不同的方式来调用(通过编程方式或者用户点击)。不过,我们仍然可以将具有特定上下文的快捷键绑定到命令上以完成相同的命令功能。



KeybindingContribution的实现。



editor-keybinding.ts



@injectable()
export class EditorKeybindingContribution implements KeybindingContribution {

    constructor(
        @inject(EditorKeybindingContext) protected readonly editorKeybindingContext: EditorKeybindingContext
    ) { }

    registerKeybindings(registry: KeybindingRegistry): void {
        [
            {
                command: 'editor.close',
                context: this.editorKeybindingContext,
                keybinding: "alt+w"
            },
            {
                command: 'editor.close.all',
                context: this.editorKeybindingContext,
                keybinding: "alt+shift+w"
            }
        ].forEach(binding => {
            registry.registerKeybinding(binding);
        });
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.



commandId必须是预先注册好的命令,而且必须唯一。 context是一个简单的类,用于确保命令和快捷键的绑定组合在特定条件下是可用的。对于编辑器而言,它看起来是这样的:



editor-keybinding.ts



@injectable()
export class EditorKeybindingContext implements KeybindingContext {
    constructor( @inject(EditorManager) protected readonly editorService: EditorManager) { }

    id = 'editor.keybinding.context';

    isEnabled(arg?: Keybinding) {
        return this.editorService && !!this.editorService.activeEditor;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.



isEnabled()方法会根据给定的条件返回true或false。请注意,context是一个可选参数,如果没有提供,则默认为 NOOP_CONTEXT。使用该context注册的快捷键将始终保持开启状态,可以在应用程序的任何地方使用。



id而言,参数 keycode是必须的,它是一个包含实际快捷键绑定的结构。下面是一个正确的结构:



keys.ts



export declare type Keystroke = { first: Key, modifiers?: Modifier[] };



Modifier.M1在OS X上是Command而在Windows/Linux上是CTRL。Key字符串常量定义在keys.ts中。

将contribution绑定到KeybindingContribution



  与绑定命令contribution一样,快捷键contribution也需要按模块进行绑定,像这样:



editor-frontend-module.ts



export default new ContainerModule(bind => {
    ...
    bind(CommandContribution).to(EditorCommandHandlers);
    bind(EditorKeybindingContext).toSelf().inSingletonScope();
    bind(KeybindingContext).toDynamicValue(context => context.container.get(EditorKeybindingContext));
    bind(KeybindingContribution).to(EditorKeybindingContribution);
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.