上一篇: 使用Theia——创建语言支持
Theia可以通过多种不同的方式进行扩展。命令允许packages提供可以被其它包调用的唯一命令,还可以向这些命令添加快捷键和上下文,使得它们只能在某些特定的条件下被调用(如窗口获取焦点、当前选项等)。
要将命令添加到Theia,必须实现 CommandContribution 类,如:
@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) }); } }
每一个contribution需要提供一个唯一的命令id,以及一个命令处理程序(由回调函数执行)。
将contribution绑定到CommandContribution。
然后将contribution的类注入到适当的模块中(确保类被标记为@injectable()),像这样:
java-frontend-module.ts
export default new ContainerModule(bind => { bind(CommandContribution).to(JavaCommandContribution).inSingletonScope(); ... });
负责注册和执行命令的类是 CommandRegistry ,通过 get commandIds() api可以获取命令列表。
默认情况下不需要给命令添加快捷键,因为它可以通过许多不同的方式来调用(通过编程方式或者用户点击)。不过,我们仍然可以将具有特定上下文的快捷键绑定到命令上以完成相同的命令功能。
要添加快捷键,只需要注入一个 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); }); } }
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; } }
context也有一个唯一的id,用于在上下文中将快捷键注册到命令中。 isEnabled() 方法会根据给定的条件返回true或false。请注意,context是一个可选参数,如果没有提供,则默认为 NOOP_CONTEXT 。使用该context注册的快捷键将始终保持开启状态,可以在应用程序的任何地方使用。
对于 id 而言,参数 keycode 是必须的,它是一个包含实际快捷键绑定的结构。下面是一个正确的结构:
keys.ts
export declare type Keystroke = { first: Key, modifiers?: Modifier[] };
Modifier是平台无关的,所以 Modifier.M1 在OS X上是Command而在Windows/Linux上是CTRL。Key字符串常量定义在 keys.ts 中。
与绑定命令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); });