Skip to content

Commit

Permalink
Add ability to register keybindings from 'package.json' file of a plugin
Browse files Browse the repository at this point in the history
Signed-off-by: Roman Nikitenko <[email protected]>
  • Loading branch information
RomanNikitenko committed Dec 11, 2018
1 parent a37b81d commit 585399d
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 0 deletions.
17 changes: 17 additions & 0 deletions packages/plugin-ext/src/common/plugin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export interface PluginPackageContribution {
viewsContainers?: { [location: string]: PluginPackageViewContainer[] };
views?: { [location: string]: PluginPackageView[] };
menus?: { [location: string]: PluginPackageMenu[] };
keybindings?: PluginPackageKeybinding[];
}

export interface PluginPackageViewContainer {
Expand All @@ -77,6 +78,12 @@ export interface PluginPackageMenu {
group?: string;
}

export interface PluginPackageKeybinding {
key: string;
command: string;
when?: string;
}

export interface PluginPackageGrammarsContribution {
language?: string;
scopeName: string;
Expand Down Expand Up @@ -302,6 +309,7 @@ export interface PluginContribution {
viewsContainers?: { [location: string]: ViewContainer[] };
views?: { [location: string]: View[] };
menus?: { [location: string]: Menu[] };
keybindings?: Keybinding[];
}

export interface GrammarsContribution {
Expand Down Expand Up @@ -388,6 +396,15 @@ export interface Menu {
group?: string;
}

/**
* Keybinding contribution
*/
export interface Keybinding {
keybinding: string;
command: string;
context?: string;
}

/**
* This interface describes a plugin lifecycle object.
*/
Expand Down
13 changes: 13 additions & 0 deletions packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import {
AutoClosingPairConditional,
AutoClosingPair,
ViewContainer,
Keybinding,
PluginPackageKeybinding,
PluginPackageViewContainer,
View,
PluginPackageView,
Expand Down Expand Up @@ -141,6 +143,9 @@ export class TheiaPluginScanner implements PluginScanner {
});
}

if (rawPlugin.contributes && rawPlugin.contributes.keybindings) {
contributions.keybindings = rawPlugin.contributes.keybindings.map(rawKeybinding => this.readKeybinding(rawKeybinding));
}
return contributions;
}

Expand All @@ -153,6 +158,14 @@ export class TheiaPluginScanner implements PluginScanner {
};
}

private readKeybinding(rawKeybinding: PluginPackageKeybinding): Keybinding {
return {
keybinding: rawKeybinding.key,
command: rawKeybinding.command,
context: rawKeybinding.when
};
}

private readViewsContainers(rawViewsContainers: PluginPackageViewContainer[], pluginPath: string): ViewContainer[] {
return rawViewsContainers.map(rawViewContainer => this.readViewContainer(rawViewContainer, pluginPath));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/********************************************************************************
* Copyright (C) 2018 Red Hat, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable, inject } from 'inversify';
import { PluginContribution } from '../../../common';
import { Keybinding, KeybindingRegistry, KeybindingScope } from '@theia/core/lib/browser/keybinding';
import { KeySequence } from '@theia/core/lib/browser';
import { ILogger } from '@theia/core/lib/common/logger';

@injectable()
export class KeybindingsContributionPointHandler {

@inject(ILogger)
protected readonly logger: ILogger;

@inject(KeybindingRegistry)
private readonly keybindingRegistry: KeybindingRegistry;

handle(contributions: PluginContribution): void {
if (!contributions || !contributions.keybindings) {
return;
}

const keybindings = contributions.keybindings;
keybindings.forEach(keybinding => {
const keybindingResult = this.keybindingRegistry.getKeybindingsForKeySequence(KeySequence.parse(keybinding.keybinding));

this.handleShadingKeybindings(keybinding, keybindingResult.shadow);
this.handlePartialKeybindings(keybinding, keybindingResult.partial);
});

this.keybindingRegistry.setKeymap(KeybindingScope.USER, keybindings);
}

private handlePartialKeybindings(keybinding: Keybinding, partialKeybindings: Keybinding[]) {
partialKeybindings.forEach(partial => {
if (keybinding.context === undefined || keybinding.context === partial.context) {
this.logger.warn(`Partial keybinding is ignored; ${Keybinding.stringify(keybinding)} shadows ${Keybinding.stringify(partial)}`);
}
});
}

private handleShadingKeybindings(keybinding: Keybinding, shadingKeybindings: Keybinding[]) {
shadingKeybindings.forEach(shadow => {
if (shadow.context === undefined || shadow.context === keybinding.context) {
this.keybindingRegistry.unregisterKeybinding(shadow);

this.logger.warn(`Shadowing keybinding is ignored; ${Keybinding.stringify(shadow)}, shadows ${Keybinding.stringify(keybinding)}`);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ViewRegistry } from './view/view-registry';
import { PluginContribution, IndentationRules, FoldingRules, ScopeMap } from '../../common';
import { PreferenceSchemaProvider } from '@theia/core/lib/browser';
import { PreferenceSchema } from '@theia/core/lib/browser/preferences';
import { KeybindingsContributionPointHandler } from './keybindings/keybindings-contribution-handler';

@injectable()
export class PluginContributionHandler {
Expand All @@ -43,6 +44,9 @@ export class PluginContributionHandler {
@inject(MonacoTextmateService)
private readonly monacoTextmateService: MonacoTextmateService;

@inject(KeybindingsContributionPointHandler)
private readonly keybindingsContributionHandler: KeybindingsContributionPointHandler;

handleContributions(contributions: PluginContribution): void {
if (contributions.configuration) {
this.updateConfigurationSchema(contributions.configuration);
Expand Down Expand Up @@ -126,6 +130,7 @@ export class PluginContributionHandler {
}

this.menusContributionHandler.handle(contributions);
this.keybindingsContributionHandler.handle(contributions);
}

private updateConfigurationSchema(schema: PreferenceSchema): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { PluginContributionHandler } from './plugin-contribution-handler';
import { ViewRegistry } from './view/view-registry';
import { TextContentResourceResolver } from './workspace-main';
import { MainPluginApiProvider } from '../../common/plugin-ext-api-contribution';
import { KeybindingsContributionPointHandler } from './keybindings/keybindings-contribution-handler';

export default new ContainerModule(bind => {
bindHostedPluginPreferences(bind);
Expand Down Expand Up @@ -97,6 +98,8 @@ export default new ContainerModule(bind => {
bind(ViewRegistry).toSelf().inSingletonScope();
bind(MenusContributionPointHandler).toSelf().inSingletonScope();

bind(KeybindingsContributionPointHandler).toSelf().inSingletonScope();

bind(PluginContributionHandler).toSelf().inSingletonScope();

bind(TextContentResourceResolver).toSelf().inSingletonScope();
Expand Down

0 comments on commit 585399d

Please sign in to comment.