theia 命令、菜单和快捷键绑定
命令是由 ID 和要执行的函数定义的可运行操作(加上一些可选参数,如名称或图标)。命令可以通过命令面板触发,也可以绑定到快捷键或菜单项,并且可以以编程方式调用。命令触发的动作可以是上下文相关的,因而它们只能在特定条件下调用(比如窗口获得焦点、或者当前选中文本等)。
以下部分提供有关如何提供命令、快捷键绑定和菜单项的详细信息。这些部分将描述如何连接不同的“贡献”以及如何使用相应的服务来管理这些项目。
如果您还不熟悉 Theia 中的贡献点或依赖注入的使用,请查看有关服务和贡献的文章(https://www.cnblogs.com/theia-ide/p/16476556.html)。
以下所有代码示例均来自 Theia 扩展生成器(https://github.com/eclipse-theia/generator-theia-extension)。您可以通过安装生成器、选择“Hello World”示例并选择“helloworld”作为名称来获得相同的代码。
贡献命令
通过提供命令,您可以向 Theia 添加自定义操作。 用户可以通过命令面板、快捷键绑定或菜单项触发命令。 也可以通过编程方式调用。
Theia 应用程序的所有命令都在 CommandRegistry 中进行管理。 要向命令注册表贡献命令,模块必须实现 CommandContribution 接口(参见下面的代码示例)。
命令是具有 id 和可选的用户可见标签的对象(参见下面示例中的 HelloworldCommand)。 命令贡献接收 registerCommands 函数中的 CommandRegistry 作为参数。 然后可以通过在此注册表上调用 registerCommand 来注册该命令。 除了命令之外,还需要提供一个回调,该回调在命令被触发时执行(CommandHandler)。 在下面的示例中,该命令使用 MessageService 来“打招呼”。
helloworld-contribution.ts
export const HelloworldCommand: Command = { id: 'Helloworld.command', label: "Say Hello" }; @injectable() export class HelloworldCommandContribution implements CommandContribution { constructor( @inject(MessageService) private readonly messageService: MessageService, ) { } registerCommands(registry: CommandRegistry): void { registry.registerCommand(HelloworldCommand, { execute: () => this.messageService.info('Hello World!') }); } }
为了使命令执行对上下文敏感,CommandHandler 可以选择实现 isEnabled 和 isVisible。您可以选择注册多个 CommandHandler 并让命令根据当前上下文执行其中一个。要为命令注册其他处理程序,请使用 CommandRegistry 上的 registerHandler 函数。执行命令时,命令注册表会检查所有已注册的处理程序。第一个在 isEnabled 上返回 true 的处理程序将被视为处于活动状态,并将被执行。但是,只有一个处理程序应该同时处于活动状态(isEnabled === true)。 isVisible 控制连接到命令的菜单项和工具项的可见性,以及命令是否显示在命令面板中。如果活动处理程序返回 true,则菜单项将可见,反之亦然。最后,通过实现 isToggle 处理程序可以选择指定连接到命令的菜单项是打开还是关闭。
将贡献绑定到 CommandContribution
为了使 Theia 可以访问我们的 CommandContribution,我们需要将自定义 HelloworldCommandContribution 绑定到相应的贡献符号 CommandContribution。这是在 helloworld-frontend-module 中完成的,有关更多详细信息,请参阅服务和贡献。
helloworld-frontend-module.ts
export default new ContainerModule(bind => { // add your contribution bindings here bind(CommandContribution).to(HelloworldCommandContribution); ... });
上面的CommandRegistry,用于注册我们贡献命令的 ,CommandRegistry也提供了与命令交互的 API。例如,您可以以编程方式执行命令,可以浏览所有已注册的命令,也可以访问最近执行的命令列表。有关详细信息,请参阅 CommandRegistry 的 TypeDoc(https://eclipse-theia.github.io/theia/docs/next/classes/core.commandregistry-1.html)。要在贡献之外使用 CommandRegistry,您可以通过依赖注入访问它。
在以下部分中,我们将描述如何将命令绑定到菜单项和键绑定。
贡献菜单项
Theia 允许您添加菜单项,菜单项将显示在 Theia 应用程序中特定菜单中。菜单项绑定到命令,因此允许用户触发操作(请参阅上面有关命令的部分)。
以下所有代码示例均来自 Theia 扩展生成器。您可以通过安装生成器、选择“Hello World”示例(参见此处)并选择“helloworld”作为名称来获得相同的代码。
Theia 应用程序的所有菜单项都在 MenuModelRegistry 中进行管理。要向注册表贡献菜单项,模块必须实现“MenuContribution”接口(参见下面的代码示例)。
该命令的注册可以在函数 registerMenus 中完成,该函数将由 Theia 框架调用。该函数提供 MenuModelRegistry 作为参数。在这个注册表上,我们可以调用 registerMenuAction。它需要一个 MenuPath 和一个 MenuAction。 MenuPath 指定要放置菜单项的菜单(和子菜单)。请参阅此处了解一些常用菜单的路径。
MenuAction 包含一个命令 id,指定要触发的命令,以及一个可选标签,指定菜单项的标签。
helloworld-contribution.ts (这个文件用于创建一个菜单项)
@injectable() export class HelloworldMenuContribution implements MenuContribution { registerMenus(menus: MenuModelRegistry): void { menus.registerMenuAction(CommonMenus.EDIT_FIND, { commandId: HelloworldCommand.id, label: HelloworldCommand.label }); } }
为了使 Theia 可以访问我们的 MenuContribution,我们需要将自定义 HelloWorldMenuContribution 绑定到相应的贡献符号 MenuContribution。 这是在 helloworld-frontend-module 中完成的,有关更多详细信息,请参阅服务和贡献。
helloworld-contribution.ts(这个文件用于把我们创建的菜单告诉theia,这样theia启动时就会把这个菜单项加载进来)
export default new ContainerModule(bind => { bind(MenuContribution).to(HelloworldMenuContribution); ... });
请注意,您还可以在没有命令的情况下提供菜单项,这样可以您创建自定义顶级菜单和子菜单。要实现这一点,请在没有命令的情况下贡献一个菜单项,然后在其他贡献中将此菜单项的 id 作为 MenuPath 引用。这会将菜单项添加到您的自定义菜单中。
快捷键绑定
快捷键绑定允许用户使用特定的组合键触发命令。键绑定可以定义条件,指定它们何时处于活动状态。例如,可能存在仅在文本编辑器获得焦点时才有效的键绑定。
请注意,以下代码示例不是生成模板的一部分,因此您需要手动添加它们(参见前面的部分)。
要贡献一个键绑定,请实现一个 KeybindingContribution(参见下面的代码示例),您可以使用它访问 KeybindingRegistry,从而允许您注册一个键绑定。键绑定包括:
keybinding:组合键
command:要触发的命令的id
when:(可选)快捷键可用的条件,满足条件时才会生效
helloworld-keybinding-contribution.ts
export class HelloworldKeybindingContribution implements KeybindingContribution { registerKeybindings(keybindings: KeybindingRegistry): void { keybindings.registerKeybinding({ keybinding: "alt+enter", command: 'Helloworld.command', when: 'editorFocus && editorIsOpen' }); } }
“when”子句的语法遵循 VS Code 术语(https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts)。 修饰符是平台无关的,所以 Modifier.M1 在 OS X 上是 Command,在 Windows/Linux 上是 CTRL。 按键的常量自符串可以在这里查看:https://eclipse-theia.github.io/theia/docs/next/modules/core.key-2.html。
正如您之前需要绑定贡献一样,键绑定贡献也需要绑定到符号 KeybindingContribution 以使 Theia 可以访问它们。
编辑器前端模块.ts
export default new ContainerModule(bind => { bind(KeybindingContribution).to(HelloworldKeybindingContribution); ... });