提交 89fdb186 编写于 作者: C Christof Marti

Offer popular keymaps inline for installation (fixes #20782)

上级 0765fd83
......@@ -5,8 +5,8 @@
'use strict';
import arrays = require('vs/base/common/arrays');
import nls = require('vs/nls');
import * as arrays from 'vs/base/common/arrays';
import * as nls from 'vs/nls';
import { chain, any } from 'vs/base/common/event';
import { onUnexpectedError, canceled } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
......@@ -17,10 +17,12 @@ import { IChoiceService } from 'vs/platform/message/common/message';
import Severity from 'vs/base/common/severity';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
interface IExtension {
export interface IKeymapExtension {
identifier: string;
local: ILocalExtension;
globallyEnabled: boolean;
}
export class KeymapExtensions implements IWorkbenchContribution {
......@@ -28,9 +30,9 @@ export class KeymapExtensions implements IWorkbenchContribution {
private disposables: IDisposable[] = [];
constructor(
@IInstantiationService private instantiationService: IInstantiationService,
@IExtensionManagementService private extensionService: IExtensionManagementService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IExtensionTipsService private tipsService: IExtensionTipsService,
@IChoiceService private choiceService: IChoiceService,
@ILifecycleService lifecycleService: ILifecycleService,
@ITelemetryService private telemetryService: ITelemetryService,
......@@ -54,14 +56,10 @@ export class KeymapExtensions implements IWorkbenchContribution {
}
private checkForOtherKeymaps(extensionId: string): TPromise<void> {
return this.extensionService.getInstalled().then(extensions => {
const installedExtensions = extensions.map(ext => ({ identifier: stripVersion(ext.id), local: ext }));
const extension = arrays.first(installedExtensions, ext => ext.identifier === extensionId);
const globallyDisabled = this.extensionEnablementService.getGloballyDisabledExtensions();
if (extension && this.isKeymapExtension(extension) && globallyDisabled.indexOf(extensionId) === -1) {
const otherKeymaps = installedExtensions.filter(ext => ext.identifier !== extensionId &&
this.isKeymapExtension(ext) &&
globallyDisabled.indexOf(ext.identifier) === -1);
return this.instantiationService.invokeFunction(getInstalledKeymaps).then(extensions => {
const extension = arrays.first(extensions, extension => extension.identifier === extensionId);
if (extension && extension.globallyEnabled) {
const otherKeymaps = extensions.filter(extension => extension.identifier !== extensionId && extension.globallyEnabled);
if (otherKeymaps.length) {
return this.promptForDisablingOtherKeymaps(extension, otherKeymaps);
}
......@@ -70,12 +68,7 @@ export class KeymapExtensions implements IWorkbenchContribution {
});
}
private isKeymapExtension(extension: IExtension): boolean {
const cats = extension.local.manifest.categories;
return cats && cats.indexOf('Keymaps') !== -1 || this.tipsService.getKeymapRecommendations().indexOf(extension.identifier) !== -1;
}
private promptForDisablingOtherKeymaps(newKeymap: IExtension, oldKeymaps: IExtension[]): TPromise<void> {
private promptForDisablingOtherKeymaps(newKeymap: IKeymapExtension, oldKeymaps: IKeymapExtension[]): TPromise<void> {
const telemetryData: { [key: string]: any; } = {
newKeymap: newKeymap.identifier,
oldKeymaps: oldKeymaps.map(k => k.identifier)
......@@ -105,6 +98,29 @@ export class KeymapExtensions implements IWorkbenchContribution {
}
}
export function getInstalledKeymaps(accessor: ServicesAccessor): TPromise<IKeymapExtension[]> {
const extensionService = accessor.get(IExtensionManagementService);
const extensionEnablementService = accessor.get(IExtensionEnablementService);
const tipsService = accessor.get(IExtensionTipsService);
return extensionService.getInstalled().then(extensions => {
const globallyDisabled = extensionEnablementService.getGloballyDisabledExtensions();
const installedExtensions = extensions.map(extension => {
const identifier = stripVersion(extension.id);
return {
identifier,
local: extension,
globallyEnabled: globallyDisabled.indexOf(identifier) === -1
};
});
return installedExtensions.filter(extension => isKeymapExtension(tipsService, extension));
});
}
function isKeymapExtension(tipsService: IExtensionTipsService, extension: IKeymapExtension): boolean {
const cats = extension.local.manifest.categories;
return cats && cats.indexOf('Keymaps') !== -1 || tipsService.getKeymapRecommendations().indexOf(extension.identifier) !== -1;
}
function stripVersion(id: string): string {
return id.replace(/-\d+\.\d+\.\d+$/, '');
}
......@@ -43,7 +43,12 @@
<li class="keybindingsReference"><button data-href="command:workbench.action.keybindingsReference"><h3>Keyboard shortcuts</h3> <span>A printable PDF with the most common keyboard shortcuts</span></button></li>
<li class="showCommands"><button data-href="command:workbench.action.showCommands"><h3>Show all commands</h3> <span>Rapidly access and search commands from the control panel (<span class="shortcut" data-command="workbench.action.showCommands"></span>)</span></button></li>
<li class="openGlobalSettings"><button data-href="command:workbench.action.openGlobalSettings"><h3>Configure settings</h3> <span>Unlock the full power of VS Code by tweaking the settings</span></button></li>
<li class="showRecommendedKeymapExtensions"><button data-href="command:workbench.extensions.action.showRecommendedKeymapExtensions"><h3>Change Default Keyboard Shortcuts</h3> <span>Install an extension to adopt the keyboard shortcuts from another tool</span></button></li>
<li class="showRecommendedKeymapExtensions"><button data-href="command:workbench.extensions.action.showRecommendedKeymapExtensions"><h3>Change Default Keyboard Shortcuts</h3> <span>Install the keyboard shortcuts of
<a class="installKeymap" data-keymap-name="Vim" data-keymap="vscodevim.vim" href="javascript:void(0)">Vim</a>,
<a class="installKeymap" data-keymap-name="Sublime" data-keymap="ms-vscode.sublime-keybindings" href="javascript:void(0)">Sublime</a>,
<a class="installKeymap" data-keymap-name="Atom" data-keymap="ms-vscode.atom-keybindings" href="javascript:void(0)">Atom</a> and
<a href="command:workbench.extensions.action.showRecommendedKeymapExtensions">others</a>
</span></button></li>
</ul>
</div>
</div>
......
......@@ -9,6 +9,7 @@ import URI from 'vs/base/common/uri';
import * as path from 'path';
import * as platform from 'vs/base/common/platform';
import * as strings from 'vs/base/common/strings';
import * as arrays from 'vs/base/common/arrays';
import { WalkThroughInput } from 'vs/workbench/parts/welcome/walkThrough/node/walkThroughInput';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IPartService } from 'vs/workbench/services/part/common/partService';
......@@ -27,7 +28,9 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Schemas } from 'vs/base/common/network';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IMessageService, Severity } from 'vs/platform/message/common/message';
import { IMessageService, Severity, CancelAction } from 'vs/platform/message/common/message';
import { getInstalledKeymaps } from 'vs/workbench/parts/extensions/electron-browser/keymapExtensions';
import { IExtensionEnablementService, IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
const enabledKey = 'workbench.welcome.enabled';
const telemetryFrom = 'welcomePage';
......@@ -102,6 +105,9 @@ class WelcomePage {
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IMessageService private messageService: IMessageService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService,
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
@ITelemetryService private telemetryService: ITelemetryService
) {
this.create();
......@@ -184,5 +190,62 @@ class WelcomePage {
}
});
}
container.addEventListener('click', event => {
for (let node = event.target as HTMLElement; node; node = node.parentNode as HTMLElement) {
if (node instanceof HTMLAnchorElement && node.classList.contains('installKeymap')) {
const keymapName = node.getAttribute('data-keymap-name');
const keymapIdentifier = node.getAttribute('data-keymap');
if (keymapName && keymapIdentifier) {
this.installKeymap(keymapName, keymapIdentifier).then(null, err => {
this.messageService.show(Severity.Error, err);
});
event.preventDefault();
event.stopPropagation();
}
}
}
});
}
private installKeymap(keymapName: string, keymapIdentifier: string): TPromise<void> {
return this.instantiationService.invokeFunction(getInstalledKeymaps).then(extensions => {
const keymap = arrays.first(extensions, extension => extension.identifier === keymapIdentifier);
if (keymap && keymap.globallyEnabled) {
this.messageService.show(Severity.Info, localize('welcomePage.keymapAlreadyInstalled', "The {0} keyboard shortcuts are already installed.", keymapName));
return;
}
this.messageService.show(Severity.Info, {
message: localize('welcomePage.willReloadAfterInstallingKeymap', "The window will quickly reload after installing the {0} keyboard shortcuts.", keymapName),
actions: [
new Action('ok', localize('ok', "OK"), null, true, () => {
return TPromise.join(extensions.filter(extension => extension.globallyEnabled)
.map(extension => {
return this.extensionEnablementService.setEnablement(extension.identifier, false);
})).then(() => {
if (keymap) {
return this.extensionEnablementService.setEnablement(keymap.identifier, true)
.then(() => {
return this.windowService.reloadWindow();
});
}
return this.extensionGalleryService.query({ names: [keymapIdentifier] })
.then(result => {
const [extension] = result.firstPage;
if (!extension) {
this.messageService.show(Severity.Error, localize('welcomePage.keymapNotFound', "The {0} keyboard shortcuts with id {1} could not be found.", keymapName, keymapIdentifier));
return undefined;
}
return this.extensionManagementService.installFromGallery(extension)
.then(() => {
return this.windowService.reloadWindow();
});
});
});
}),
CancelAction
]
});
});
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册