diff --git a/src/vs/platform/actions/common/menusExtensionPoint.ts b/src/vs/platform/actions/common/menusExtensionPoint.ts new file mode 100644 index 00000000000..59c845702b9 --- /dev/null +++ b/src/vs/platform/actions/common/menusExtensionPoint.ts @@ -0,0 +1,118 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {localize} from 'vs/nls'; +import {IJSONSchema} from 'vs/base/common/jsonSchema'; +import {IExtensionMessageCollector, ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry'; + +namespace schema { + + export function isValidLocation(location: string, collector: IExtensionMessageCollector): boolean { + switch (location) { + case 'editor/primary': + case 'editor/secondary': + return true; + } + return false; + } + + export function isValidMenuItem(item: MenuItem, collector: IExtensionMessageCollector): boolean { + + return true; + } + + export function isValidMenus(menu: Menus, collector: IExtensionMessageCollector): boolean { + + for (let key in menu) { + if (menu.hasOwnProperty(key)) { + let value = menu[key]; + if (!isValidLocation(key, collector)) { + collector.warn(localize('invalid', "`{0}` is not a valid menu location", key)); + continue; + } + + if (!Array.isArray(value)) { + collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `Array`", key)); + return false; + } + + for (let item of value) { + if (!isValidMenuItem(item, collector)) { + return false; + } + } + } + } + + return true; + } + + export const menus = { + + }; +} + +export interface MenuItem { + command: string; + alt: string; +} + +export interface Menus { + 'editor/primary': MenuItem[]; + 'editor/secondary': MenuItem[]; +} + +ExtensionsRegistry.registerExtensionPoint('menus', schema.menus).setHandler(extensions => { + for (let extension of extensions) { + const {value} = extension; + + if (schema.isValidMenus(value, extension.collector)) { + for (var key in value) { + if (value.hasOwnProperty(key)) { + MenusRegistry.registerMenuItems(MenuLocations.fromString(key), value[key]); + } + } + } + } +}); + +export enum MenuLocations { + EditorPrimary = 0, + EditorSecondary = 1 +} + +export namespace MenuLocations { + export function fromString(value: string): MenuLocations { + switch (value) { + case 'editor/primary': return MenuLocations.EditorPrimary; + case 'editor/secondary': return MenuLocations.EditorSecondary; + } + } +} + +export interface IMenuRegistry { + registerMenuItems(location: MenuLocations, items: MenuItem[]): void; + getMenuItems(location: MenuLocations): MenuItem[]; +} + +export const MenusRegistry: IMenuRegistry = new class { + + private _values: { [location: number]: MenuItem[] } = Object.create(null); + + registerMenuItems(location: MenuLocations, items: MenuItem[]): void { + let array = this._values[location]; + if (array) { + array.push(...items); + } else { + this._values[location] = items; + } + } + + getMenuItems(location: MenuLocations): MenuItem[] { + return this._values[location]; + } +}; + diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 489914e4be0..f6b3e7f647a 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -16,6 +16,9 @@ import 'vs/editor/browser/editor.all'; // Languages import 'vs/languages/languages.main'; +// Extension Points +import 'vs/platform/actions/common/menusExtensionPoint'; + // Workbench import 'vs/workbench/browser/actions/toggleStatusbarVisibility'; import 'vs/workbench/browser/actions/toggleSidebarVisibility';