diff --git a/arduino-debugger-extension/package.json b/arduino-debugger-extension/package.json index 56bdaba8..a29628d5 100644 --- a/arduino-debugger-extension/package.json +++ b/arduino-debugger-extension/package.json @@ -3,9 +3,6 @@ "version": "0.0.7", "description": "An extension for debugging Arduino programs", "license": "MIT", - "engines": { - "node": ">=10.11.0 <12" - }, "dependencies": { "@theia/debug": "next", "arduino-ide-extension": "0.0.7", diff --git a/arduino-debugger-extension/src/browser/arduino-debug-frontend-application-contribution.ts b/arduino-debugger-extension/src/browser/arduino-debug-frontend-application-contribution.ts index 60f9dd21..7ce59452 100644 --- a/arduino-debugger-extension/src/browser/arduino-debug-frontend-application-contribution.ts +++ b/arduino-debugger-extension/src/browser/arduino-debug-frontend-application-contribution.ts @@ -114,7 +114,7 @@ export class ArduinoDebugFrontendApplicationContribution extends DebugFrontendAp id: ArduinoDebugCommands.START_DEBUG.id, command: ArduinoDebugCommands.START_DEBUG.id, tooltip: 'Start Debugging', - priority: 1 + priority: 3 }); } diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 8477daac..5b389af6 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -3,9 +3,6 @@ "version": "0.0.7", "description": "An extension for Theia building the Arduino IDE", "license": "MIT", - "engines": { - "node": ">=10.11.0 <12" - }, "scripts": { "prepare": "yarn download-cli && yarn download-ls && yarn run clean && yarn run build", "clean": "rimraf lib", @@ -22,7 +19,6 @@ "@grpc/grpc-js": "^1.1.1", "@theia/application-package": "next", "@theia/core": "next", - "@theia/cpp": "next", "@theia/editor": "next", "@theia/filesystem": "next", "@theia/git": "next", @@ -31,6 +27,8 @@ "@theia/monaco": "next", "@theia/navigator": "next", "@theia/outline-view": "next", + "@theia/preferences": "next", + "@theia/output": "next", "@theia/search-in-workspace": "next", "@theia/terminal": "next", "@theia/workspace": "next", @@ -40,9 +38,11 @@ "@types/google-protobuf": "^3.7.2", "@types/js-yaml": "^3.12.2", "@types/lodash.debounce": "^4.0.6", + "@types/ncp": "^2.0.4", "@types/ps-tree": "^1.1.0", "@types/react-select": "^3.0.0", "@types/sinon": "^7.5.2", + "@types/temp": "^0.8.34", "@types/which": "^1.3.1", "ajv": "^6.5.3", "css-element-queries": "^1.2.0", @@ -53,11 +53,13 @@ "google-protobuf": "^3.11.4", "lodash.debounce": "^4.0.8", "js-yaml": "^3.13.1", + "ncp": "^2.0.0", "p-queue": "^5.0.0", "ps-tree": "^1.2.0", "react-select": "^3.0.4", "semver": "^6.3.0", "string-natural-compare": "^2.0.3", + "temp": "^0.9.1", "tree-kill": "^1.2.1", "upath": "^1.1.2", "which": "^1.3.1" @@ -66,7 +68,6 @@ "@types/chai": "^4.2.7", "@types/chai-string": "^1.4.2", "@types/mocha": "^5.2.7", - "@types/temp": "^0.8.34", "chai": "^4.2.0", "chai-string": "^1.5.0", "decompress": "^4.2.0", @@ -76,11 +77,9 @@ "grpc_tools_node_protoc_ts": "^4.1.0", "mocha": "^7.0.0", "moment": "^2.24.0", - "ncp": "^2.0.0", "protoc": "^1.0.4", "shelljs": "^0.8.3", "sinon": "^9.0.1", - "temp": "^0.9.1", "uuid": "^3.2.1", "yargs": "^11.1.0" }, @@ -108,8 +107,8 @@ "frontend": "lib/browser/arduino-ide-frontend-module" }, { - "frontend": "lib/browser/menu/browser-arduino-menu-module", - "frontendElectron": "lib/electron-browser/menu/electron-arduino-menu-module" + "frontend": "lib/browser/theia/core/browser-menu-module", + "frontendElectron": "lib/electron-browser/theia/core/electron-menu-module" }, { "frontend": "lib/browser/boards/quick-open/boards-quick-open-module" diff --git a/arduino-ide-extension/src/browser/arduino-commands.ts b/arduino-ide-extension/src/browser/arduino-commands.ts index faa042f4..ff22d3f8 100644 --- a/arduino-ide-extension/src/browser/arduino-commands.ts +++ b/arduino-ide-extension/src/browser/arduino-commands.ts @@ -1,75 +1,30 @@ import { Command } from '@theia/core/lib/common/command'; +/** + * @deprecated all these commands should go under contributions and have their command, menu, keybinding, and toolbar contributions. + */ export namespace ArduinoCommands { - const category = 'Arduino'; - - export const VERIFY: Command = { - id: 'arduino-verify', - label: 'Verify Sketch' - } - export const VERIFY_TOOLBAR: Command = { - id: 'arduino-verify-toolbar', - } - - export const UPLOAD: Command = { - id: 'arduino-upload', - label: 'Upload Sketch' - } - export const UPLOAD_TOOLBAR: Command = { - id: 'arduino-upload-toolbar', - } - export const TOGGLE_COMPILE_FOR_DEBUG: Command = { - id: "arduino-toggle-compile-for-debug" - } - - export const SHOW_OPEN_CONTEXT_MENU: Command = { - id: 'arduino-show-open-context-menu', - label: 'Open Sketch', - category + id: 'arduino-toggle-compile-for-debug' }; - export const OPEN_FILE_NAVIGATOR: Command = { - id: 'arduino-open-file-navigator' - } - - export const OPEN_SKETCH: Command = { - id: 'arduino-open-file' - } - /** * Unlike `OPEN_SKETCH`, it opens all files from a sketch folder. (ino, cpp, etc...) */ export const OPEN_SKETCH_FILES: Command = { id: 'arduino-open-sketch-files' - } - - export const SAVE_SKETCH: Command = { - id: 'arduino-save-file' - } - - export const NEW_SKETCH: Command = { - id: 'arduino-new-sketch', - label: 'New Sketch', - category - } + }; export const OPEN_BOARDS_DIALOG: Command = { id: 'arduino-open-boards-dialog' - } + }; export const TOGGLE_ADVANCED_MODE: Command = { id: 'arduino-toggle-advanced-mode' - } + }; export const TOGGLE_ADVANCED_MODE_TOOLBAR: Command = { - id: "arduino-toggle-advanced-mode-toolbar" - } - - export const OPEN_CLI_CONFIG: Command = { - id: 'arduino-open-cli-config', - label: 'Open CLI Configuration', - category + id: 'arduino-toggle-advanced-mode-toolbar' }; } diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index fbae515b..9b595384 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -1,61 +1,45 @@ import * as React from 'react'; import { injectable, inject, postConstruct } from 'inversify'; import URI from '@theia/core/lib/common/uri'; -import { EditorWidget } from '@theia/editor/lib/browser/editor-widget'; import { MessageService } from '@theia/core/lib/common/message-service'; -import { CommandContribution, CommandRegistry, Command, CommandHandler } from '@theia/core/lib/common/command'; +import { CommandContribution, CommandRegistry } from '@theia/core/lib/common/command'; import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; -import { BoardsService, BoardsServiceClient, CoreService, Sketch, SketchesService, ToolOutputServiceClient } from '../common/protocol'; +import { BoardsService, BoardsServiceClient, CoreService, SketchesService, ToolOutputServiceClient, Port } from '../common/protocol'; import { ArduinoCommands } from './arduino-commands'; import { BoardsServiceClientImpl } from './boards/boards-service-client-impl'; -import { WorkspaceRootUriAwareCommandHandler, WorkspaceCommands } from '@theia/workspace/lib/browser/workspace-commands'; -import { SelectionService, MenuContribution, MenuModelRegistry, MAIN_MENU_BAR, MenuPath } from '@theia/core'; +import { SelectionService, MenuContribution, MenuModelRegistry, MAIN_MENU_BAR } from '@theia/core'; import { ArduinoToolbar } from './toolbar/arduino-toolbar'; import { EditorManager, EditorMainMenu } from '@theia/editor/lib/browser'; import { - ContextMenuRenderer, Widget, StatusBar, StatusBarAlignment, FrontendApplicationContribution, - FrontendApplication, KeybindingContribution, KeybindingRegistry, OpenerService, open + ContextMenuRenderer, StatusBar, StatusBarAlignment, FrontendApplicationContribution, + FrontendApplication, KeybindingContribution, KeybindingRegistry, OpenerService } from '@theia/core/lib/browser'; -import { OpenFileDialogProps, FileDialogService } from '@theia/filesystem/lib/browser/file-dialog'; -import { FileSystem, FileStat } from '@theia/filesystem/lib/common'; -import { CommonCommands, CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution'; -import { FileSystemCommands } from '@theia/filesystem/lib/browser/filesystem-frontend-contribution'; -import { FileDownloadCommands } from '@theia/filesystem/lib/browser/download/file-download-command-contribution'; +import { FileDialogService } from '@theia/filesystem/lib/browser/file-dialog'; +import { FileSystem } from '@theia/filesystem/lib/common'; +import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution'; import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu'; import { TerminalMenus } from '@theia/terminal/lib/browser/terminal-frontend-contribution'; -import { MaybePromise } from '@theia/core/lib/common/types'; import { BoardsConfigDialog } from './boards/boards-config-dialog'; import { BoardsToolBarItem } from './boards/boards-toolbar-item'; import { BoardsConfig } from './boards/boards-config'; import { MonitorConnection } from './monitor/monitor-connection'; import { MonitorViewContribution } from './monitor/monitor-view-contribution'; -import { ArduinoWorkspaceService } from './arduino-workspace-service'; +import { WorkspaceService } from './theia/workspace/workspace-service'; import { FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; import { OutputContribution } from '@theia/output/lib/browser/output-contribution'; import { OutlineViewContribution } from '@theia/outline-view/lib/browser/outline-view-contribution'; import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution'; import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution'; import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; -import { FileNavigatorCommands } from '@theia/navigator/lib/browser/navigator-contribution'; import { EditorMode } from './editor-mode'; import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; import { ArduinoDaemon } from '../common/protocol/arduino-daemon'; import { ConfigService } from '../common/protocol/config-service'; -import { BoardsConfigStore } from './boards/boards-config-store'; -import { MainMenuManager } from './menu/main-menu-manager'; - -export namespace ArduinoMenus { - export const SKETCH = [...MAIN_MENU_BAR, '3_sketch']; - export const TOOLS = [...MAIN_MENU_BAR, '4_tools']; -} - -export namespace ArduinoToolbarContextMenu { - export const OPEN_SKETCH_PATH: MenuPath = ['arduino-open-sketch-context-menu']; - export const OPEN_GROUP: MenuPath = [...OPEN_SKETCH_PATH, '1_open']; - export const WS_SKETCHES_GROUP: MenuPath = [...OPEN_SKETCH_PATH, '2_sketches']; - export const EXAMPLE_SKETCHES_GROUP: MenuPath = [...OPEN_SKETCH_PATH, '3_examples']; -} +import { BoardsDataStore } from './boards/boards-data-store'; +import { MainMenuManager } from '../common/main-menu-manager'; +import { FileSystemExt } from '../common/protocol/filesystem-ext'; +import { ArduinoMenus } from './menu/arduino-menus'; @injectable() export class ArduinoFrontendContribution implements FrontendApplicationContribution, @@ -110,8 +94,8 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut @inject(StatusBar) protected readonly statusBar: StatusBar; - @inject(ArduinoWorkspaceService) - protected readonly workspaceService: ArduinoWorkspaceService; + @inject(WorkspaceService) + protected readonly workspaceService: WorkspaceService; @inject(MonitorConnection) protected readonly monitorConnection: MonitorConnection; @@ -146,14 +130,14 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut @inject(ConfigService) protected readonly configService: ConfigService; - @inject(BoardsConfigStore) - protected readonly boardsConfigStore: BoardsConfigStore; + @inject(BoardsDataStore) + protected readonly boardsDataStore: BoardsDataStore; @inject(MainMenuManager) protected readonly mainMenuManager: MainMenuManager; - protected application: FrontendApplication; - protected wsSketchCount: number = 0; // TODO: this does not belong here, does it? + @inject(FileSystemExt) + protected readonly fileSystemExt: FileSystemExt; @postConstruct() protected async init(): Promise { @@ -161,20 +145,25 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut // tslint:disable-next-line:max-line-length this.messageService.warn('You appear to be offline. Without an Internet connection, the Arduino CLI might not be able to download the required resources and could cause malfunction. Please connect to the Internet and restart the application.'); } - const updateStatusBar = (config: BoardsConfig.Config) => { + const updateStatusBar = ({ selectedBoard, selectedPort }: BoardsConfig.Config) => { this.statusBar.setElement('arduino-selected-board', { alignment: StatusBarAlignment.RIGHT, - text: BoardsConfig.Config.toString(config) + text: selectedBoard ? `$(microchip) ${selectedBoard.name}` : '$(close) no board selected', + className: 'arduino-selected-board' }); + if (selectedBoard) { + this.statusBar.setElement('arduino-selected-port', { + alignment: StatusBarAlignment.RIGHT, + text: selectedPort ? `on ${Port.toString(selectedPort)}` : '[not connected]', + className: 'arduino-selected-port' + }); + } } this.boardsServiceClientImpl.onBoardsConfigChanged(updateStatusBar); updateStatusBar(this.boardsServiceClientImpl.boardsConfig); - - this.registerSketchesInMenu(this.menuRegistry); } onStart(app: FrontendApplication): void { - this.application = app; // Initialize all `pro-mode` widgets. This is a NOOP if in normal mode. for (const viewContribution of [ this.fileNavigatorContributions, @@ -183,36 +172,13 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut this.problemContribution, this.scmContribution, this.siwContribution] as Array) { - if (viewContribution.initializeLayout) { - viewContribution.initializeLayout(this.application); + viewContribution.initializeLayout(app); } } } registerToolbarItems(registry: TabBarToolbarRegistry): void { - registry.registerItem({ - id: ArduinoCommands.VERIFY.id, - command: ArduinoCommands.VERIFY_TOOLBAR.id, - tooltip: 'Verify' - }); - registry.registerItem({ - id: ArduinoCommands.UPLOAD.id, - command: ArduinoCommands.UPLOAD_TOOLBAR.id, - tooltip: 'Upload' - }); - registry.registerItem({ - id: ArduinoCommands.SHOW_OPEN_CONTEXT_MENU.id, - command: ArduinoCommands.SHOW_OPEN_CONTEXT_MENU.id, - tooltip: 'Open', - priority: 2 - }); - registry.registerItem({ - id: ArduinoCommands.SAVE_SKETCH.id, - command: ArduinoCommands.SAVE_SKETCH.id, - tooltip: 'Save', - priority: 2 - }); registry.registerItem({ id: BoardsToolBarItem.TOOLBAR_ID, render: () => , isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', - priority: 2 + priority: 7 }); registry.registerItem({ id: 'toggle-serial-monitor', command: MonitorViewContribution.TOGGLE_SERIAL_MONITOR_TOOLBAR, - tooltip: 'Toggle Serial Monitor' + tooltip: 'Serial Monitor' }); - registry.registerItem({ id: ArduinoCommands.TOGGLE_ADVANCED_MODE.id, command: ArduinoCommands.TOGGLE_ADVANCED_MODE_TOOLBAR.id, - tooltip: 'Toggle Advanced Mode', - text: (this.editorMode.proMode ? '$(toggle-on)' : '$(toggle-off)') + tooltip: this.editorMode.proMode ? 'Switch to Classic Mode' : 'Switch to Advanced Mode', + text: this.editorMode.proMode ? '$(toggle-on)' : '$(toggle-off)' }); } registerCommands(registry: CommandRegistry): void { - // TODO: use proper API https://github.com/eclipse-theia/theia/pull/6599 - const allHandlers: { [id: string]: CommandHandler[] } = (registry as any)._handlers; - - // Make sure to reveal the `Explorer` before executing `New File` and `New Folder`. - for (const command of [WorkspaceCommands.NEW_FILE, WorkspaceCommands.NEW_FOLDER]) { - const { id } = command; - const handlers = allHandlers[id].slice(); - registry.unregisterCommand(id); - registry.registerCommand(command); - for (const handler of handlers) { - const wrapper: CommandHandler = { - execute: (...args: any[]) => { - this.fileNavigatorContributions.openView({ reveal: true }).then(() => handler.execute(args)); - }, - isVisible: (...args: any[]) => { - return handler.isVisible!(args); - }, - isEnabled: (args: any[]) => { - return handler.isEnabled!(args); - }, - isToggled: (args: any[]) => { - return handler.isToggled!(args); - } - }; - if (!handler.isEnabled) { - delete wrapper.isEnabled; - } - if (!handler.isToggled) { - delete wrapper.isToggled; - } - if (!handler.isVisible) { - delete wrapper.isVisible; - } - registry.registerHandler(id, wrapper); - } - } - - registry.registerCommand(ArduinoCommands.VERIFY, { - execute: this.verify.bind(this) - }); - registry.registerCommand(ArduinoCommands.VERIFY_TOOLBAR, { - isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', - execute: this.verify.bind(this) - }); - registry.registerCommand(ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG, { execute: () => this.editorMode.toggleCompileForDebug(), isToggled: () => this.editorMode.compileForDebug }); - - registry.registerCommand(ArduinoCommands.UPLOAD, { - execute: this.upload.bind(this) - }); - registry.registerCommand(ArduinoCommands.UPLOAD_TOOLBAR, { - isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', - execute: this.upload.bind(this) - }); - - registry.registerCommand(ArduinoCommands.SHOW_OPEN_CONTEXT_MENU, { - isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', - execute: async (widget: Widget, target: EventTarget) => { - if (this.wsSketchCount) { - const el = (target as HTMLElement).parentElement; - if (el) { - this.contextMenuRenderer.render(ArduinoToolbarContextMenu.OPEN_SKETCH_PATH, { - x: el.getBoundingClientRect().left, - y: el.getBoundingClientRect().top + el.offsetHeight - }); - } - } else { - this.commandRegistry.executeCommand(ArduinoCommands.OPEN_FILE_NAVIGATOR.id); - } - } - }); - - registry.registerCommand(ArduinoCommands.OPEN_FILE_NAVIGATOR, { - execute: () => this.doOpenFile() - }); - - registry.registerCommand(ArduinoCommands.OPEN_SKETCH, { - execute: async (sketch: Sketch) => { - this.workspaceService.open(new URI(sketch.uri)); - } - }); - registry.registerCommand(ArduinoCommands.OPEN_SKETCH_FILES, { execute: async (uri: string) => { this.openSketchFiles(uri); } }); - - registry.registerCommand(ArduinoCommands.SAVE_SKETCH, { - isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', - execute: (sketch: Sketch) => { - registry.executeCommand(CommonCommands.SAVE_ALL.id); - } - }); - - registry.registerCommand(ArduinoCommands.NEW_SKETCH, new WorkspaceRootUriAwareCommandHandler(this.workspaceService, this.selectionService, { - execute: async uri => { - try { - // hack: sometimes we don't get the workspace root, but the currently active file: correct for that - if (uri.path.ext !== "") { - uri = uri.withPath(uri.path.dir.dir); - } - - const sketch = await this.sketchService.createNewSketch(uri.toString()); - this.workspaceService.open(new URI(sketch.uri)); - } catch (e) { - await this.messageService.error(e.toString()); - } - } - })); - registry.registerCommand(ArduinoCommands.OPEN_BOARDS_DIALOG, { execute: async () => { const boardsConfig = await this.boardsConfigDialog.open(); @@ -359,7 +219,6 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut } } }); - registry.registerCommand(ArduinoCommands.TOGGLE_ADVANCED_MODE, { isToggled: () => this.editorMode.proMode, execute: () => this.editorMode.toggleProMode() @@ -369,189 +228,35 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut isToggled: () => this.editorMode.proMode, execute: () => this.editorMode.toggleProMode() }); - - registry.registerCommand(ArduinoCommands.OPEN_CLI_CONFIG, { - execute: () => this.configService.getCliConfigFileUri().then(uri => open(this.openerService, new URI(uri))) - }); - } - - protected async verify() { - const widget = this.getCurrentWidget(); - if (widget instanceof EditorWidget) { - await widget.saveable.save(); - } - - const uri = this.toUri(widget); - if (!uri) { - return; - } - - try { - const { boardsConfig } = this.boardsServiceClientImpl; - if (!boardsConfig || !boardsConfig.selectedBoard) { - throw new Error('No boards selected. Please select a board.'); - } - if (!boardsConfig.selectedBoard.fqbn) { - throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`); - } - const fqbn = await this.boardsConfigStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn); - this.outputContribution.openView({ reveal: true }); - await this.coreService.compile({ - sketchUri: uri.toString(), - fqbn, - optimizeForDebug: this.editorMode.compileForDebug - }); - } catch (e) { - await this.messageService.error(e.toString()); - } - } - - protected async upload() { - const widget = this.getCurrentWidget(); - if (widget instanceof EditorWidget) { - await widget.saveable.save(); - } - - const uri = this.toUri(widget); - if (!uri) { - return; - } - - const monitorConfig = this.monitorConnection.monitorConfig; - if (monitorConfig) { - await this.monitorConnection.disconnect(); - } - - try { - const { boardsConfig } = this.boardsServiceClientImpl; - if (!boardsConfig || !boardsConfig.selectedBoard) { - throw new Error('No boards selected. Please select a board.'); - } - const { selectedPort } = boardsConfig; - if (!selectedPort) { - throw new Error('No ports selected. Please select a port.'); - } - if (!boardsConfig.selectedBoard.fqbn) { - throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`); - } - this.outputContribution.openView({ reveal: true }); - const fqbn = await this.boardsConfigStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn); - await this.coreService.upload({ - sketchUri: uri.toString(), - fqbn, - port: selectedPort.address, - optimizeForDebug: this.editorMode.compileForDebug - }); - } catch (e) { - await this.messageService.error(e.toString()); - } finally { - if (monitorConfig) { - await this.monitorConnection.connect(monitorConfig); - } - } } registerMenus(registry: MenuModelRegistry) { if (!this.editorMode.proMode) { - // If are not in pro-mode, we have to disable the context menu for the tabs. - // Such as `Close`, `Close All`, etc. - for (const command of [ - CommonCommands.CLOSE_TAB, - CommonCommands.CLOSE_OTHER_TABS, - CommonCommands.CLOSE_RIGHT_TABS, - CommonCommands.CLOSE_ALL_TABS, - CommonCommands.COLLAPSE_PANEL, - CommonCommands.TOGGLE_MAXIMIZED, - FileNavigatorCommands.REVEAL_IN_NAVIGATOR - ]) { - registry.unregisterMenuAction(command); + const menuId = (menuPath: string[]): string => { + const index = menuPath.length - 1; + const menuId = menuPath[index]; + return menuId; } - - registry.unregisterMenuAction(FileSystemCommands.UPLOAD); - registry.unregisterMenuAction(FileDownloadCommands.DOWNLOAD); - - registry.unregisterMenuAction(WorkspaceCommands.OPEN_FOLDER); - registry.unregisterMenuAction(WorkspaceCommands.OPEN_WORKSPACE); - registry.unregisterMenuAction(WorkspaceCommands.OPEN_RECENT_WORKSPACE); - registry.unregisterMenuAction(WorkspaceCommands.SAVE_WORKSPACE_AS); - registry.unregisterMenuAction(WorkspaceCommands.CLOSE); - - registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(MonacoMenus.SELECTION)); - registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(EditorMainMenu.GO)); - registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(TerminalMenus.TERMINAL)); - registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(CommonMenus.VIEW)); + registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(MonacoMenus.SELECTION)); + registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(EditorMainMenu.GO)); + registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(TerminalMenus.TERMINAL)); + registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(CommonMenus.VIEW)); } - registry.registerSubmenu(ArduinoMenus.SKETCH, 'Sketch'); + registry.registerSubmenu(ArduinoMenus.TOOLS, 'Tools'); registry.registerMenuAction(ArduinoMenus.SKETCH, { commandId: ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG.id, label: 'Optimize for Debugging', order: '1' }); - registry.registerMenuAction(ArduinoMenus.SKETCH, { - commandId: ArduinoCommands.VERIFY.id, - label: 'Verify/Compile', - order: '2' - }); - registry.registerMenuAction(ArduinoMenus.SKETCH, { - commandId: ArduinoCommands.UPLOAD.id, - label: 'Upload', - order: '3' - }); - registry.registerMenuAction(ArduinoToolbarContextMenu.OPEN_GROUP, { - commandId: ArduinoCommands.OPEN_FILE_NAVIGATOR.id, - label: 'Open...' - }); - - registry.registerSubmenu(ArduinoMenus.TOOLS, 'Tools'); - registry.registerMenuAction(CommonMenus.HELP, { commandId: ArduinoCommands.TOGGLE_ADVANCED_MODE.id, label: 'Advanced Mode' }); - - registry.registerMenuAction([...CommonMenus.FILE, '0_new_sketch'], { - commandId: ArduinoCommands.NEW_SKETCH.id - }); - - registry.registerMenuAction([...CommonMenus.FILE_SETTINGS_SUBMENU, '3_settings_cli'], { - commandId: ArduinoCommands.OPEN_CLI_CONFIG.id - }); - } - - protected getMenuId(menuPath: string[]): string { - const index = menuPath.length - 1; - const menuId = menuPath[index]; - return menuId; } registerKeybindings(keybindings: KeybindingRegistry): void { - keybindings.registerKeybinding({ - command: ArduinoCommands.VERIFY.id, - keybinding: 'ctrlcmd+alt+v' - }); - keybindings.registerKeybinding({ - command: ArduinoCommands.UPLOAD.id, - keybinding: 'ctrlcmd+alt+u' - }); - } - - protected async registerSketchesInMenu(registry: MenuModelRegistry): Promise { - const sketches = await this.sketchService.getSketches(); - this.wsSketchCount = sketches.length; - sketches.forEach(sketch => { - const command: Command = { - id: 'openSketch' + sketch.name - } - this.commandRegistry.registerCommand(command, { - execute: () => this.commandRegistry.executeCommand(ArduinoCommands.OPEN_SKETCH.id, sketch) - }); - - registry.registerMenuAction(ArduinoToolbarContextMenu.WS_SKETCHES_GROUP, { - commandId: command.id, - label: sketch.name - }); - }); + keybindings.unregisterKeybinding('ctrlcmd+n'); // Unregister the keybinding for `New File`, will be used by `New Sketch`. (eclipse-theia/theia#8170) } protected async openSketchFiles(uri: string): Promise { @@ -559,82 +264,9 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut for (const uri of uris) { await this.editorManager.open(new URI(uri)); } - } - - /** - * Opens a file after prompting the `Open File` dialog. Shows a warning message if - * - the file to open does not exist, - * - it was not a file, but a directory, or - * - the file does not pass validation. - * - * Otherwise, resolves to the URI of the file. - */ - protected async doOpenFile(): Promise { - const props: OpenFileDialogProps = { - title: WorkspaceCommands.OPEN_FILE.dialogLabel, - canSelectFolders: false, - canSelectFiles: true - }; - const [rootStat] = await this.workspaceService.roots; - const destinationFileUri = await this.fileDialogService.showOpenDialog(props, rootStat); - if (!destinationFileUri) { - return; + if (uris.length) { + await this.editorManager.open(new URI(uris[0])); // Make sure the sketch file has the focus. } - const destinationFile = await this.fileSystem.getFileStat(destinationFileUri.toString()); - if (!destinationFile) { - this.messageService.warn(`File does not exist: ${this.fileSystem.getFsPath(destinationFileUri.toString())}`) - return; - } - if (destinationFile.isDirectory) { - this.messageService.warn('Please select a sketch file, not a directory.') - return; - } - const message = await this.validate(destinationFile); - if (message) { - this.messageService.warn(message); - return; - } - this.workspaceService.open(destinationFileUri.parent); - } - - protected getCurrentWidget(): EditorWidget | undefined { - let widget = this.editorManager.currentEditor; - if (!widget) { - const visibleWidgets = this.editorManager.all.filter(w => w.isVisible); - if (visibleWidgets.length > 0) { - widget = visibleWidgets[0]; - } - } - return widget; - } - - /** - * Returns `undefined` if the `file` is valid. Otherwise, returns with the validation error message. - */ - protected validate(file: FileStat): MaybePromise { - const uri = new URI(file.uri); - const path = uri.path; - const { name, ext, dir } = path; - if (ext !== '.ino') { - return "Only sketches with '.ino' extension can be opened."; - } - if (name !== dir.name) { - return `The file "${name}${ext}" needs to be inside a sketch folder named "${name}".`; - } - return undefined; - } - - private toUri(arg: any): URI | undefined { - if (arg instanceof URI) { - return arg; - } - if (typeof arg === 'string') { - return new URI(arg); - } - if (arg instanceof EditorWidget) { - return arg.editor.uri; - } - return undefined; } registerColors(colors: ColorRegistry): void { @@ -663,6 +295,24 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut hc: 'editorWidget.background' }, description: 'Color of the Arduino Pro IDE foreground which is used for dialogs, such as the Select Board dialog.' + }, + { + id: 'arduino.toolbar.background', + defaults: { + dark: 'button.background', + light: 'button.background', + hc: 'activityBar.inactiveForeground' + }, + description: 'Background color of the toolbar items. Such as Upload, Verify, etc.' + }, + { + id: 'arduino.toolbar.hoverBackground', + defaults: { + dark: 'button.hoverBackground', + light: 'button.hoverBackground', + hc: 'activityBar.inactiveForeground' + }, + description: 'Background color of the toolbar items when hovering over them. Such as Upload, Verify, etc.' } ); } diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index d444d55d..80b742d6 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -1,11 +1,11 @@ import '../../src/browser/style/index.css'; -import { ContainerModule, interfaces } from 'inversify'; +import { ContainerModule } from 'inversify'; import { WidgetFactory } from '@theia/core/lib/browser/widget-manager'; import { CommandContribution } from '@theia/core/lib/common/command'; import { bindViewContribution } from '@theia/core/lib/browser/shell/view-contribution'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging/ws-connection-provider'; -import { FrontendApplicationContribution, FrontendApplication } from '@theia/core/lib/browser/frontend-application' +import { FrontendApplicationContribution, FrontendApplication as TheiaFrontendApplication } from '@theia/core/lib/browser/frontend-application' import { LanguageGrammarDefinitionContribution } from '@theia/monaco/lib/browser/textmate'; import { LanguageClientContribution } from '@theia/languages/lib/browser'; import { ArduinoLanguageClientContribution } from './language/arduino-language-client-contribution'; @@ -22,31 +22,35 @@ import { ToolOutputServiceClient } from '../common/protocol/tool-output-service' import { ToolOutputService } from '../common/protocol/tool-output-service'; import { ToolOutputServiceClientImpl } from './tool-output/client-service-impl'; import { BoardsServiceClientImpl } from './boards/boards-service-client-impl'; -import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; -import { ArduinoWorkspaceService } from './arduino-workspace-service'; -import { OutlineViewContribution } from '@theia/outline-view/lib/browser/outline-view-contribution'; -import { ArduinoOutlineViewContribution } from './customization/arduino-outline-contribution'; -import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution'; -import { ArduinoProblemContribution } from './customization/arduino-problem-contribution'; -import { ArduinoNavigatorContribution } from './customization/arduino-navigator-contribution'; -import { FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; +import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; +import { WorkspaceService } from './theia/workspace/workspace-service'; +import { OutlineViewContribution as TheiaOutlineViewContribution } from '@theia/outline-view/lib/browser/outline-view-contribution'; +import { OutlineViewContribution } from './theia/outline/outline-contribution'; +import { ProblemContribution as TheiaProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution'; +import { ProblemContribution } from './theia/markers/problem-contribution'; +import { FileNavigatorContribution } from './theia/navigator/navigator-contribution'; +import { FileNavigatorContribution as TheiaFileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; import { ArduinoToolbarContribution } from './toolbar/arduino-toolbar-contribution'; -import { OutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution'; -import { ArduinoOutputToolContribution } from './customization/arduino-output-tool-contribution'; -import { EditorContribution } from '@theia/editor/lib/browser/editor-contribution'; -import { ArduinoEditorContribution } from './customization/arduino-editor-contribution'; -import { MonacoStatusBarContribution } from '@theia/monaco/lib/browser/monaco-status-bar-contribution'; -import { ArduinoMonacoStatusBarContribution } from './customization/arduino-monaco-status-bar-contribution'; -import { ApplicationShell, ShellLayoutRestorer, KeybindingContribution } from '@theia/core/lib/browser'; +import { EditorContribution as TheiaEditorContribution } from '@theia/editor/lib/browser/editor-contribution'; +import { EditorContribution } from './theia/editor/editor-contribution'; +import { MonacoStatusBarContribution as TheiaMonacoStatusBarContribution } from '@theia/monaco/lib/browser/monaco-status-bar-contribution'; +import { MonacoStatusBarContribution } from './theia/monaco/monaco-status-bar-contribution'; +import { + ApplicationShell as TheiaApplicationShell, + ShellLayoutRestorer as TheiaShellLayoutRestorer, + KeybindingContribution, + CommonFrontendContribution as TheiaCommonFrontendContribution, + KeybindingRegistry as TheiaKeybindingRegistry +} from '@theia/core/lib/browser'; import { MenuContribution } from '@theia/core/lib/common/menu'; -import { ArduinoApplicationShell } from './customization/arduino-application-shell'; -import { ArduinoFrontendApplication } from './customization/arduino-frontend-application'; +import { ApplicationShell } from './theia/core/application-shell'; +import { FrontendApplication } from './theia/core/frontend-application'; import { BoardsConfigDialog, BoardsConfigDialogProps } from './boards/boards-config-dialog'; import { BoardsConfigDialogWidget } from './boards/boards-config-dialog-widget'; -import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution'; -import { ArduinoScmContribution } from './customization/arduino-scm-contribution'; -import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; -import { ArduinoSearchInWorkspaceContribution } from './customization/arduino-search-in-workspace-contribution'; +import { ScmContribution as TheiaScmContribution } from '@theia/scm/lib/browser/scm-contribution'; +import { ScmContribution } from './theia/scm/scm-contribution'; +import { SearchInWorkspaceFrontendContribution as TheiaSearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; +import { SearchInWorkspaceFrontendContribution } from './theia/search-in-workspace/search-in-workspace-frontend-contribution'; import { LibraryListWidgetFrontendContribution } from './library/library-widget-frontend-contribution'; import { MonitorServiceClientImpl } from './monitor/monitor-service-client-impl'; import { MonitorServicePath, MonitorService, MonitorServiceClient } from '../common/protocol/monitor-service'; @@ -55,29 +59,52 @@ import { MonitorWidget } from './monitor/monitor-widget'; import { MonitorViewContribution } from './monitor/monitor-view-contribution'; import { MonitorConnection } from './monitor/monitor-connection'; import { MonitorModel } from './monitor/monitor-model'; -import { TabBarDecoratorService } from '@theia/core/lib/browser/shell/tab-bar-decorator'; -import { ArduinoTabBarDecoratorService } from './shell/arduino-tab-bar-decorator'; -import { ProblemManager } from '@theia/markers/lib/browser'; -import { ArduinoProblemManager } from './markers/arduino-problem-manager'; +import { TabBarDecoratorService as TheiaTabBarDecoratorService } from '@theia/core/lib/browser/shell/tab-bar-decorator'; +import { TabBarDecoratorService } from './theia/core/tab-bar-decorator'; +import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser'; +import { ProblemManager } from './theia/markers/problem-manager'; import { BoardsAutoInstaller } from './boards/boards-auto-installer'; -import { AboutDialog } from '@theia/core/lib/browser/about-dialog'; -import { ArduinoAboutDialog } from './customization/arduino-about-dialog'; -import { ArduinoShellLayoutRestorer } from './shell/arduino-shell-layout-restorer'; +import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog'; +import { AboutDialog } from './theia/core/about-dialog'; +import { ShellLayoutRestorer } from './theia/core/shell-layout-restorer'; import { EditorMode } from './editor-mode'; -import { ListItemRenderer } from './components/component-list/list-item-renderer'; +import { ListItemRenderer } from './widgets/component-list/list-item-renderer'; import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; import { MonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service'; import { ArduinoDaemonClientImpl } from './arduino-daemon-client-impl'; import { ArduinoDaemonClient, ArduinoDaemonPath, ArduinoDaemon } from '../common/protocol/arduino-daemon'; -import { EditorManager } from '@theia/editor/lib/browser'; -import { ArduinoEditorManager } from './editor/arduino-editor-manager'; -import { ArduinoFrontendConnectionStatusService, ArduinoApplicationConnectionStatusContribution } from './customization/arduino-connection-status-service'; -import { FrontendConnectionStatusService, ApplicationConnectionStatusContribution } from '@theia/core/lib/browser/connection-status-service'; +import { EditorManager as TheiaEditorManager } from '@theia/editor/lib/browser'; +import { EditorManager } from './theia/editor/editor-manager'; +import { FrontendConnectionStatusService, ApplicationConnectionStatusContribution } from './theia/core/connection-status-service'; +import { + FrontendConnectionStatusService as TheiaFrontendConnectionStatusService, + ApplicationConnectionStatusContribution as TheiaApplicationConnectionStatusContribution +} from '@theia/core/lib/browser/connection-status-service'; import { ConfigServiceClientImpl } from './config-service-client-impl'; import { CoreServiceClientImpl } from './core-service-client-impl'; -import { BoardsDetailsMenuUpdater } from './boards/boards-details-menu-updater'; -import { BoardsConfigStore } from './boards/boards-config-store'; +import { BoardsDataMenuUpdater } from './boards/boards-data-menu-updater'; +import { BoardsDataStore } from './boards/boards-data-store'; import { ILogger } from '@theia/core'; +import { FileSystemExt, FileSystemExtPath } from '../common/protocol/filesystem-ext'; +import { WorkspaceFrontendContribution as TheiaWorkspaceFrontendContribution, FileMenuContribution as TheiaFileMenuContribution } from '@theia/workspace/lib/browser'; +import { WorkspaceFrontendContribution, ArduinoFileMenuContribution } from './theia/workspace/workspace-frontend-contribution'; +import { Contribution } from './contributions/contribution'; +import { NewSketch } from './contributions/new-sketch'; +import { OpenSketch } from './contributions/open-sketch'; +import { CloseSketch } from './contributions/close-sketch'; +import { SaveAsSketch } from './contributions/save-as-sketch'; +import { SaveSketch } from './contributions/save-sketch'; +import { VerifySketch } from './contributions/verify-sketch'; +import { UploadSketch } from './contributions/upload-sketch'; +import { CommonFrontendContribution } from './theia/core/common-frontend-contribution'; +import { EditContributions } from './contributions/edit-contributions'; +import { OpenSketchExternal } from './contributions/open-sketch-external'; +import { PreferencesContribution as TheiaPreferencesContribution } from '@theia/preferences/lib/browser/preference-contribution'; +import { PreferencesContribution } from './theia/preferences/preference-contribution'; +import { QuitApp } from './contributions/quit-app'; +import { SketchControl } from './contributions/sketch-control'; +import { Settings } from './contributions/settings'; +import { KeybindingRegistry } from './theia/core/keybindings'; const ElementQueries = require('css-element-queries/src/ElementQueries'); @@ -88,7 +115,7 @@ MonacoThemingService.register({ json: require('../../src/browser/data/arduino.color-theme.json') }); -export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => { +export default new ContainerModule((bind, unbind, isBound, rebind) => { ElementQueries.listen(); ElementQueries.init(); @@ -150,19 +177,15 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un bind(BoardsServiceClient).toDynamicValue(async context => { const client = context.container.get(BoardsServiceClientImpl); const service = context.container.get(BoardsService); - const [attachedBoards, availablePorts] = await Promise.all([ - service.getAttachedBoards(), - service.getAvailablePorts() - ]); - client.init({ attachedBoards, availablePorts }); + await client.init(service); WebSocketConnectionProvider.createProxy(context.container, BoardsServicePath, client); return client; }).inSingletonScope(); // To be able to track, and update the menu based on the core settings (aka. board details) of the currently selected board. - bind(FrontendApplicationContribution).to(BoardsDetailsMenuUpdater).inSingletonScope(); - bind(BoardsConfigStore).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(BoardsConfigStore); + bind(FrontendApplicationContribution).to(BoardsDataMenuUpdater).inSingletonScope(); + bind(BoardsDataStore).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(BoardsDataStore); // Logger for the Arduino daemon bind(ILogger).toDynamicValue(ctx => { const parentLogger = ctx.container.get(ILogger); @@ -236,50 +259,54 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un return client; }).inSingletonScope(); - bind(ArduinoWorkspaceService).toSelf().inSingletonScope(); - rebind(WorkspaceService).toService(ArduinoWorkspaceService); + bind(WorkspaceService).toSelf().inSingletonScope(); + rebind(TheiaWorkspaceService).toService(WorkspaceService); // Customizing default Theia layout based on the editor mode: `pro-mode` or `classic`. bind(EditorMode).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(EditorMode); // Layout and shell customizations. - rebind(OutlineViewContribution).to(ArduinoOutlineViewContribution).inSingletonScope(); - rebind(ProblemContribution).to(ArduinoProblemContribution).inSingletonScope(); - rebind(FileNavigatorContribution).to(ArduinoNavigatorContribution).inSingletonScope(); - rebind(OutputToolbarContribution).to(ArduinoOutputToolContribution).inSingletonScope(); - rebind(EditorContribution).to(ArduinoEditorContribution).inSingletonScope(); - rebind(MonacoStatusBarContribution).to(ArduinoMonacoStatusBarContribution).inSingletonScope(); - rebind(ApplicationShell).to(ArduinoApplicationShell).inSingletonScope(); - rebind(ScmContribution).to(ArduinoScmContribution).inSingletonScope(); - rebind(SearchInWorkspaceFrontendContribution).to(ArduinoSearchInWorkspaceContribution).inSingletonScope(); - rebind(FrontendApplication).to(ArduinoFrontendApplication).inSingletonScope(); + rebind(TheiaOutlineViewContribution).to(OutlineViewContribution).inSingletonScope(); + rebind(TheiaProblemContribution).to(ProblemContribution).inSingletonScope(); + rebind(TheiaFileNavigatorContribution).to(FileNavigatorContribution).inSingletonScope(); + rebind(TheiaEditorContribution).to(EditorContribution).inSingletonScope(); + rebind(TheiaMonacoStatusBarContribution).to(MonacoStatusBarContribution).inSingletonScope(); + rebind(TheiaApplicationShell).to(ApplicationShell).inSingletonScope(); + rebind(TheiaScmContribution).to(ScmContribution).inSingletonScope(); + rebind(TheiaSearchInWorkspaceFrontendContribution).to(SearchInWorkspaceFrontendContribution).inSingletonScope(); + rebind(TheiaFrontendApplication).to(FrontendApplication).inSingletonScope(); + rebind(TheiaWorkspaceFrontendContribution).to(WorkspaceFrontendContribution).inSingletonScope(); + rebind(TheiaFileMenuContribution).to(ArduinoFileMenuContribution).inSingletonScope(); + rebind(TheiaCommonFrontendContribution).to(CommonFrontendContribution).inSingletonScope(); + rebind(TheiaPreferencesContribution).to(PreferencesContribution).inSingletonScope(); + rebind(TheiaKeybindingRegistry).to(KeybindingRegistry).inSingletonScope(); // Show a disconnected status bar, when the daemon is not available - bind(ArduinoApplicationConnectionStatusContribution).toSelf().inSingletonScope(); - rebind(ApplicationConnectionStatusContribution).toService(ArduinoApplicationConnectionStatusContribution); - bind(ArduinoFrontendConnectionStatusService).toSelf().inSingletonScope(); - rebind(FrontendConnectionStatusService).toService(ArduinoFrontendConnectionStatusService); + bind(ApplicationConnectionStatusContribution).toSelf().inSingletonScope(); + rebind(TheiaApplicationConnectionStatusContribution).toService(ApplicationConnectionStatusContribution); + bind(FrontendConnectionStatusService).toSelf().inSingletonScope(); + rebind(TheiaFrontendConnectionStatusService).toService(FrontendConnectionStatusService); // Editor customizations. Sets the editor to `readOnly` if under the data dir. - bind(ArduinoEditorManager).toSelf().inSingletonScope(); - rebind(EditorManager).toService(ArduinoEditorManager); + bind(EditorManager).toSelf().inSingletonScope(); + rebind(TheiaEditorManager).toService(EditorManager); // Decorator customizations - bind(ArduinoTabBarDecoratorService).toSelf().inSingletonScope(); - rebind(TabBarDecoratorService).toService(ArduinoTabBarDecoratorService); + bind(TabBarDecoratorService).toSelf().inSingletonScope(); + rebind(TheiaTabBarDecoratorService).toService(TabBarDecoratorService); // Problem markers - bind(ArduinoProblemManager).toSelf().inSingletonScope(); - rebind(ProblemManager).toService(ArduinoProblemManager); + bind(ProblemManager).toSelf().inSingletonScope(); + rebind(TheiaProblemManager).toService(ProblemManager); // About dialog to show the CLI version - bind(ArduinoAboutDialog).toSelf().inSingletonScope(); - rebind(AboutDialog).toService(ArduinoAboutDialog); + bind(AboutDialog).toSelf().inSingletonScope(); + rebind(TheiaAboutDialog).toService(AboutDialog); // Customized layout restorer that can restore the state in async way: https://github.com/eclipse-theia/theia/issues/6579 - bind(ArduinoShellLayoutRestorer).toSelf().inSingletonScope(); - rebind(ShellLayoutRestorer).toService(ArduinoShellLayoutRestorer); + bind(ShellLayoutRestorer).toSelf().inSingletonScope(); + rebind(TheiaShellLayoutRestorer).toService(ShellLayoutRestorer); // Arduino daemon client. Receives notifications from the backend if the CLI daemon process has been restarted. bind(ArduinoDaemon).toDynamicValue(context => { @@ -293,4 +320,20 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un WebSocketConnectionProvider.createProxy(context.container, ArduinoDaemonPath, client); return client; }).inSingletonScope(); + + // File-system extension + bind(FileSystemExt).toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, FileSystemExtPath)).inSingletonScope(); + + Contribution.configure(bind, NewSketch); + Contribution.configure(bind, OpenSketch); + Contribution.configure(bind, CloseSketch); + Contribution.configure(bind, SaveSketch); + Contribution.configure(bind, SaveAsSketch); + Contribution.configure(bind, VerifySketch); + Contribution.configure(bind, UploadSketch); + Contribution.configure(bind, OpenSketchExternal); + Contribution.configure(bind, EditContributions); + Contribution.configure(bind, QuitApp); + Contribution.configure(bind, SketchControl); + Contribution.configure(bind, Settings); }); diff --git a/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts b/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts index cb0c340d..50a06166 100644 --- a/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts +++ b/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts @@ -4,10 +4,9 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser/fronten import { BoardsService, Board } from '../../common/protocol/boards-service'; import { BoardsServiceClientImpl } from './boards-service-client-impl'; import { BoardsListWidgetFrontendContribution } from './boards-widget-frontend-contribution'; -import { InstallationProgressDialog } from '../components/progress-dialog'; +import { InstallationProgressDialog } from '../widgets/progress-dialog'; import { BoardsConfig } from './boards-config'; - /** * Listens on `BoardsConfig.Config` changes, if a board is selected which does not * have the corresponding core installed, it proposes the user to install the core. diff --git a/arduino-ide-extension/src/browser/boards/boards-config.tsx b/arduino-ide-extension/src/browser/boards/boards-config.tsx index 59a380a9..6ae778f2 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config.tsx +++ b/arduino-ide-extension/src/browser/boards/boards-config.tsx @@ -127,7 +127,7 @@ export class BoardsConfig extends React.Component> => { - return this.props.boardsService.searchBoards(options); + return this.props.boardsServiceClient.searchBoards(options); } protected get availablePorts(): Promise { @@ -178,13 +178,24 @@ export class BoardsConfig extends React.Component(); + const toKey = ({ name, packageName, fqbn }: Board.Detailed) => !!fqbn ? `${name}-${packageName}-${fqbn}` : `${name}-${packageName}`; + for (const board of Board.decorateBoards(selectedBoard, searchResults)) { + const key = toKey(board); + if (!distinctBoards.has(key)) { + distinctBoards.set(key, board); + } + } + return
- {Board.decorateBoards(selectedBoard, searchResults).map(board => + {Array.from(distinctBoards.values()).map(board => key={`${board.name}-${board.packageName}`} item={board} label={board.name} diff --git a/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts b/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts new file mode 100644 index 00000000..3e6f524f --- /dev/null +++ b/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts @@ -0,0 +1,113 @@ +import { inject, injectable } from 'inversify'; +import { CommandRegistry } from '@theia/core/lib/common/command'; +import { MenuModelRegistry, MenuNode } from '@theia/core/lib/common/menu'; +import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; +import { BoardsServiceClientImpl } from './boards-service-client-impl'; +import { Board, ConfigOption, Programmer } from '../../common/protocol'; +import { FrontendApplicationContribution } from '@theia/core/lib/browser'; +import { BoardsDataStore } from './boards-data-store'; +import { MainMenuManager } from '../../common/main-menu-manager'; +import { ArduinoMenus } from '../menu/arduino-menus'; + +@injectable() +export class BoardsDataMenuUpdater implements FrontendApplicationContribution { + + @inject(CommandRegistry) + protected readonly commandRegistry: CommandRegistry; + + @inject(MenuModelRegistry) + protected readonly menuRegistry: MenuModelRegistry; + + @inject(MainMenuManager) + protected readonly mainMenuManager: MainMenuManager; + + @inject(BoardsDataStore) + protected readonly boardsDataStore: BoardsDataStore; + + @inject(BoardsServiceClientImpl) + protected readonly boardsServiceClient: BoardsServiceClientImpl; + + protected readonly toDisposeOnBoardChange = new DisposableCollection(); + + async onStart(): Promise { + await this.updateMenuActions(this.boardsServiceClient.boardsConfig.selectedBoard); + this.boardsDataStore.onChanged(async () => await this.updateMenuActions(this.boardsServiceClient.boardsConfig.selectedBoard)); + this.boardsServiceClient.onBoardsConfigChanged(async ({ selectedBoard }) => await this.updateMenuActions(selectedBoard)); + } + + protected async updateMenuActions(selectedBoard: Board | undefined): Promise { + if (selectedBoard) { + this.toDisposeOnBoardChange.dispose(); + this.mainMenuManager.update(); + const { fqbn } = selectedBoard; + if (fqbn) { + const { configOptions, programmers, selectedProgrammer } = await this.boardsDataStore.getData(fqbn); + if (configOptions.length) { + const boardsConfigMenuPath = [...ArduinoMenus.TOOLS__BOARD_SETTINGS_GROUP, 'z01_boardsConfig']; // `z_` is for ordering. + for (const { label, option, values } of configOptions.sort(ConfigOption.LABEL_COMPARATOR)) { + const menuPath = [...boardsConfigMenuPath, `${option}`]; + const commands = new Map() + for (const value of values) { + const id = `${fqbn}-${option}--${value.value}`; + const command = { id }; + const selectedValue = value.value; + const handler = { + execute: () => this.boardsDataStore.selectConfigOption({ fqbn, option, selectedValue }), + isToggled: () => value.selected + }; + commands.set(id, Object.assign(this.commandRegistry.registerCommand(command, handler), { label: value.label })); + } + this.menuRegistry.registerSubmenu(menuPath, label); + this.toDisposeOnBoardChange.pushAll([ + ...commands.values(), + Disposable.create(() => this.unregisterSubmenu(menuPath)), // We cannot dispose submenu entries: https://github.com/eclipse-theia/theia/issues/7299 + ...Array.from(commands.keys()).map((commandId, i) => { + const { label } = commands.get(commandId)!; + this.menuRegistry.registerMenuAction(menuPath, { commandId, order: `${i}`, label }); + return Disposable.create(() => this.menuRegistry.unregisterMenuAction(commandId)); + }) + ]); + } + } + if (programmers.length) { + const programmersMenuPath = [...ArduinoMenus.TOOLS__BOARD_SETTINGS_GROUP, 'z02_programmers']; + const label = selectedProgrammer ? `Programmer: "${selectedProgrammer.name}"` : 'Programmer' + this.menuRegistry.registerSubmenu(programmersMenuPath, label); + this.toDisposeOnBoardChange.push(Disposable.create(() => this.unregisterSubmenu(programmersMenuPath))); + for (const programmer of programmers) { + const { id, name } = programmer; + const command = { id: `${fqbn}-programmer--${id}` }; + const handler = { + execute: () => this.boardsDataStore.selectProgrammer({ fqbn, selectedProgrammer: programmer }), + isToggled: () => Programmer.equals(programmer, selectedProgrammer) + }; + this.menuRegistry.registerMenuAction(programmersMenuPath, { commandId: command.id, label: name }); + this.commandRegistry.registerCommand(command, handler); + this.toDisposeOnBoardChange.pushAll([ + Disposable.create(() => this.commandRegistry.unregisterCommand(command)), + Disposable.create(() => this.menuRegistry.unregisterMenuAction(command.id)) + ]); + } + } + this.mainMenuManager.update(); + } + } + } + + protected unregisterSubmenu(menuPath: string[]): void { + if (menuPath.length < 2) { + throw new Error(`Expected at least two item as a menu-path. Got ${JSON.stringify(menuPath)} instead.`); + } + const toRemove = menuPath[menuPath.length - 1]; + const parentMenuPath = menuPath.slice(0, menuPath.length - 1); + // This is unsafe. Calling `getMenu` with a non-existing menu-path will result in a new menu creation. + // https://github.com/eclipse-theia/theia/issues/7300 + const parent = this.menuRegistry.getMenu(parentMenuPath); + const index = parent.children.findIndex(({ id }) => id === toRemove); + if (index === -1) { + throw new Error(`Could not find menu with menu-path: ${JSON.stringify(menuPath)}.`); + } + (parent.children as Array).splice(index, 1); + } + +} diff --git a/arduino-ide-extension/src/browser/boards/boards-config-store.ts b/arduino-ide-extension/src/browser/boards/boards-data-store.ts similarity index 64% rename from arduino-ide-extension/src/browser/boards/boards-config-store.ts rename to arduino-ide-extension/src/browser/boards/boards-data-store.ts index 8967174c..155a2169 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config-store.ts +++ b/arduino-ide-extension/src/browser/boards/boards-data-store.ts @@ -1,14 +1,15 @@ import { injectable, inject, named } from 'inversify'; import { ILogger } from '@theia/core/lib/common/logger'; +import { deepClone } from '@theia/core/lib/common/objects'; import { MaybePromise } from '@theia/core/lib/common/types'; import { Event, Emitter } from '@theia/core/lib/common/event'; -import { deepClone, notEmpty } from '@theia/core/lib/common/objects'; import { FrontendApplicationContribution, LocalStorageService } from '@theia/core/lib/browser'; -import { BoardsService, ConfigOption, Installable, BoardDetails } from '../../common/protocol'; +import { notEmpty } from '../../common/utils'; import { BoardsServiceClientImpl } from './boards-service-client-impl'; +import { BoardsService, ConfigOption, Installable, BoardDetails, Programmer } from '../../common/protocol'; @injectable() -export class BoardsConfigStore implements FrontendApplicationContribution { +export class BoardsDataStore implements FrontendApplicationContribution { @inject(ILogger) @named('store') @@ -60,39 +61,62 @@ export class BoardsConfigStore implements FrontendApplicationContribution { fqbn: string, boardsPackageVersion: MaybePromise = this.getBoardsPackageVersion(fqbn)): Promise { - const configOptions = await this.getConfig(fqbn, boardsPackageVersion); + const { configOptions } = await this.getData(fqbn, boardsPackageVersion); return ConfigOption.decorate(fqbn, configOptions); } - async getConfig( + async getData( fqbn: string, - boardsPackageVersion: MaybePromise = this.getBoardsPackageVersion(fqbn)): Promise { + boardsPackageVersion: MaybePromise = this.getBoardsPackageVersion(fqbn)): Promise { const version = await boardsPackageVersion; if (!version) { - return []; + return BoardsDataStore.Data.EMPTY; } const key = this.getStorageKey(fqbn, version); - let configOptions = await this.storageService.getData(key, undefined); - if (configOptions) { - return configOptions; + let data = await this.storageService.getData(key, undefined); + if (data) { + if (data.programmers !== undefined) { // to be backward compatible. We did not save the `programmers` into the `localStorage`. + return data; + } } - const details = await this.getBoardDetailsSafe(fqbn); - if (!details) { - return []; + const boardDetails = await this.getBoardDetailsSafe(fqbn); + if (!boardDetails) { + return BoardsDataStore.Data.EMPTY; } - configOptions = details.configOptions; - await this.storageService.setData(key, configOptions); - return configOptions; + data = { configOptions: boardDetails.configOptions, programmers: boardDetails.programmers }; + await this.storageService.setData(key, data); + return data; } - async setSelected( + async selectProgrammer( + { fqbn, selectedProgrammer }: { fqbn: string, selectedProgrammer: Programmer }, + boardsPackageVersion: MaybePromise = this.getBoardsPackageVersion(fqbn)): Promise { + + const data = deepClone(await this.getData(fqbn, boardsPackageVersion)); + const { programmers } = data; + if (!programmers.find(p => Programmer.equals(selectedProgrammer, p))) { + return false; + } + + const version = await boardsPackageVersion; + if (!version) { + return false; + } + + await this.setData({ fqbn, data: { ...data, selectedProgrammer }, version }); + this.fireChanged(); + return true; + } + + async selectConfigOption( { fqbn, option, selectedValue }: { fqbn: string, option: string, selectedValue: string }, boardsPackageVersion: MaybePromise = this.getBoardsPackageVersion(fqbn)): Promise { - const configOptions = deepClone(await this.getConfig(fqbn, boardsPackageVersion)); + const data = deepClone(await this.getData(fqbn, boardsPackageVersion)); + const { configOptions } = data; const configOption = configOptions.find(c => c.option === option); if (!configOption) { return false; @@ -113,16 +137,17 @@ export class BoardsConfigStore implements FrontendApplicationContribution { if (!version) { return false; } - await this.setConfig({ fqbn, configOptions, version }); + + await this.setData({ fqbn, data, version }); this.fireChanged(); return true; } - protected async setConfig( - { fqbn, configOptions, version }: { fqbn: string, configOptions: ConfigOption[], version: Installable.Version }): Promise { + protected async setData( + { fqbn, data, version }: { fqbn: string, data: BoardsDataStore.Data, version: Installable.Version }): Promise { const key = this.getStorageKey(fqbn, version); - return this.storageService.setData(key, configOptions); + return this.storageService.setData(key, data); } protected getStorageKey(fqbn: string, version: Installable.Version): string { @@ -159,3 +184,17 @@ export class BoardsConfigStore implements FrontendApplicationContribution { } } + +export namespace BoardsDataStore { + export interface Data { + readonly configOptions: ConfigOption[]; + readonly programmers: Programmer[]; + readonly selectedProgrammer?: Programmer; + } + export namespace Data { + export const EMPTY: Data = { + configOptions: [], + programmers: [] + }; + } +} diff --git a/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts b/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts deleted file mode 100644 index c9df896c..00000000 --- a/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { CommandRegistry } from '@theia/core/lib/common/command'; -import { MenuModelRegistry, MenuNode } from '@theia/core/lib/common/menu'; -import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; -import { BoardsServiceClientImpl } from './boards-service-client-impl'; -import { Board, ConfigOption } from '../../common/protocol'; -import { FrontendApplicationContribution } from '@theia/core/lib/browser'; -import { ArduinoMenus } from '../arduino-frontend-contribution'; -import { BoardsConfigStore } from './boards-config-store'; -import { MainMenuManager } from '../menu/main-menu-manager'; - -@injectable() -export class BoardsDetailsMenuUpdater implements FrontendApplicationContribution { - - @inject(CommandRegistry) - protected readonly commandRegistry: CommandRegistry; - - @inject(MenuModelRegistry) - protected readonly menuRegistry: MenuModelRegistry; - - @inject(MainMenuManager) - protected readonly mainMenuManager: MainMenuManager; - - @inject(BoardsConfigStore) - protected readonly boardsConfigStore: BoardsConfigStore; - - @inject(BoardsServiceClientImpl) - protected readonly boardsServiceClient: BoardsServiceClientImpl; - - protected readonly toDisposeOnBoardChange = new DisposableCollection(); - - onStart(): void { - this.boardsConfigStore.onChanged(() => this.updateMenuActions(this.boardsServiceClient.boardsConfig.selectedBoard)); - this.boardsServiceClient.onBoardsConfigChanged(({ selectedBoard }) => this.updateMenuActions(selectedBoard)); - this.updateMenuActions(this.boardsServiceClient.boardsConfig.selectedBoard); - } - - protected async updateMenuActions(selectedBoard: Board | undefined): Promise { - if (selectedBoard) { - this.toDisposeOnBoardChange.dispose(); - this.mainMenuManager.update(); - const { fqbn } = selectedBoard; - if (fqbn) { - const configOptions = await this.boardsConfigStore.getConfig(fqbn); - const boardsConfigMenuPath = [...ArduinoMenus.TOOLS, 'z_boardsConfig']; // `z_` is for ordering. - for (const { label, option, values } of configOptions.sort(ConfigOption.LABEL_COMPARATOR)) { - const menuPath = [...boardsConfigMenuPath, `${option}`]; - const commands = new Map() - for (const value of values) { - const id = `${fqbn}-${option}--${value.value}`; - const command = { id }; - const selectedValue = value.value; - const handler = { - execute: () => this.boardsConfigStore.setSelected({ fqbn, option, selectedValue }), - isToggled: () => value.selected - }; - commands.set(id, Object.assign(this.commandRegistry.registerCommand(command, handler), { label: value.label })); - } - this.menuRegistry.registerSubmenu(menuPath, label); - this.toDisposeOnBoardChange.pushAll([ - ...commands.values(), - Disposable.create(() => this.unregisterSubmenu(menuPath)), // We cannot dispose submenu entries: https://github.com/eclipse-theia/theia/issues/7299 - ...Array.from(commands.keys()).map((commandId, index) => { - const { label } = commands.get(commandId)!; - this.menuRegistry.registerMenuAction(menuPath, { commandId, order: String(index), label }); - return Disposable.create(() => this.menuRegistry.unregisterMenuAction(commandId)); - }) - ]); - } - this.mainMenuManager.update(); - } - } - } - - protected unregisterSubmenu(menuPath: string[]): void { - if (menuPath.length < 2) { - throw new Error(`Expected at least two item as a menu-path. Got ${JSON.stringify(menuPath)} instead.`); - } - const toRemove = menuPath[menuPath.length - 1]; - const parentMenuPath = menuPath.slice(0, menuPath.length - 1); - // This is unsafe. Calling `getMenu` with a non-existing menu-path will result in a new menu creation. - // https://github.com/eclipse-theia/theia/issues/7300 - const parent = this.menuRegistry.getMenu(parentMenuPath); - const index = parent.children.findIndex(({ id }) => id === toRemove); - if (index === -1) { - throw new Error(`Could not find menu with menu-path: ${JSON.stringify(menuPath)}.`); - } - (parent.children as Array).splice(index, 1); - } - -} diff --git a/arduino-ide-extension/src/browser/boards/boards-list-widget.ts b/arduino-ide-extension/src/browser/boards/boards-list-widget.ts index 54947d62..c48e76c5 100644 --- a/arduino-ide-extension/src/browser/boards/boards-list-widget.ts +++ b/arduino-ide-extension/src/browser/boards/boards-list-widget.ts @@ -1,7 +1,7 @@ import { inject, injectable } from 'inversify'; import { BoardsPackage, BoardsService } from '../../common/protocol/boards-service'; -import { ListWidget } from '../components/component-list/list-widget'; -import { ListItemRenderer } from '../components/component-list/list-item-renderer'; +import { ListWidget } from '../widgets/component-list/list-widget'; +import { ListItemRenderer } from '../widgets/component-list/list-item-renderer'; @injectable() export class BoardsListWidget extends ListWidget { diff --git a/arduino-ide-extension/src/browser/boards/boards-service-client-impl.ts b/arduino-ide-extension/src/browser/boards/boards-service-client-impl.ts index aa18b5ea..e565fd92 100644 --- a/arduino-ide-extension/src/browser/boards/boards-service-client-impl.ts +++ b/arduino-ide-extension/src/browser/boards/boards-service-client-impl.ts @@ -5,9 +5,15 @@ import { MessageService } from '@theia/core/lib/common/message-service'; import { StorageService } from '@theia/core/lib/browser/storage-service'; import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; import { RecursiveRequired } from '../../common/types'; -import { BoardsServiceClient, AttachedBoardsChangeEvent, BoardInstalledEvent, Board, Port, BoardUninstalledEvent } from '../../common/protocol'; +import { BoardsServiceClient, AttachedBoardsChangeEvent, BoardInstalledEvent, Board, Port, BoardUninstalledEvent, BoardsService } from '../../common/protocol'; import { BoardsConfig } from './boards-config'; import { naturalCompare } from '../../common/utils'; +import { compareAnything } from '../theia/monaco/comparers'; + +interface BoardMatch { + readonly board: Board & Readonly<{ packageName: string }>; + readonly matches: monaco.filters.IMatch[] | undefined; +} @injectable() export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApplicationContribution { @@ -40,6 +46,7 @@ export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApp protected _attachedBoards: Board[] = []; // This does not contain the `Unknown` boards. They're visible from the available ports only. protected _availablePorts: Port[] = []; protected _availableBoards: AvailableBoard[] = []; + protected boardsService: BoardsService; /** * Event when the state of the attached/detached boards has changed. For instance, the user have detached a physical board. @@ -65,7 +72,12 @@ export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApp * When the FE connects to the BE, the BE stets the known boards and ports.\ * This is a DI workaround for not being able to inject the service into the client. */ - init({ attachedBoards, availablePorts }: { attachedBoards: Board[], availablePorts: Port[] }): void { + async init(boardsService: BoardsService): Promise { + this.boardsService = boardsService; + const [attachedBoards, availablePorts] = await Promise.all([ + this.boardsService.getAttachedBoards(), + this.boardsService.getAvailablePorts() + ]); this._attachedBoards = attachedBoards; this._availablePorts = availablePorts; this.reconcileAvailableBoards().then(() => this.tryReconnect()); @@ -157,6 +169,40 @@ export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApp } } + async searchBoards({ query, cores }: { query?: string, cores?: string[] }): Promise> { + const boards = await this.boardsService.allBoards({}); + const coresFilter = !!cores && cores.length + ? ((toFilter: { packageName: string }) => cores.some(core => core === toFilter.packageName)) + : () => true; + if (!query) { + return boards.filter(coresFilter).sort(Board.compare); + } + const toMatch = ((toFilter: Board & { packageName: string }) => (({ board: toFilter, matches: monaco.filters.matchesFuzzy(query, toFilter.name, true) }))); + const compareEntries = (left: BoardMatch, right: BoardMatch, lookFor: string) => { + const leftMatches = left.matches || []; + const rightMatches = right.matches || []; + if (leftMatches.length && !rightMatches.length) { + return -1; + } + if (!leftMatches.length && rightMatches.length) { + return 1; + } + if (leftMatches.length === 0 && rightMatches.length === 0) { + return 0; + } + const leftLabel = left.board.name.replace(/\r?\n/g, ' '); + const rightLabel = right.board.name.replace(/\r?\n/g, ' '); + return compareAnything(leftLabel, rightLabel, lookFor); + } + const normalizedQuery = query.toLowerCase(); + return boards + .filter(coresFilter) + .map(toMatch) + .filter(({ matches }) => !!matches) + .sort((left, right) => compareEntries(left, right, normalizedQuery)) + .map(({ board }) => board); + } + get boardsConfig(): BoardsConfig.Config { return this._boardsConfig; } diff --git a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts index 5d1815ba..9117081e 100644 --- a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts @@ -1,9 +1,9 @@ import { injectable } from 'inversify'; import { MenuModelRegistry } from '@theia/core'; import { BoardsListWidget } from './boards-list-widget'; -import { ArduinoMenus } from '../arduino-frontend-contribution'; import { BoardsPackage } from '../../common/protocol/boards-service'; -import { ListWidgetFrontendContribution } from '../components/component-list/list-widget-frontend-contribution'; +import { ListWidgetFrontendContribution } from '../widgets/component-list/list-widget-frontend-contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; @injectable() export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution { @@ -19,7 +19,7 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont rank: 600 }, toggleCommandId: BoardsListWidgetFrontendContribution.OPEN_MANAGER, - toggleKeybinding: 'ctrlcmd+shift+b' + toggleKeybinding: 'CtrlCmd+Shift+B' }); } @@ -29,9 +29,10 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont registerMenus(menus: MenuModelRegistry): void { if (this.toggleCommand) { - menus.registerMenuAction(ArduinoMenus.TOOLS, { + menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { commandId: this.toggleCommand.id, - label: 'Boards Manager...' + label: 'Boards Manager...', + order: '4' }); } } diff --git a/arduino-ide-extension/src/browser/boards/quick-open/boards-quick-open-service.ts b/arduino-ide-extension/src/browser/boards/quick-open/boards-quick-open-service.ts index 27a21819..45c76041 100644 --- a/arduino-ide-extension/src/browser/boards/quick-open/boards-quick-open-service.ts +++ b/arduino-ide-extension/src/browser/boards/quick-open/boards-quick-open-service.ts @@ -17,7 +17,7 @@ import { import { naturalCompare } from '../../../common/utils'; import { BoardsService, Port, Board, ConfigOption, ConfigValue } from '../../../common/protocol'; import { CoreServiceClientImpl } from '../../core-service-client-impl'; -import { BoardsConfigStore } from '../boards-config-store'; +import { BoardsDataStore } from '../boards-data-store'; import { BoardsServiceClientImpl, AvailableBoard } from '../boards-service-client-impl'; @injectable() @@ -41,8 +41,8 @@ export class BoardsQuickOpenService implements QuickOpenContribution, QuickOpenM @inject(BoardsServiceClientImpl) protected readonly boardsServiceClient: BoardsServiceClientImpl; - @inject(BoardsConfigStore) - protected readonly configStore: BoardsConfigStore; + @inject(BoardsDataStore) + protected readonly boardsDataStore: BoardsDataStore; @inject(CoreServiceClientImpl) protected coreServiceClient: CoreServiceClientImpl; @@ -52,7 +52,7 @@ export class BoardsQuickOpenService implements QuickOpenContribution, QuickOpenM // Attached boards plus the user's config. protected availableBoards: AvailableBoard[] = []; // Only for the `selected` one from the `availableBoards`. Note: the `port` of the `selected` is optional. - protected boardConfigs: ConfigOption[] = []; + protected data: BoardsDataStore.Data = BoardsDataStore.Data.EMPTY; protected allBoards: Board.Detailed[] = [] protected selectedBoard?: (AvailableBoard & { port: Port }); @@ -86,7 +86,7 @@ export class BoardsQuickOpenService implements QuickOpenContribution, QuickOpenM placeholder += 'No board selected.'; } placeholder += 'Type to filter boards'; - if (this.boardConfigs.length) { + if (this.data.configOptions.length) { placeholder += ' or use the ↓↑ keys to adjust the board settings...'; } else { placeholder += '...'; @@ -129,7 +129,7 @@ export class BoardsQuickOpenService implements QuickOpenContribution, QuickOpenM // Show the config only if the `input` is empty. if (!lookFor.trim().length) { - toAccept.push(...this.boardConfigs.map((config, i) => { + toAccept.push(...this.data.configOptions.map((config, i) => { let group: QuickOpenGroupItemOptions | undefined = undefined; if (i === 0) { group = { groupLabel: 'Board Settings', showBorder: true }; @@ -157,14 +157,14 @@ export class BoardsQuickOpenService implements QuickOpenContribution, QuickOpenM protected async update(availableBoards: AvailableBoard[]): Promise { // `selectedBoard` is not an attached board, we need to show the board settings for it (TODO: clarify!) const selectedBoard = availableBoards.filter(AvailableBoard.hasPort).find(({ selected }) => selected); - const [configs, boards] = await Promise.all([ - selectedBoard && selectedBoard.fqbn ? this.configStore.getConfig(selectedBoard.fqbn) : Promise.resolve([]), - this.boardsService.searchBoards({}) + const [data, boards] = await Promise.all([ + selectedBoard && selectedBoard.fqbn ? this.boardsDataStore.getData(selectedBoard.fqbn) : Promise.resolve(BoardsDataStore.Data.EMPTY), + this.boardsService.allBoards({}) ]); this.allBoards = Board.decorateBoards(selectedBoard, boards) .filter(board => !availableBoards.some(availableBoard => Board.sameAs(availableBoard, board))); this.availableBoards = availableBoards; - this.boardConfigs = configs; + this.data = data; this.selectedBoard = selectedBoard; if (this.isOpen) { @@ -280,7 +280,7 @@ export class BoardsQuickOpenService implements QuickOpenContribution, QuickOpenM return; } const { fqbn } = this.selectedBoard; - this.configStore.setSelected({ + this.boardsDataStore.selectConfigOption({ fqbn, option: config.option, selectedValue: value.value diff --git a/arduino-ide-extension/src/browser/config-service-client-impl.ts b/arduino-ide-extension/src/browser/config-service-client-impl.ts index e8ca9cf9..6351bb59 100644 --- a/arduino-ide-extension/src/browser/config-service-client-impl.ts +++ b/arduino-ide-extension/src/browser/config-service-client-impl.ts @@ -4,7 +4,7 @@ import { Event, Emitter } from '@theia/core/lib/common/event'; import { CommandService } from '@theia/core/lib/common/command'; import { MessageService } from '@theia/core/lib/common/message-service'; import { ConfigServiceClient, Config } from '../common/protocol'; -import { ArduinoCommands } from './arduino-commands'; +import { Settings } from './contributions/settings'; @injectable() export class ConfigServiceClientImpl implements ConfigServiceClient { @@ -32,7 +32,7 @@ export class ConfigServiceClientImpl implements ConfigServiceClient { this.invalidConfigPopup = this.messageService.error(`Your CLI configuration is invalid. Do you want to correct it now?`, 'No', 'Yes') .then(answer => { if (answer === 'Yes') { - this.commandService.executeCommand(ArduinoCommands.OPEN_CLI_CONFIG.id) + this.commandService.executeCommand(Settings.Commands.OPEN_CLI_CONFIG.id) } this.invalidConfigPopup = undefined; }) diff --git a/arduino-ide-extension/src/browser/contributions/close-sketch.ts b/arduino-ide-extension/src/browser/contributions/close-sketch.ts new file mode 100644 index 00000000..3e2f1651 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/close-sketch.ts @@ -0,0 +1,89 @@ +import { inject, injectable } from 'inversify'; +import { remote } from 'electron'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, URI } from './contribution'; +import { SaveAsSketch } from './save-as-sketch'; +import { EditorManager } from '@theia/editor/lib/browser'; +import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor'; + +@injectable() +export class CloseSketch extends SketchContribution { + + @inject(EditorManager) + protected readonly editorManager: EditorManager; + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(CloseSketch.Commands.CLOSE_SKETCH, { + execute: async () => { + const sketch = await this.currentSketch(); + if (!sketch) { + return; + } + const isTemp = await this.sketchService.isTemp(sketch); + const uri = await this.currentSketchFile(); + if (!uri) { + return; + } + if (isTemp && await this.wasTouched(uri)) { + const { response } = await remote.dialog.showMessageBox({ + type: 'question', + buttons: ["Don't Save", 'Cancel', 'Save'], + message: 'Do you want to save changes to this sketch before closing?', + detail: "If you don't save, your changes will be lost." + }); + if (response === 1) { // Cancel + return; + } + if (response === 2) { // Save + const saved = await this.commandService.executeCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH.id, { openAfterMove: false, execOnlyIfTemp: true }); + if (!saved) { // If it was not saved, do bail the close. + return; + } + } + } + window.close(); + } + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { + commandId: CloseSketch.Commands.CLOSE_SKETCH.id, + label: 'Close', + order: '5' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: CloseSketch.Commands.CLOSE_SKETCH.id, + keybinding: 'CtrlCmd+W' // TODO: Windows binding? + }); + } + + /** + * If the file was ever touched/modified. We get this based on the `version` of the monaco model. + */ + protected async wasTouched(uri: string): Promise { + const editorWidget = await this.editorManager.getByUri(new URI(uri)); + if (editorWidget) { + const { editor } = editorWidget; + if (editor instanceof MonacoEditor) { + const versionId = editor.getControl().getModel()?.getVersionId(); + if (Number.isInteger(versionId) && versionId! > 1) { + return true; + } + } + } + return false; + } + +} + +export namespace CloseSketch { + export namespace Commands { + export const CLOSE_SKETCH: Command = { + id: 'arduino-close-sketch' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/contribution.ts b/arduino-ide-extension/src/browser/contributions/contribution.ts new file mode 100644 index 00000000..6fdb13ab --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/contribution.ts @@ -0,0 +1,107 @@ +import { inject, injectable, interfaces } from 'inversify'; +import URI from '@theia/core/lib/common/uri'; +import { ILogger } from '@theia/core/lib/common/logger'; +import { notEmpty } from '@theia/core/lib/common/objects'; +import { FileSystem } from '@theia/filesystem/lib/common'; +import { LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { MessageService } from '@theia/core/lib/common/message-service'; +import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; +import { open, OpenerService } from '@theia/core/lib/browser/opener-service'; +import { MenuModelRegistry, MenuContribution } from '@theia/core/lib/common/menu'; +import { KeybindingRegistry, KeybindingContribution } from '@theia/core/lib/browser/keybinding'; +import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; +import { Command, CommandRegistry, CommandContribution, CommandService } from '@theia/core/lib/common/command'; +import { SketchesService, ConfigService, FileSystemExt, Sketch } from '../../common/protocol'; +import { EditorMode } from '../editor-mode'; + +export { Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry, URI, Sketch, open }; + +@injectable() +export abstract class Contribution implements CommandContribution, MenuContribution, KeybindingContribution, TabBarToolbarContribution { + + @inject(ILogger) + protected readonly logger: ILogger; + + @inject(MessageService) + protected readonly messageService: MessageService; + + @inject(CommandService) + protected readonly commandService: CommandService; + + @inject(WorkspaceService) + protected readonly workspaceService: WorkspaceService; + + @inject(EditorMode) + protected readonly editorMode: EditorMode; + + @inject(LabelProvider) + protected readonly labelProvider: LabelProvider; + + registerCommands(registry: CommandRegistry): void { + } + + registerMenus(registry: MenuModelRegistry): void { + } + + registerKeybindings(registry: KeybindingRegistry): void { + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + } + +} + +@injectable() +export abstract class SketchContribution extends Contribution { + + @inject(FileSystem) + protected readonly fileSystem: FileSystem; + + @inject(FileSystemExt) + protected readonly fileSystemExt: FileSystemExt; + + @inject(ConfigService) + protected readonly configService: ConfigService; + + @inject(SketchesService) + protected readonly sketchService: SketchesService; + + @inject(OpenerService) + protected readonly openerService: OpenerService; + + protected async currentSketch(): Promise { + const sketches = (await Promise.all(this.workspaceService.tryGetRoots().map(({ uri }) => this.sketchService.getSketchFolder(uri)))).filter(notEmpty); + if (!sketches.length) { + return; + } + if (sketches.length > 1) { + console.log(`Multiple sketch folders were found in the workspace. Falling back to the first one. Sketch folders: ${JSON.stringify(sketches)}`); + } + return sketches[0]; + } + + protected async currentSketchFile(): Promise { + const sketch = await this.currentSketch(); + if (sketch) { + const uri = new URI(sketch.uri).resolve(`${sketch.name}.ino`).toString(); + const exists = await this.fileSystem.exists(uri); + if (!exists) { + this.messageService.warn(`Could not find sketch file: ${uri}`); + return undefined; + } + return uri; + } + return undefined; + } + +} + +export namespace Contribution { + export function configure(bind: interfaces.Bind, serviceIdentifier: interfaces.ServiceIdentifier): void { + bind(serviceIdentifier).toSelf().inSingletonScope(); + bind(CommandContribution).toService(serviceIdentifier); + bind(MenuContribution).toService(serviceIdentifier); + bind(KeybindingContribution).toService(serviceIdentifier); + bind(TabBarToolbarContribution).toService(serviceIdentifier); + } +} diff --git a/arduino-ide-extension/src/browser/contributions/edit-contributions.ts b/arduino-ide-extension/src/browser/contributions/edit-contributions.ts new file mode 100644 index 00000000..7d551e19 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/edit-contributions.ts @@ -0,0 +1,274 @@ +import { inject, injectable } from 'inversify'; +import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'; +import { ClipboardService } from '@theia/core/lib/browser/clipboard-service'; +import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service'; +import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service'; +import { EDITOR_FONT_DEFAULTS } from '@theia/editor/lib/browser/editor-preferences'; +import { Contribution, Command, MenuModelRegistry, KeybindingRegistry, CommandRegistry } from './contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; + +// TODO: [macOS]: to remove `Start Dictation...` and `Emoji & Symbol` see this thread: https://github.com/electron/electron/issues/8283#issuecomment-269522072 +// Depends on https://github.com/eclipse-theia/theia/pull/7964 +@injectable() +export class EditContributions extends Contribution { + + @inject(MonacoEditorService) + protected readonly codeEditorService: MonacoEditorService; + + @inject(ClipboardService) + protected readonly clipboardService: ClipboardService; + + @inject(PreferenceService) + protected readonly preferences: PreferenceService; + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(EditContributions.Commands.GO_TO_LINE, { execute: () => this.run('editor.action.gotoLine') }); + registry.registerCommand(EditContributions.Commands.TOGGLE_COMMENT, { execute: () => this.run('editor.action.commentLine') }); + registry.registerCommand(EditContributions.Commands.INDENT_LINES, { execute: () => this.run('editor.action.indentLines') }); + registry.registerCommand(EditContributions.Commands.OUTDENT_LINES, { execute: () => this.run('editor.action.outdentLines') }); + registry.registerCommand(EditContributions.Commands.FIND, { execute: () => this.run('actions.find') }); + registry.registerCommand(EditContributions.Commands.FIND_NEXT, { execute: () => this.run('actions.findWithSelection') }); + registry.registerCommand(EditContributions.Commands.FIND_PREVIOUS, { execute: () => this.run('editor.action.nextMatchFindAction') }); + registry.registerCommand(EditContributions.Commands.USE_FOR_FIND, { execute: () => this.run('editor.action.previousSelectionMatchFindAction') }); + registry.registerCommand(EditContributions.Commands.INCREASE_FONT_SIZE, { + execute: () => this.preferences.set('editor.fontSize', this.preferences.get('editor.fontSize', EDITOR_FONT_DEFAULTS.fontSize) + 1) + }); + registry.registerCommand(EditContributions.Commands.DECREASE_FONT_SIZE, { + execute: () => this.preferences.set('editor.fontSize', this.preferences.get('editor.fontSize', EDITOR_FONT_DEFAULTS.fontSize) - 1) + }); + /* Tools */registry.registerCommand(EditContributions.Commands.AUTO_FORMAT, { execute: () => this.run('editor.action.formatDocument') }); + registry.registerCommand(EditContributions.Commands.COPY_FOR_FORUM, { + execute: async () => { + const value = await this.currentValue(); + if (value !== undefined) { + this.clipboardService.writeText(`[code] +${value} +[/code]`) + } + } + }); + registry.registerCommand(EditContributions.Commands.COPY_FOR_GITHUB, { + execute: async () => { + const value = await this.currentValue(); + if (value !== undefined) { + this.clipboardService.writeText(`\`\`\`cpp +${value} +\`\`\``) + } + } + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: CommonCommands.CUT.id, + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: CommonCommands.COPY.id, + order: '1' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: EditContributions.Commands.COPY_FOR_FORUM.id, + label: 'Copy for Forum', + order: '2' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: EditContributions.Commands.COPY_FOR_GITHUB.id, + label: 'Copy for GitHub', + order: '3' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: CommonCommands.PASTE.id, + order: '4' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: CommonCommands.SELECT_ALL.id, + order: '5' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { + commandId: EditContributions.Commands.GO_TO_LINE.id, + label: 'Go to Line...', + order: '6' + }); + + registry.registerMenuAction(ArduinoMenus.EDIT__CODE_CONTROL_GROUP, { + commandId: EditContributions.Commands.TOGGLE_COMMENT.id, + label: 'Comment/Uncomment', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__CODE_CONTROL_GROUP, { + commandId: EditContributions.Commands.INDENT_LINES.id, + label: 'Increase Indent', + order: '1' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__CODE_CONTROL_GROUP, { + commandId: EditContributions.Commands.OUTDENT_LINES.id, + label: 'Decrease Indent', + order: '2' + }); + + registry.registerMenuAction(ArduinoMenus.EDIT__FONT_CONTROL_GROUP, { + commandId: EditContributions.Commands.INCREASE_FONT_SIZE.id, + label: 'Increase Font Size', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__FONT_CONTROL_GROUP, { + commandId: EditContributions.Commands.DECREASE_FONT_SIZE.id, + label: 'Decrease Font Size', + order: '1' + }); + + registry.registerMenuAction(ArduinoMenus.EDIT__FIND_GROUP, { + commandId: EditContributions.Commands.FIND.id, + label: 'Find', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__FIND_GROUP, { + commandId: EditContributions.Commands.FIND_NEXT.id, + label: 'Find Next', + order: '1' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__FIND_GROUP, { + commandId: EditContributions.Commands.FIND_PREVIOUS.id, + label: 'Find Previous', + order: '2' + }); + registry.registerMenuAction(ArduinoMenus.EDIT__FIND_GROUP, { + commandId: EditContributions.Commands.USE_FOR_FIND.id, + label: 'Use Selection for Find', // XXX: The Java IDE uses `Use Selection For Find`. + order: '3' + }); + + // `Tools` + registry.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { + commandId: EditContributions.Commands.AUTO_FORMAT.id, + label: 'Auto Format', // XXX: The Java IDE uses `Use Selection For Find`. + order: '0' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: EditContributions.Commands.COPY_FOR_FORUM.id, + keybinding: 'CtrlCmd+Shift+C' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.COPY_FOR_GITHUB.id, + keybinding: 'CtrlCmd+Alt+C' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.GO_TO_LINE.id, + keybinding: 'CtrlCmd+L' + }); + + registry.registerKeybinding({ + command: EditContributions.Commands.TOGGLE_COMMENT.id, + keybinding: 'CtrlCmd+/' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.INDENT_LINES.id, + keybinding: 'Tab' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.OUTDENT_LINES.id, + keybinding: 'Shift+Tab' + }); + + registry.registerKeybinding({ + command: EditContributions.Commands.INCREASE_FONT_SIZE.id, + keybinding: 'CtrlCmd+=' // TODO: compare with the Java IDE. It uses `⌘+`. There is no `+` on EN_US. + }); + registry.registerKeybinding({ + command: EditContributions.Commands.DECREASE_FONT_SIZE.id, + keybinding: 'CtrlCmd+-' + }); + + registry.registerKeybinding({ + command: EditContributions.Commands.FIND.id, + keybinding: 'CtrlCmd+F' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.FIND_NEXT.id, + keybinding: 'CtrlCmd+G' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.FIND_PREVIOUS.id, + keybinding: 'CtrlCmd+Shift+G' + }); + registry.registerKeybinding({ + command: EditContributions.Commands.USE_FOR_FIND.id, + keybinding: 'CtrlCmd+E' + }); + + // `Tools` + registry.registerKeybinding({ + command: EditContributions.Commands.AUTO_FORMAT.id, + keybinding: 'CtrlCmd+T' + }); + } + + protected async current(): Promise { + return this.codeEditorService.getFocusedCodeEditor() || this.codeEditorService.getActiveCodeEditor(); + } + + protected async currentValue(): Promise { + const currentEditor = await this.current() + return currentEditor?.getValue(); + } + + protected async run(commandId: string): Promise { + const editor = await this.current(); + if (editor) { + const action = editor.getAction(commandId); + if (action) { + return action.run(); + } + } + } + +} + +export namespace EditContributions { + export namespace Commands { + export const COPY_FOR_FORUM: Command = { + id: 'arduino-copy-for-forum' + }; + export const COPY_FOR_GITHUB: Command = { + id: 'arduino-copy-for-github' + }; + export const GO_TO_LINE: Command = { + id: 'arduino-go-to-line' + }; + export const TOGGLE_COMMENT: Command = { + id: 'arduino-toggle-comment' + }; + export const INDENT_LINES: Command = { + id: 'arduino-indent-lines' + }; + export const OUTDENT_LINES: Command = { + id: 'arduino-outdent-lines' + }; + export const FIND: Command = { + id: 'arduino-find' + }; + export const FIND_NEXT: Command = { + id: 'arduino-find-next' + }; + export const FIND_PREVIOUS: Command = { + id: 'arduino-find-previous' + }; + export const USE_FOR_FIND: Command = { + id: 'arduino-for-find' + }; + export const INCREASE_FONT_SIZE: Command = { + id: 'arduino-increase-font-size' + }; + export const DECREASE_FONT_SIZE: Command = { + id: 'arduino-decrease-font-size' + }; + export const AUTO_FORMAT: Command = { + id: 'arduino-auto-format' // `Auto Format` should belong to `Tool`. + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/new-sketch.ts b/arduino-ide-extension/src/browser/contributions/new-sketch.ts new file mode 100644 index 00000000..d788d2db --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/new-sketch.ts @@ -0,0 +1,63 @@ +import { injectable } from 'inversify'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { ArduinoToolbar } from '../toolbar/arduino-toolbar'; +import { SketchContribution, URI, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution'; + +@injectable() +export class NewSketch extends SketchContribution { + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(NewSketch.Commands.NEW_SKETCH, { + execute: () => this.newSketch() + }); + registry.registerCommand(NewSketch.Commands.NEW_SKETCH__TOOLBAR, { + isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', + execute: () => registry.executeCommand(NewSketch.Commands.NEW_SKETCH.id) + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { + commandId: NewSketch.Commands.NEW_SKETCH.id, + label: 'New', + order: '0' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: NewSketch.Commands.NEW_SKETCH.id, + keybinding: 'CtrlCmd+N' + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + id: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id, + command: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id, + tooltip: 'New', + priority: 3 + }); + } + + async newSketch(): Promise { + try { + const sketch = await this.sketchService.createNewSketch(); + this.workspaceService.open(new URI(sketch.uri)); + } catch (e) { + await this.messageService.error(e.toString()); + } + } + +} + +export namespace NewSketch { + export namespace Commands { + export const NEW_SKETCH: Command = { + id: 'arduino-new-sketch' + }; + export const NEW_SKETCH__TOOLBAR: Command = { + id: 'arduino-new-sketch--toolbar' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts b/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts new file mode 100644 index 00000000..33383bc3 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts @@ -0,0 +1,51 @@ +import { injectable } from 'inversify'; +import { remote } from 'electron'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry } from './contribution'; + +@injectable() +export class OpenSketchExternal extends SketchContribution { + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(OpenSketchExternal.Commands.OPEN_EXTERNAL, { + execute: () => this.openExternal() + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.SKETCH__UTILS_GROUP, { + commandId: OpenSketchExternal.Commands.OPEN_EXTERNAL.id, + label: 'Show Sketch Folder', + order: '0' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: OpenSketchExternal.Commands.OPEN_EXTERNAL.id, + keybinding: 'CtrlCmd+Alt+K' + }); + } + + protected async openExternal(): Promise { + const uri = await this.currentSketchFile(); + if (uri) { + const exists = this.fileSystem.exists(uri); + if (exists) { + const fsPath = await this.fileSystem.getFsPath(uri); + if (fsPath) { + remote.shell.showItemInFolder(fsPath); + } + } + } + } + +} + +export namespace OpenSketchExternal { + export namespace Commands { + export const OPEN_EXTERNAL: Command = { + id: 'arduino-open-sketch-external' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/open-sketch.ts b/arduino-ide-extension/src/browser/contributions/open-sketch.ts new file mode 100644 index 00000000..74323009 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/open-sketch.ts @@ -0,0 +1,136 @@ +import { inject, injectable } from 'inversify'; +import { remote } from 'electron'; +import { MaybePromise } from '@theia/core/lib/common/types'; +import { Widget, ContextMenuRenderer } from '@theia/core/lib/browser'; +import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { ArduinoToolbar } from '../toolbar/arduino-toolbar'; +import { SketchContribution, Sketch, URI, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution'; + +@injectable() +export class OpenSketch extends SketchContribution { + + @inject(MenuModelRegistry) + protected readonly menuRegistry: MenuModelRegistry; + + @inject(ContextMenuRenderer) + protected readonly contextMenuRenderer: ContextMenuRenderer; + + protected readonly toDisposeBeforeCreateNewContextMenu = new DisposableCollection(); + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(OpenSketch.Commands.OPEN_SKETCH, { + execute: arg => Sketch.is(arg) ? this.openSketch(arg) : this.openSketch() + }); + registry.registerCommand(OpenSketch.Commands.OPEN_SKETCH__TOOLBAR, { + isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', + execute: async (_: Widget, target: EventTarget) => { + const sketches = await this.sketchService.getSketches(); + if (!sketches.length) { + this.openSketch(); + } else { + this.toDisposeBeforeCreateNewContextMenu.dispose(); + if (!(target instanceof HTMLElement)) { + return; + } + const { parentElement } = target; + if (!parentElement) { + return; + } + + this.menuRegistry.registerMenuAction(ArduinoMenus.OPEN_SKETCH__CONTEXT__OPEN_GROUP, { + commandId: OpenSketch.Commands.OPEN_SKETCH.id, + label: 'Open...' + }); + this.toDisposeBeforeCreateNewContextMenu.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(OpenSketch.Commands.OPEN_SKETCH))); + for (const sketch of sketches) { + const command = { id: `arduino-open-sketch--${sketch.uri}` }; + const handler = { execute: () => this.openSketch(sketch) }; + this.toDisposeBeforeCreateNewContextMenu.push(registry.registerCommand(command, handler)); + this.menuRegistry.registerMenuAction(ArduinoMenus.OPEN_SKETCH__CONTEXT__RECENT_GROUP, { + commandId: command.id, + label: sketch.name + }); + this.toDisposeBeforeCreateNewContextMenu.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command))); + } + const options = { + menuPath: ArduinoMenus.OPEN_SKETCH__CONTEXT, + anchor: { + x: parentElement.getBoundingClientRect().left, + y: parentElement.getBoundingClientRect().top + parentElement.offsetHeight + } + } + this.contextMenuRenderer.render(options); + } + } + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { + commandId: OpenSketch.Commands.OPEN_SKETCH.id, + label: 'Open...', + order: '1' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: OpenSketch.Commands.OPEN_SKETCH.id, + keybinding: 'CtrlCmd+O' + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + id: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id, + command: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id, + tooltip: 'Open', + priority: 4 + }); + } + + async openSketch(toOpen: MaybePromise = this.selectSketch()): Promise { + const sketch = await toOpen; + if (sketch) { + this.workspaceService.open(new URI(sketch.uri)); + } + } + + protected async selectSketch(): Promise { + const config = await this.configService.getConfiguration(); + const defaultPath = await this.fileSystem.getFsPath(config.sketchDirUri); + const { filePaths } = await remote.dialog.showOpenDialog({ + defaultPath, + properties: ['createDirectory', 'openFile'], + filters: [ + { + name: 'Sketch', + extensions: ['ino'] + } + ] + }); + if (!filePaths.length) { + return undefined; + } + if (filePaths.length > 1) { + this.logger.warn(`Multiple sketches were selected: ${filePaths}. Using the first one.`); + } + // TODO: validate sketch file name against the sketch folder. Move the file if required. + const sketchFilePath = filePaths[0]; + const sketchFileUri = await this.fileSystemExt.getUri(sketchFilePath); + return this.sketchService.getSketchFolder(sketchFileUri); + } + +} + +export namespace OpenSketch { + export namespace Commands { + export const OPEN_SKETCH: Command = { + id: 'arduino-open-sketch' + }; + export const OPEN_SKETCH__TOOLBAR: Command = { + id: 'arduino-open-sketch--toolbar' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/quit-app.ts b/arduino-ide-extension/src/browser/contributions/quit-app.ts new file mode 100644 index 00000000..2eee530b --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/quit-app.ts @@ -0,0 +1,45 @@ +import { injectable } from 'inversify'; +import { remote } from 'electron'; +import { isOSX, isWindows } from '@theia/core/lib/common/os'; +import { Contribution, Command, MenuModelRegistry, KeybindingRegistry, CommandRegistry } from './contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; + +@injectable() +export class QuitApp extends Contribution { + + registerCommands(registry: CommandRegistry): void { + if (!isOSX) { + registry.registerCommand(QuitApp.Commands.QUIT_APP, { + execute: () => remote.app.quit() + }); + } + } + + registerMenus(registry: MenuModelRegistry): void { + if (!isOSX) { + registry.registerMenuAction(ArduinoMenus.FILE__QUIT_GROUP, { + commandId: QuitApp.Commands.QUIT_APP.id, + label: 'Quit', + order: '0' + }); + } + } + + registerKeybindings(registry: KeybindingRegistry): void { + if (!isOSX) { + registry.registerKeybinding({ + command: QuitApp.Commands.QUIT_APP.id, + keybinding: isWindows ? 'Alt+F4' : 'Ctrl+Q' + }); + } + } + +} + +export namespace QuitApp { + export namespace Commands { + export const QUIT_APP: Command = { + id: 'arduino-quit-app' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts new file mode 100644 index 00000000..0b5f9753 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts @@ -0,0 +1,86 @@ +import { injectable } from 'inversify'; +import { remote } from 'electron'; +import * as dateFormat from 'dateformat'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { SketchContribution, URI, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry } from './contribution'; + +@injectable() +export class SaveAsSketch extends SketchContribution { + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH, { + execute: args => this.saveAs(args) + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { + commandId: SaveAsSketch.Commands.SAVE_AS_SKETCH.id, + label: 'Save As...', + order: '7' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: SaveAsSketch.Commands.SAVE_AS_SKETCH.id, + keybinding: 'CtrlCmd+Shift+S' + }); + } + + /** + * Resolves `true` if the sketch was successfully saved as something. + */ + async saveAs({ execOnlyIfTemp, openAfterMove }: SaveAsSketch.Options = SaveAsSketch.Options.DEFAULT): Promise { + const sketch = await this.currentSketch(); + if (!sketch) { + return false; + } + + const isTemp = await this.sketchService.isTemp(sketch); + if (!isTemp && !!execOnlyIfTemp) { + return false; + } + + // If target does not exist, propose a `directories.user`/${sketch.name} path + // If target exists, propose `directories.user`/${sketch.name}_copy_${yyyymmddHHMMss} + const sketchDirUri = new URI((await this.configService.getConfiguration()).sketchDirUri); + const exists = await this.fileSystem.exists(sketchDirUri.resolve(sketch.name).toString()); + const defaultUri = exists + ? sketchDirUri.resolve(sketchDirUri.resolve(`${sketch.name}_copy_${dateFormat(new Date(), 'yyyymmddHHMMss')}`).toString()) + : sketchDirUri.resolve(sketch.name); + const defaultPath = await this.fileSystem.getFsPath(defaultUri.toString())!; + const { filePath, canceled } = await remote.dialog.showSaveDialog({ title: 'Save sketch folder as...', defaultPath }); + if (!filePath || canceled) { + return false; + } + const destinationUri = await this.fileSystemExt.getUri(filePath); + if (!destinationUri) { + return false; + } + const workspaceUri = await this.sketchService.copy(sketch, { destinationUri }); + if (workspaceUri && openAfterMove) { + this.workspaceService.open(new URI(workspaceUri)); + } + return !!workspaceUri; + } + +} + +export namespace SaveAsSketch { + export namespace Commands { + export const SAVE_AS_SKETCH: Command = { + id: 'arduino-save-as-sketch' + }; + } + export interface Options { + readonly execOnlyIfTemp?: boolean; + readonly openAfterMove?: boolean; + } + export namespace Options { + export const DEFAULT: Options = { + execOnlyIfTemp: false, + openAfterMove: true + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/save-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-sketch.ts new file mode 100644 index 00000000..a047d5ca --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/save-sketch.ts @@ -0,0 +1,59 @@ +import { injectable } from 'inversify'; +import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { ArduinoToolbar } from '../toolbar/arduino-toolbar'; +import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution'; + +@injectable() +export class SaveSketch extends SketchContribution { + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(SaveSketch.Commands.SAVE_SKETCH, { + execute: () => this.saveSketch() + }); + registry.registerCommand(SaveSketch.Commands.SAVE_SKETCH__TOOLBAR, { + isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', + execute: () => registry.executeCommand(SaveSketch.Commands.SAVE_SKETCH.id) + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { + commandId: SaveSketch.Commands.SAVE_SKETCH.id, + label: 'Save', + order: '6' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: SaveSketch.Commands.SAVE_SKETCH.id, + keybinding: 'CtrlCmd+S' + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + id: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id, + command: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id, + tooltip: 'Save', + priority: 5 + }); + } + + async saveSketch(): Promise { + return this.commandService.executeCommand(CommonCommands.SAVE_ALL.id); + } + +} + +export namespace SaveSketch { + export namespace Commands { + export const SAVE_SKETCH: Command = { + id: 'arduino-save-sketch' + }; + export const SAVE_SKETCH__TOOLBAR: Command = { + id: 'arduino-save-sketch--toolbar' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/settings.ts b/arduino-ide-extension/src/browser/contributions/settings.ts new file mode 100644 index 00000000..a1e899aa --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/settings.ts @@ -0,0 +1,38 @@ +import { injectable } from 'inversify'; +import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'; +import { URI, Command, MenuModelRegistry, CommandRegistry, SketchContribution, open } from './contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; + +@injectable() +export class Settings extends SketchContribution { + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(Settings.Commands.OPEN_CLI_CONFIG, { + execute: () => this.configService.getCliConfigFileUri().then(uri => open(this.openerService, new URI(uri))) + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.FILE__SETTINGS_GROUP, { + commandId: CommonCommands.OPEN_PREFERENCES.id, + label: 'Preferences...', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.FILE__SETTINGS_GROUP, { + commandId: Settings.Commands.OPEN_CLI_CONFIG.id, + label: 'Open CLI Configuration', + order: '1', + }); + } + +} + +export namespace Settings { + export namespace Commands { + export const OPEN_CLI_CONFIG: Command = { + id: 'arduino-open-cli-config', + label: 'Open CLI Configuration', + category: 'Arduino' + } + } +} diff --git a/arduino-ide-extension/src/browser/contributions/sketch-control.ts b/arduino-ide-extension/src/browser/contributions/sketch-control.ts new file mode 100644 index 00000000..f4cebf5a --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/sketch-control.ts @@ -0,0 +1,129 @@ +import { inject, injectable } from 'inversify'; +import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'; +import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell'; +import { WorkspaceCommands } from '@theia/workspace/lib/browser'; +import { ContextMenuRenderer } from '@theia/core/lib/browser/context-menu-renderer'; +import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; +import { URI, SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry, open } from './contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; + +@injectable() +export class SketchControl extends SketchContribution { + + @inject(ApplicationShell) + protected readonly shell: ApplicationShell; + + @inject(MenuModelRegistry) + protected readonly menuRegistry: MenuModelRegistry; + + @inject(ContextMenuRenderer) + protected readonly contextMenuRenderer: ContextMenuRenderer; + + protected readonly toDisposeBeforeCreateNewContextMenu = new DisposableCollection(); + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR, { + isVisible: widget => this.shell.getWidgets('main').indexOf(widget) !== -1, + execute: async () => { + this.toDisposeBeforeCreateNewContextMenu.dispose(); + const sketch = await this.currentSketch(); + if (!sketch) { + return; + } + + const target = document.getElementById(SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id); + if (!(target instanceof HTMLElement)) { + return; + } + const { parentElement } = target; + if (!parentElement) { + return; + } + + const uris = await this.sketchService.getSketchFiles(sketch.uri); + // TODO: order them! The Java IDE orders them by tab index. Use the shell and the editor manager to achieve it. + for (let i = 0; i < uris.length; i++) { + const uri = new URI(uris[i]); + const command = { id: `arduino-focus-file--${uri.toString()}` }; + const handler = { execute: () => open(this.openerService, uri) }; + this.toDisposeBeforeCreateNewContextMenu.push(registry.registerCommand(command, handler)); + this.menuRegistry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__RESOURCES_GROUP, { + commandId: command.id, + label: this.labelProvider.getName(uri), + order: `${i}` + }); + this.toDisposeBeforeCreateNewContextMenu.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command))); + } + const options = { + menuPath: ArduinoMenus.SKETCH_CONTROL__CONTEXT, + anchor: { + x: parentElement.getBoundingClientRect().left, + y: parentElement.getBoundingClientRect().top + parentElement.offsetHeight + } + } + this.contextMenuRenderer.render(options); + } + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, { + commandId: WorkspaceCommands.NEW_FILE.id, + label: 'New Tab', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, { + commandId: WorkspaceCommands.FILE_RENAME.id, + label: 'Rename', + order: '1' + }); + registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, { + commandId: WorkspaceCommands.FILE_DELETE.id, + label: 'Delete', + order: '2' + }); + + registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__NAVIGATION_GROUP, { + commandId: CommonCommands.PREVIOUS_TAB.id, + label: 'Previous Tab', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__NAVIGATION_GROUP, { + commandId: CommonCommands.NEXT_TAB.id, + label: 'Next Tab', + order: '0' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: WorkspaceCommands.NEW_FILE.id, + keybinding: 'CtrlCmd+Shift+N' + }); + registry.registerKeybinding({ + command: CommonCommands.PREVIOUS_TAB.id, + keybinding: 'CtrlCmd+Alt+Left' // TODO: check why electron does not show the keybindings in the UI. + }); + registry.registerKeybinding({ + command: CommonCommands.NEXT_TAB.id, + keybinding: 'CtrlCmd+Alt+Right' + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + id: SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id, + command: SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id + }); + } + +} + +export namespace SketchControl { + export namespace Commands { + export const OPEN_SKETCH_CONTROL__TOOLBAR: Command = { + id: 'arduino-open-sketch-control--toolbar', + iconClass: 'fa fa-caret-down' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts new file mode 100644 index 00000000..079a4a86 --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -0,0 +1,136 @@ +import { inject, injectable } from 'inversify'; +import { OutputChannelManager } from '@theia/output/lib/common/output-channel'; +import { CoreService } from '../../common/protocol'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { ArduinoToolbar } from '../toolbar/arduino-toolbar'; +import { BoardsDataStore } from '../boards/boards-data-store'; +import { MonitorConnection } from '../monitor/monitor-connection'; +import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl'; +import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution'; + +@injectable() +export class UploadSketch extends SketchContribution { + + @inject(CoreService) + protected readonly coreService: CoreService; + + @inject(MonitorConnection) + protected readonly monitorConnection: MonitorConnection; + + @inject(BoardsDataStore) + protected readonly boardsDataStore: BoardsDataStore; + + @inject(BoardsServiceClientImpl) + protected readonly boardsServiceClientImpl: BoardsServiceClientImpl; + + @inject(OutputChannelManager) + protected readonly outputChannelManager: OutputChannelManager; + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH, { + execute: () => this.uploadSketch() + }); + registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH_USING_PROGRAMMER, { + execute: () => this.uploadSketch(true) + }); + registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR, { + isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', + execute: () => registry.executeCommand(UploadSketch.Commands.UPLOAD_SKETCH.id) + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, { + commandId: UploadSketch.Commands.UPLOAD_SKETCH.id, + label: 'Upload', + order: '0' + }); + registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, { + commandId: UploadSketch.Commands.UPLOAD_SKETCH_USING_PROGRAMMER.id, + label: 'Upload Using Programmer', + order: '1' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: UploadSketch.Commands.UPLOAD_SKETCH.id, + keybinding: 'CtrlCmd+U' + }); + registry.registerKeybinding({ + command: UploadSketch.Commands.UPLOAD_SKETCH_USING_PROGRAMMER.id, + keybinding: 'CtrlCmd+Shift+U' + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + id: UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR.id, + command: UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR.id, + tooltip: 'Upload', + priority: 1 + }); + } + + async uploadSketch(usingProgrammer: boolean = false): Promise { + const uri = await this.currentSketchFile(); + if (!uri) { + return; + } + const monitorConfig = this.monitorConnection.monitorConfig; + if (monitorConfig) { + await this.monitorConnection.disconnect(); + } + try { + const { boardsConfig } = this.boardsServiceClientImpl; + if (!boardsConfig || !boardsConfig.selectedBoard) { + throw new Error('No boards selected. Please select a board.'); + } + const { selectedPort } = boardsConfig; + if (!selectedPort) { + throw new Error('No ports selected. Please select a port.'); + } + if (!boardsConfig.selectedBoard.fqbn) { + throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`); + } + const [fqbn, data] = await Promise.all([ + this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn), + this.boardsDataStore.getData(boardsConfig.selectedBoard.fqbn) + ]); + this.outputChannelManager.getChannel('Arduino: upload').clear(); + const programmer = usingProgrammer ? data.selectedProgrammer : undefined; + if (usingProgrammer && !programmer) { + this.messageService.warn('Programmer is not selected. Uploading without programmer.', { timeout: 2000 }); + } + await this.coreService.upload({ + sketchUri: uri, + fqbn, + port: selectedPort.address, + optimizeForDebug: this.editorMode.compileForDebug, + programmer + }); + this.messageService.info('Done uploading.', { timeout: 1000 }); + } catch (e) { + this.messageService.error(e.toString()); + } finally { + if (monitorConfig) { + await this.monitorConnection.connect(monitorConfig); + } + } + } + +} + +export namespace UploadSketch { + export namespace Commands { + export const UPLOAD_SKETCH: Command = { + id: 'arduino-upload-sketch' + }; + export const UPLOAD_SKETCH_USING_PROGRAMMER: Command = { + id: 'arduino-upload-sketch-using-programmer' + }; + export const UPLOAD_SKETCH_TOOLBAR: Command = { + id: 'arduino-upload-sketch--toolbar' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/verify-sketch.ts b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts new file mode 100644 index 00000000..954233dc --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts @@ -0,0 +1,100 @@ +import { inject, injectable } from 'inversify'; +import { OutputChannelManager } from '@theia/output/lib/common/output-channel'; +import { CoreService } from '../../common/protocol'; +import { ArduinoMenus } from '../menu/arduino-menus'; +import { ArduinoToolbar } from '../toolbar/arduino-toolbar'; +import { BoardsDataStore } from '../boards/boards-data-store'; +import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl'; +import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution'; + +@injectable() +export class VerifySketch extends SketchContribution { + + @inject(CoreService) + protected readonly coreService: CoreService; + + @inject(BoardsDataStore) + protected readonly boardsDataStore: BoardsDataStore; + + @inject(BoardsServiceClientImpl) + protected readonly boardsServiceClientImpl: BoardsServiceClientImpl; + + @inject(OutputChannelManager) + protected readonly outputChannelManager: OutputChannelManager; + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, { + execute: () => this.verifySketch() + }); + registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR, { + isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left', + execute: () => registry.executeCommand(VerifySketch.Commands.VERIFY_SKETCH.id) + }); + } + + registerMenus(registry: MenuModelRegistry): void { + registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, { + commandId: VerifySketch.Commands.VERIFY_SKETCH.id, + label: 'Verify/Compile', + order: '2' + }); + } + + registerKeybindings(registry: KeybindingRegistry): void { + registry.registerKeybinding({ + command: VerifySketch.Commands.VERIFY_SKETCH.id, + keybinding: 'CtrlCmd+R' + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + id: VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR.id, + command: VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR.id, + tooltip: 'Verify', + priority: 0 + }); + } + + async verifySketch(): Promise { + const uri = await this.currentSketchFile(); + if (!uri) { + return; + } + try { + const { boardsConfig } = this.boardsServiceClientImpl; + if (!boardsConfig || !boardsConfig.selectedBoard) { + throw new Error('No boards selected. Please select a board.'); + } + if (!boardsConfig.selectedBoard.fqbn) { + throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`); + } + const [data, fqbn] = await Promise.all([ + this.boardsDataStore.getData(boardsConfig.selectedBoard.fqbn), + this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn) + ]); + this.outputChannelManager.getChannel('Arduino: compile').clear(); + await this.coreService.compile({ + sketchUri: uri, + fqbn, + optimizeForDebug: this.editorMode.compileForDebug, + programmer: data.selectedProgrammer + }); + this.messageService.info('Done compiling.', { timeout: 1000 }); + } catch (e) { + this.messageService.error(e.toString()); + } + } + +} + +export namespace VerifySketch { + export namespace Commands { + export const VERIFY_SKETCH: Command = { + id: 'arduino-verify-sketch' + }; + export const VERIFY_SKETCH_TOOLBAR: Command = { + id: 'arduino-verify-sketch--toolbar' + }; + } +} diff --git a/arduino-ide-extension/src/browser/customization/arduino-application-shell.ts b/arduino-ide-extension/src/browser/customization/arduino-application-shell.ts deleted file mode 100644 index f6922d56..00000000 --- a/arduino-ide-extension/src/browser/customization/arduino-application-shell.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { ApplicationShell, Widget, Saveable, FocusTracker, Message } from '@theia/core/lib/browser'; -import { EditorWidget } from '@theia/editor/lib/browser'; -import { injectable, inject } from 'inversify'; -import { EditorMode } from '../editor-mode'; - -@injectable() -export class ArduinoApplicationShell extends ApplicationShell { - - @inject(EditorMode) - protected readonly editorMode: EditorMode; - - protected refreshBottomPanelToggleButton() { - if (this.editorMode.proMode) { - super.refreshBottomPanelToggleButton(); - } - } - - protected async track(widget: Widget): Promise { - if (this.editorMode.proMode) { - super.track(widget); - } else { - const tracker = (this as any).tracker as FocusTracker; - tracker.add(widget); - this.disableClose(Saveable.apply(widget)); - if (ApplicationShell.TrackableWidgetProvider.is(widget)) { - for (const toTrack of await widget.getTrackableWidgets()) { - tracker.add(toTrack); - this.disableClose(Saveable.apply(toTrack)); - } - if (widget.onDidChangeTrackableWidgets) { - widget.onDidChangeTrackableWidgets(widgets => widgets.forEach(w => this.track(w))); - } - } - } - } - - private disableClose(widget: Widget | undefined): void { - if (widget instanceof EditorWidget) { - const onCloseRequest = (_: Message) => { - // NOOP - }; - (widget as any).onCloseRequest = onCloseRequest.bind(widget); - } - } - -} diff --git a/arduino-ide-extension/src/browser/customization/arduino-frontend-application.ts b/arduino-ide-extension/src/browser/customization/arduino-frontend-application.ts deleted file mode 100644 index 23455c91..00000000 --- a/arduino-ide-extension/src/browser/customization/arduino-frontend-application.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { injectable, inject } from 'inversify'; -import { FileSystem } from '@theia/filesystem/lib/common/filesystem'; -import { CommandService } from '@theia/core/lib/common/command'; -import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; -import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { EditorMode } from '../editor-mode'; -import { ArduinoCommands } from '../arduino-commands'; - -@injectable() -export class ArduinoFrontendApplication extends FrontendApplication { - - @inject(FileSystem) - protected readonly fileSystem: FileSystem; - - @inject(WorkspaceService) - protected readonly workspaceService: WorkspaceService; - - @inject(CommandService) - protected readonly commandService: CommandService; - - @inject(EditorMode) - protected readonly editorMode: EditorMode; - - protected async initializeLayout(): Promise { - await super.initializeLayout(); - // If not in PRO mode, we open the sketch file with all the related files. - // Otherwise, we reuse the workbench's restore functionality and we do not open anything at all. - // TODO: check `otherwise`. Also, what if we check for opened editors, instead of blindly opening them? - if (!this.editorMode.proMode) { - const roots = await this.workspaceService.roots; - for (const root of roots) { - const exists = await this.fileSystem.exists(root.uri); - if (exists) { - await this.commandService.executeCommand(ArduinoCommands.OPEN_SKETCH_FILES.id, root.uri); - } - } - } - } - -} diff --git a/arduino-ide-extension/src/browser/customization/arduino-monaco-status-bar-contribution.ts b/arduino-ide-extension/src/browser/customization/arduino-monaco-status-bar-contribution.ts deleted file mode 100644 index 39466c71..00000000 --- a/arduino-ide-extension/src/browser/customization/arduino-monaco-status-bar-contribution.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { MonacoStatusBarContribution } from '@theia/monaco/lib/browser/monaco-status-bar-contribution'; - -export class ArduinoMonacoStatusBarContribution extends MonacoStatusBarContribution { - - protected setConfigTabSizeWidget() { - } - - protected setLineEndingWidget() { - } - -} diff --git a/arduino-ide-extension/src/browser/customization/arduino-navigator-contribution.ts b/arduino-ide-extension/src/browser/customization/arduino-navigator-contribution.ts deleted file mode 100644 index 5fb3e83b..00000000 --- a/arduino-ide-extension/src/browser/customization/arduino-navigator-contribution.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { injectable, inject } from 'inversify'; -import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; -import { EditorMode } from '../editor-mode'; - -@injectable() -export class ArduinoNavigatorContribution extends FileNavigatorContribution { - - @inject(EditorMode) - protected readonly editorMode: EditorMode; - - async initializeLayout(app: FrontendApplication): Promise { - if (this.editorMode.proMode) { - return super.initializeLayout(app); - } - } - -} diff --git a/arduino-ide-extension/src/browser/customization/arduino-output-tool-contribution.ts b/arduino-ide-extension/src/browser/customization/arduino-output-tool-contribution.ts deleted file mode 100644 index 9d98d4aa..00000000 --- a/arduino-ide-extension/src/browser/customization/arduino-output-tool-contribution.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; -import { OutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution'; -import { EditorMode } from '../editor-mode'; - -@injectable() -export class ArduinoOutputToolContribution extends OutputToolbarContribution { - - @inject(EditorMode) - protected readonly editorMode: EditorMode; - - async registerToolbarItems(toolbarRegistry: TabBarToolbarRegistry): Promise { - if (this.editorMode.proMode) { - super.registerToolbarItems(toolbarRegistry); - } - } - -} diff --git a/arduino-ide-extension/src/browser/customization/arduino-search-in-workspace-contribution.ts b/arduino-ide-extension/src/browser/customization/arduino-search-in-workspace-contribution.ts deleted file mode 100644 index 26677baa..00000000 --- a/arduino-ide-extension/src/browser/customization/arduino-search-in-workspace-contribution.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { inject, injectable } from 'inversify'; -import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; -import { EditorMode } from '../editor-mode'; - -@injectable() -export class ArduinoSearchInWorkspaceContribution extends SearchInWorkspaceFrontendContribution { - - @inject(EditorMode) - protected readonly editorMode: EditorMode; - - async initializeLayout(app: FrontendApplication): Promise { - if (this.editorMode.proMode) { - return super.initializeLayout(app); - } - } - -} diff --git a/arduino-ide-extension/src/browser/editor-mode.ts b/arduino-ide-extension/src/browser/editor-mode.ts index 2b9afb7e..bd3df946 100644 --- a/arduino-ide-extension/src/browser/editor-mode.ts +++ b/arduino-ide-extension/src/browser/editor-mode.ts @@ -2,10 +2,9 @@ import { injectable, inject } from 'inversify'; import { ApplicationShell, FrontendApplicationContribution, FrontendApplication, Widget } from '@theia/core/lib/browser'; import { EditorWidget } from '@theia/editor/lib/browser'; import { OutputWidget } from '@theia/output/lib/browser/output-widget'; -import { MainMenuManager } from './menu/main-menu-manager'; +import { MainMenuManager } from '../common/main-menu-manager'; import { BoardsListWidget } from './boards/boards-list-widget'; import { LibraryListWidget } from './library/library-list-widget'; -import { ArduinoShellLayoutRestorer } from './shell/arduino-shell-layout-restorer'; @injectable() export class EditorMode implements FrontendApplicationContribution { @@ -42,7 +41,7 @@ export class EditorMode implements FrontendApplicationContribution { // `storeLayout` has a sync API but the implementation is async, we store the layout manually before we reload the page. // See: https://github.com/eclipse-theia/theia/issues/6579 // XXX: hack instead of injecting the `ArduinoShellLayoutRestorer` we have to retrieve it from the application to avoid DI cycle. - const layoutRestorer = (this.app as any).layoutRestorer as ArduinoShellLayoutRestorer + const layoutRestorer = (this.app as any).layoutRestorer as { storeLayoutAsync(app: FrontendApplication): Promise }; await layoutRestorer.storeLayoutAsync(this.app); window.location.reload(true); } diff --git a/arduino-ide-extension/src/browser/library/library-list-widget.ts b/arduino-ide-extension/src/browser/library/library-list-widget.ts index 6e90ac75..bb7f03c8 100644 --- a/arduino-ide-extension/src/browser/library/library-list-widget.ts +++ b/arduino-ide-extension/src/browser/library/library-list-widget.ts @@ -1,7 +1,7 @@ import { inject, injectable } from 'inversify'; import { Library, LibraryService } from '../../common/protocol/library-service'; -import { ListWidget } from '../components/component-list/list-widget'; -import { ListItemRenderer } from '../components/component-list/list-item-renderer'; +import { ListWidget } from '../widgets/component-list/list-widget'; +import { ListItemRenderer } from '../widgets/component-list/list-item-renderer'; @injectable() export class LibraryListWidget extends ListWidget { diff --git a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts index ed165c7a..eb87dd19 100644 --- a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts @@ -3,7 +3,7 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser/fronten import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution'; import { MenuModelRegistry } from '@theia/core'; import { LibraryListWidget } from './library-list-widget'; -import { ArduinoMenus } from '../arduino-frontend-contribution'; +import { ArduinoMenus } from '../menu/arduino-menus'; @injectable() export class LibraryListWidgetFrontendContribution extends AbstractViewContribution implements FrontendApplicationContribution { @@ -17,7 +17,7 @@ export class LibraryListWidgetFrontendContribution extends AbstractViewContribut rank: 700 }, toggleCommandId: `${LibraryListWidget.WIDGET_ID}:toggle`, - toggleKeybinding: 'ctrlcmd+shift+l' + toggleKeybinding: 'CtrlCmd+Shift+I' }); } @@ -27,9 +27,10 @@ export class LibraryListWidgetFrontendContribution extends AbstractViewContribut registerMenus(menus: MenuModelRegistry): void { if (this.toggleCommand) { - menus.registerMenuAction(ArduinoMenus.TOOLS, { + menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { commandId: this.toggleCommand.id, - label: 'Manage Libraries...' + label: 'Manage Libraries...', + order: '3' }); } } diff --git a/arduino-ide-extension/src/browser/menu/arduino-menus.ts b/arduino-ide-extension/src/browser/menu/arduino-menus.ts new file mode 100644 index 00000000..471de834 --- /dev/null +++ b/arduino-ide-extension/src/browser/menu/arduino-menus.ts @@ -0,0 +1,52 @@ +import { MAIN_MENU_BAR } from '@theia/core/lib/common/menu'; +import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution'; +import { isOSX } from '@theia/core'; + +export namespace ArduinoMenus { + + // Main menu + // -- File + export const FILE__SKETCH_GROUP = [...CommonMenus.FILE, '0_sketch']; + export const FILE__PRINT_GROUP = [...CommonMenus.FILE, '1_print']; + // XXX: on macOS, the settings group is not under `File` + export const FILE__SETTINGS_GROUP = [...(isOSX ? MAIN_MENU_BAR : CommonMenus.FILE), '2_settings']; + export const FILE__QUIT_GROUP = [...CommonMenus.FILE, '3_quit']; + + // -- Edit + // `Copy`, `Copy to Forum`, `Paste`, etc. + // Note: `1_undo` is the first group from Theia, we start with `2` + export const EDIT__TEXT_CONTROL_GROUP = [...CommonMenus.EDIT, '2_text_control']; + // `Comment/Uncomment`, etc. + export const EDIT__CODE_CONTROL_GROUP = [...CommonMenus.EDIT, '3_code_control']; + export const EDIT__FONT_CONTROL_GROUP = [...CommonMenus.EDIT, '4_font_control']; + export const EDIT__FIND_GROUP = [...CommonMenus.EDIT, '5_find']; + + // -- Sketch + export const SKETCH = [...MAIN_MENU_BAR, '3_sketch']; + export const SKETCH__MAIN_GROUP = [...SKETCH, '0_main']; + export const SKETCH__UTILS_GROUP = [...SKETCH, '1_utils']; + + // -- Tools + export const TOOLS = [...MAIN_MENU_BAR, '4_tools']; + // `Auto Format`, `Library Manager...`, `Boards Manager...` + export const TOOLS__MAIN_GROUP = [...TOOLS, '0_main']; + // Core settings, such as `Processor` and `Programmers` for the board. + export const TOOLS__BOARD_SETTINGS_GROUP = [...TOOLS, '1_board_settings']; + + // Context menu + // -- Open + export const OPEN_SKETCH__CONTEXT = ['arduino-open-sketch--context']; + export const OPEN_SKETCH__CONTEXT__OPEN_GROUP = [...OPEN_SKETCH__CONTEXT, '0_open']; + export const OPEN_SKETCH__CONTEXT__RECENT_GROUP = [...OPEN_SKETCH__CONTEXT, '1_recent']; + export const OPEN_SKETCH__CONTEXT__EXAMPLES_GROUP = [...OPEN_SKETCH__CONTEXT, '2_examples']; + + // -- Sketch control + export const SKETCH_CONTROL__CONTEXT = ['arduino-sketch-control--context']; + // `New Tab`, `Rename`, `Delete` + export const SKETCH_CONTROL__CONTEXT__MAIN_GROUP = [...SKETCH_CONTROL__CONTEXT, '0_main']; + // `Previous Tab`, `Next Tab` + export const SKETCH_CONTROL__CONTEXT__NAVIGATION_GROUP = [...SKETCH_CONTROL__CONTEXT, '1_navigation']; + // Sketch files opened in editors + export const SKETCH_CONTROL__CONTEXT__RESOURCES_GROUP = [...SKETCH_CONTROL__CONTEXT, '2_resources']; + +} diff --git a/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts b/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts deleted file mode 100644 index 11fe0589..00000000 --- a/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import '../../../src/browser/style/browser-menu.css' -import { ContainerModule } from 'inversify'; -import { BrowserMenuBarContribution, BrowserMainMenuFactory } from '@theia/core/lib/browser/menu/browser-menu-plugin'; -import { MainMenuManager } from './main-menu-manager'; -import { ArduinoMenuContribution } from './arduino-menu-contribution'; -import { ArduinoBrowserMainMenuFactory } from './arduino-browser-main-menu-factory'; - - -export default new ContainerModule((bind, unbind, isBound, rebind) => { - bind(ArduinoBrowserMainMenuFactory).toSelf().inSingletonScope(); - bind(MainMenuManager).toService(ArduinoBrowserMainMenuFactory); - rebind(BrowserMainMenuFactory).toService(ArduinoBrowserMainMenuFactory); - rebind(BrowserMenuBarContribution).to(ArduinoMenuContribution).inSingletonScope(); -}); diff --git a/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx b/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx index 343cb796..a37cd38d 100644 --- a/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx +++ b/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; -import { injectable, inject } from "inversify"; -import { AbstractViewContribution } from "@theia/core/lib/browser"; -import { MonitorWidget } from "./monitor-widget"; -import { MenuModelRegistry, Command, CommandRegistry } from "@theia/core"; -import { ArduinoMenus } from "../arduino-frontend-contribution"; -import { TabBarToolbarContribution, TabBarToolbarRegistry } from "@theia/core/lib/browser/shell/tab-bar-toolbar"; +import { injectable, inject } from 'inversify'; +import { AbstractViewContribution } from '@theia/core/lib/browser'; +import { MonitorWidget } from './monitor-widget'; +import { MenuModelRegistry, Command, CommandRegistry } from '@theia/core'; +import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { ArduinoToolbar } from '../toolbar/arduino-toolbar'; import { MonitorModel } from './monitor-model'; +import { ArduinoMenus } from '../menu/arduino-menus'; export namespace SerialMonitor { export namespace Commands { @@ -42,15 +42,16 @@ export class MonitorViewContribution extends AbstractViewContribution .p-TabBar-tabCloseIcon, -body:not(.arduino-advanced-mode) .p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-current > .p-TabBar-tabCloseIcon { - background-image: none; - cursor: pointer; -} - -body:not(.arduino-advanced-mode) .p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable.theia-mod-dirty:hover > .p-TabBar-tabCloseIcon, -body:not(.arduino-advanced-mode) .p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable.theia-mod-dirty > .p-TabBar-tabCloseIcon:hover { - background-size: 10px; - background-image: var(--theia-icon-circle); - cursor: pointer; -} \ No newline at end of file diff --git a/arduino-ide-extension/src/browser/style/index.css b/arduino-ide-extension/src/browser/style/index.css index 2540171a..bb8c88c3 100644 --- a/arduino-ide-extension/src/browser/style/index.css +++ b/arduino-ide-extension/src/browser/style/index.css @@ -1,9 +1,10 @@ @import './list-widget.css'; -@import './board-select-dialog.css'; +@import './boards-config-dialog.css'; @import './main.css'; -@import './editor.css'; @import './monitor.css'; @import './arduino-select.css'; +@import './status-bar.css'; +@import './terminal.css'; .theia-input.warning:focus { outline-width: 1px; diff --git a/arduino-ide-extension/src/browser/style/main.css b/arduino-ide-extension/src/browser/style/main.css index 1f62e515..14d5f040 100644 --- a/arduino-ide-extension/src/browser/style/main.css +++ b/arduino-ide-extension/src/browser/style/main.css @@ -2,15 +2,6 @@ background: var(--theia-editorGroupHeader-tabsBackground); } -.theia-output { - background: var(--theia-terminal-background); - color: var(--theia-terminal-foreground); -} - -#outputView { - cursor: text; -} - .p-TabBar-toolbar .item.arduino-tool-item { margin-left: 3px; } @@ -21,14 +12,15 @@ align-items: center; height: 24px; width: 24px; - background: var(--theia-button-background); + background: var(--theia-arduino-toolbar-background); } .p-TabBar-toolbar .item.arduino-tool-item > div:hover { - background: var(--theia-button-hoverBackground); + background: (--theia-arduino-toolbar-hoverBackground); } -.arduino-verify, .arduino-upload { +.arduino-verify-sketch--toolbar, +.arduino-upload-sketch--toolbar { border-radius: 12px; } @@ -42,22 +34,27 @@ mask-size: 800%; } -.arduino-save-file-icon { +.arduino-save-sketch--toolbar-icon { -webkit-mask-position: 59px -4px; mask-position: 59px -4px; } -.arduino-verify-icon { +.arduino-verify-sketch--toolbar-icon { -webkit-mask-position: 188px -4px; mask-position: 188px -4px; } -.arduino-upload-icon { +.arduino-upload-sketch--toolbar-icon { -webkit-mask-position: 156px -4px; mask-position: 156px -4px; } -.arduino-show-open-context-menu-icon { +.arduino-new-sketch--toolbar-icon { + -webkit-mask-position: 124px -4px; + mask-position: 124px -4px; +} + +.arduino-open-sketch--toolbar-icon { -webkit-mask-position: 92px -4px; mask-position: 92px -4px; } @@ -117,7 +114,17 @@ display: flex; justify-content: center; align-items: center; - color: var(--theia-titleBar-activeBackground);; + color: var(--theia-titleBar-activeBackground); +} + +.arduino-open-boards-control-icon { + mask: none; + -webkit-mask: none; + background: none; + display: flex; + justify-content: center; + align-items: center; + color: var(--theia-titleBar-activeBackground); } .monaco-editor .margin { @@ -125,6 +132,10 @@ box-sizing: border-box; } +.theia-output .monaco-editor .margin { + border-right: none; +} + .noWrapInfo { white-space: nowrap; overflow: hidden; @@ -138,3 +149,9 @@ .p-Widget.dialogOverlay .dialogBlock { background-color: var(--theia-arduino-foreground); } + +#arduino-open-sketch-control--toolbar { + background-color: var(--theia-tab-inactiveBackground); + border: 1px solid var(--theia-arduino-toolbar-background); + padding: 2px 0px 2px 9px; +} diff --git a/arduino-ide-extension/src/browser/style/status-bar.css b/arduino-ide-extension/src/browser/style/status-bar.css new file mode 100644 index 00000000..de464c24 --- /dev/null +++ b/arduino-ide-extension/src/browser/style/status-bar.css @@ -0,0 +1,7 @@ +#theia-statusBar .area .element.arduino-selected-port { + margin-left: 0px; +} + +#theia-statusBar .area .element.arduino-selected-board > *:last-child { + margin-right: 0px; +} diff --git a/arduino-ide-extension/src/browser/style/terminal.css b/arduino-ide-extension/src/browser/style/terminal.css new file mode 100644 index 00000000..34ea6ccf --- /dev/null +++ b/arduino-ide-extension/src/browser/style/terminal.css @@ -0,0 +1,3 @@ +.terminal-container .xterm .xterm-helper-textarea { + opacity: 0 !important; /* fix secondary cursor-like issue. See https://github.com/eclipse-theia/theia/issues/8158 */ +} diff --git a/arduino-ide-extension/src/browser/customization/arduino-about-dialog.ts b/arduino-ide-extension/src/browser/theia/core/about-dialog.ts similarity index 77% rename from arduino-ide-extension/src/browser/customization/arduino-about-dialog.ts rename to arduino-ide-extension/src/browser/theia/core/about-dialog.ts index e9f4ae3f..e4ec9962 100644 --- a/arduino-ide-extension/src/browser/customization/arduino-about-dialog.ts +++ b/arduino-ide-extension/src/browser/theia/core/about-dialog.ts @@ -1,9 +1,9 @@ import { injectable, inject, postConstruct } from 'inversify'; -import { AboutDialog, ABOUT_CONTENT_CLASS } from '@theia/core/lib/browser/about-dialog'; -import { ConfigService } from '../../common/protocol/config-service'; +import { AboutDialog as TheiaAboutDialog, ABOUT_CONTENT_CLASS } from '@theia/core/lib/browser/about-dialog'; +import { ConfigService } from '../../../common/protocol/config-service'; @injectable() -export class ArduinoAboutDialog extends AboutDialog { +export class AboutDialog extends TheiaAboutDialog { @inject(ConfigService) protected readonly configService: ConfigService; diff --git a/arduino-ide-extension/src/browser/theia/core/application-shell.ts b/arduino-ide-extension/src/browser/theia/core/application-shell.ts new file mode 100644 index 00000000..d8767008 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/application-shell.ts @@ -0,0 +1,44 @@ + +import { injectable, inject } from 'inversify'; +import { EditorWidget } from '@theia/editor/lib/browser'; +import { CommandService } from '@theia/core/lib/common/command'; +import { PreferencesWidget } from '@theia/preferences/lib/browser/views/preference-widget'; +import { ApplicationShell as TheiaApplicationShell, Widget } from '@theia/core/lib/browser'; +import { EditorMode } from '../../editor-mode'; +import { SaveAsSketch } from '../../contributions/save-as-sketch'; + +@injectable() +export class ApplicationShell extends TheiaApplicationShell { + + @inject(EditorMode) + protected readonly editorMode: EditorMode; + + @inject(CommandService) + protected readonly commandService: CommandService; + + protected track(widget: Widget): void { + super.track(widget); + if (!this.editorMode.proMode) { + if (widget instanceof EditorWidget) { + // Always allow closing the whitelisted files. + // TODO: It would be better to blacklist the sketch files only. + if (['tasks.json', + 'launch.json', + 'settings.json', + 'arduino-cli.yaml'].some(fileName => widget.editor.uri.toString().endsWith(fileName))) { + return; + } + } + if (widget instanceof PreferencesWidget) { + return; + } + widget.title.closable = false; + } + } + + async saveAll(): Promise { + await super.saveAll(); + await this.commandService.executeCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH.id, { execOnlyIfTemp: true, openAfterMove: true }); + } + +} diff --git a/arduino-ide-extension/src/browser/menu/arduino-browser-main-menu-factory.ts b/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts similarity index 54% rename from arduino-ide-extension/src/browser/menu/arduino-browser-main-menu-factory.ts rename to arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts index e7970c79..18bc79af 100644 --- a/arduino-ide-extension/src/browser/menu/arduino-browser-main-menu-factory.ts +++ b/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts @@ -1,9 +1,9 @@ import { injectable } from 'inversify'; -import { BrowserMainMenuFactory, MenuBarWidget } from '@theia/core/lib/browser/menu/browser-menu-plugin'; -import { MainMenuManager } from './main-menu-manager'; +import { BrowserMainMenuFactory as TheiaBrowserMainMenuFactory, MenuBarWidget } from '@theia/core/lib/browser/menu/browser-menu-plugin'; +import { MainMenuManager } from '../../../common/main-menu-manager'; @injectable() -export class ArduinoBrowserMainMenuFactory extends BrowserMainMenuFactory implements MainMenuManager { +export class BrowserMainMenuFactory extends TheiaBrowserMainMenuFactory implements MainMenuManager { protected menuBar: MenuBarWidget | undefined; diff --git a/arduino-ide-extension/src/browser/theia/core/browser-menu-module.ts b/arduino-ide-extension/src/browser/theia/core/browser-menu-module.ts new file mode 100644 index 00000000..3ef17660 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/browser-menu-module.ts @@ -0,0 +1,13 @@ +import '../../../../src/browser/style/browser-menu.css'; +import { ContainerModule } from 'inversify'; +import { BrowserMenuBarContribution, BrowserMainMenuFactory as TheiaBrowserMainMenuFactory } from '@theia/core/lib/browser/menu/browser-menu-plugin'; +import { MainMenuManager } from '../../../common/main-menu-manager'; +import { ArduinoMenuContribution } from './browser-menu-plugin'; +import { BrowserMainMenuFactory } from './browser-main-menu-factory'; + +export default new ContainerModule((bind, unbind, isBound, rebind) => { + bind(BrowserMainMenuFactory).toSelf().inSingletonScope(); + bind(MainMenuManager).toService(BrowserMainMenuFactory); + rebind(TheiaBrowserMainMenuFactory).toService(BrowserMainMenuFactory); + rebind(BrowserMenuBarContribution).to(ArduinoMenuContribution).inSingletonScope(); +}); diff --git a/arduino-ide-extension/src/browser/menu/arduino-menu-contribution.ts b/arduino-ide-extension/src/browser/theia/core/browser-menu-plugin.ts similarity index 100% rename from arduino-ide-extension/src/browser/menu/arduino-menu-contribution.ts rename to arduino-ide-extension/src/browser/theia/core/browser-menu-plugin.ts diff --git a/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts new file mode 100644 index 00000000..ac1f309b --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts @@ -0,0 +1,29 @@ +import { injectable } from 'inversify'; +import { MenuModelRegistry } from '@theia/core/lib/common/menu'; +import { CommonFrontendContribution as TheiaCommonFrontendContribution, CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'; + +@injectable() +export class CommonFrontendContribution extends TheiaCommonFrontendContribution { + + registerMenus(registry: MenuModelRegistry): void { + super.registerMenus(registry); + for (const command of [ + CommonCommands.SAVE, + CommonCommands.SAVE_ALL, + CommonCommands.CUT, + CommonCommands.COPY, + CommonCommands.PASTE, + CommonCommands.COPY_PATH, + CommonCommands.FIND, + CommonCommands.REPLACE, + CommonCommands.AUTO_SAVE, + CommonCommands.OPEN_PREFERENCES, + CommonCommands.SELECT_ICON_THEME, + CommonCommands.SELECT_COLOR_THEME, + CommonCommands.OPEN_PREFERENCES + ]) { + registry.unregisterMenuAction(command); + } + } + +} diff --git a/arduino-ide-extension/src/browser/customization/arduino-connection-status-service.ts b/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts similarity index 75% rename from arduino-ide-extension/src/browser/customization/arduino-connection-status-service.ts rename to arduino-ide-extension/src/browser/theia/core/connection-status-service.ts index addff7d7..eae61d39 100644 --- a/arduino-ide-extension/src/browser/customization/arduino-connection-status-service.ts +++ b/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts @@ -1,11 +1,15 @@ import { inject, injectable, postConstruct } from 'inversify'; import { Disposable } from '@theia/core/lib/common/disposable'; import { StatusBarAlignment } from '@theia/core/lib/browser/status-bar/status-bar'; -import { FrontendConnectionStatusService, ApplicationConnectionStatusContribution, ConnectionStatus } from '@theia/core/lib/browser/connection-status-service'; -import { ArduinoDaemonClientImpl } from '../arduino-daemon-client-impl'; +import { + FrontendConnectionStatusService as TheiaFrontendConnectionStatusService, + ApplicationConnectionStatusContribution as TheiaApplicationConnectionStatusContribution, + ConnectionStatus +} from '@theia/core/lib/browser/connection-status-service'; +import { ArduinoDaemonClientImpl } from '../../arduino-daemon-client-impl'; @injectable() -export class ArduinoFrontendConnectionStatusService extends FrontendConnectionStatusService { +export class FrontendConnectionStatusService extends TheiaFrontendConnectionStatusService { @inject(ArduinoDaemonClientImpl) protected readonly daemonClient: ArduinoDaemonClientImpl; @@ -23,7 +27,7 @@ export class ArduinoFrontendConnectionStatusService extends FrontendConnectionSt } @injectable() -export class ArduinoApplicationConnectionStatusContribution extends ApplicationConnectionStatusContribution { +export class ApplicationConnectionStatusContribution extends TheiaApplicationConnectionStatusContribution { @inject(ArduinoDaemonClientImpl) protected readonly daemonClient: ArduinoDaemonClientImpl; diff --git a/arduino-ide-extension/src/browser/theia/core/frontend-application.ts b/arduino-ide-extension/src/browser/theia/core/frontend-application.ts new file mode 100644 index 00000000..45b6ae5c --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/frontend-application.ts @@ -0,0 +1,31 @@ +import { injectable, inject } from 'inversify'; +import { FileSystem } from '@theia/filesystem/lib/common/filesystem'; +import { CommandService } from '@theia/core/lib/common/command'; +import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; +import { FrontendApplication as TheiaFrontendApplication } from '@theia/core/lib/browser/frontend-application'; +import { ArduinoCommands } from '../../arduino-commands'; + +@injectable() +export class FrontendApplication extends TheiaFrontendApplication { + + @inject(FileSystem) + protected readonly fileSystem: FileSystem; + + @inject(WorkspaceService) + protected readonly workspaceService: WorkspaceService; + + @inject(CommandService) + protected readonly commandService: CommandService; + + protected async initializeLayout(): Promise { + await super.initializeLayout(); + const roots = await this.workspaceService.roots; + for (const root of roots) { + const exists = await this.fileSystem.exists(root.uri); + if (exists) { + await this.commandService.executeCommand(ArduinoCommands.OPEN_SKETCH_FILES.id, root.uri); + } + } + } + +} diff --git a/arduino-ide-extension/src/browser/theia/core/keybindings.ts b/arduino-ide-extension/src/browser/theia/core/keybindings.ts new file mode 100644 index 00000000..40c83318 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/keybindings.ts @@ -0,0 +1,28 @@ +import { injectable } from 'inversify'; +import { Command } from '@theia/core/lib/common/command'; +import { Keybinding } from '@theia/core/lib/common/keybinding'; +import { KeybindingRegistry as TheiaKeybindingRegistry, KeybindingScope } from '@theia/core/lib/browser/keybinding'; + +@injectable() +export class KeybindingRegistry extends TheiaKeybindingRegistry { + + // https://github.com/eclipse-theia/theia/issues/8209 + unregisterKeybinding(key: string): void; + unregisterKeybinding(keybinding: Keybinding): void; + unregisterKeybinding(command: Command): void; + unregisterKeybinding(arg: string | Keybinding | Command): void { + const keymap = this.keymaps[KeybindingScope.DEFAULT]; + const filter = Command.is(arg) + ? ({ command }: Keybinding) => command === arg.id + : ({ keybinding }: Keybinding) => Keybinding.is(arg) + ? keybinding === arg.keybinding + : keybinding === arg; + for (const binding of keymap.filter(filter)) { + const idx = keymap.indexOf(binding); + if (idx !== -1) { + keymap.splice(idx, 1); + } + } + } + +} diff --git a/arduino-ide-extension/src/browser/shell/arduino-shell-layout-restorer.ts b/arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts similarity index 83% rename from arduino-ide-extension/src/browser/shell/arduino-shell-layout-restorer.ts rename to arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts index 8f2fed01..cd6c1825 100644 --- a/arduino-ide-extension/src/browser/shell/arduino-shell-layout-restorer.ts +++ b/arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts @@ -1,9 +1,9 @@ import { injectable } from 'inversify'; import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { ShellLayoutRestorer } from '@theia/core/lib/browser/shell/shell-layout-restorer'; +import { ShellLayoutRestorer as TheiaShellLayoutRestorer } from '@theia/core/lib/browser/shell/shell-layout-restorer'; @injectable() -export class ArduinoShellLayoutRestorer extends ShellLayoutRestorer { +export class ShellLayoutRestorer extends TheiaShellLayoutRestorer { // Workaround for https://github.com/eclipse-theia/theia/issues/6579. async storeLayoutAsync(app: FrontendApplication): Promise { diff --git a/arduino-ide-extension/src/browser/shell/arduino-tab-bar-decorator.ts b/arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts similarity index 81% rename from arduino-ide-extension/src/browser/shell/arduino-tab-bar-decorator.ts rename to arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts index ee171cbf..e82a5f81 100644 --- a/arduino-ide-extension/src/browser/shell/arduino-tab-bar-decorator.ts +++ b/arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts @@ -3,12 +3,12 @@ import URI from '@theia/core/lib/common/uri'; import { Title, Widget } from '@phosphor/widgets'; import { ILogger } from '@theia/core'; import { WidgetDecoration } from '@theia/core/lib/browser/widget-decoration'; -import { TabBarDecoratorService } from '@theia/core/lib/browser/shell/tab-bar-decorator'; -import { ConfigService } from '../../common/protocol/config-service'; +import { TabBarDecoratorService as TheiaTabBarDecoratorService } from '@theia/core/lib/browser/shell/tab-bar-decorator'; +import { ConfigService } from '../../../common/protocol/config-service'; import { EditorWidget } from '@theia/editor/lib/browser'; @injectable() -export class ArduinoTabBarDecoratorService extends TabBarDecoratorService { +export class TabBarDecoratorService extends TheiaTabBarDecoratorService { @inject(ConfigService) protected readonly configService: ConfigService; @@ -16,7 +16,6 @@ export class ArduinoTabBarDecoratorService extends TabBarDecoratorService { @inject(ILogger) protected readonly logger: ILogger; - protected dataDirUri: URI | undefined; @postConstruct() diff --git a/arduino-ide-extension/src/browser/customization/arduino-editor-contribution.ts b/arduino-ide-extension/src/browser/theia/editor/editor-contribution.ts similarity index 73% rename from arduino-ide-extension/src/browser/customization/arduino-editor-contribution.ts rename to arduino-ide-extension/src/browser/theia/editor/editor-contribution.ts index 25f64e6a..e92c4c25 100644 --- a/arduino-ide-extension/src/browser/customization/arduino-editor-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/editor/editor-contribution.ts @@ -1,8 +1,10 @@ -import { EditorContribution } from '@theia/editor/lib/browser/editor-contribution'; +import { injectable } from 'inversify'; +import { EditorContribution as TheiaEditorContribution } from '@theia/editor/lib/browser/editor-contribution'; import { TextEditor } from '@theia/editor/lib/browser'; import { StatusBarAlignment } from '@theia/core/lib/browser'; -export class ArduinoEditorContribution extends EditorContribution { +@injectable() +export class EditorContribution extends TheiaEditorContribution { protected updateLanguageStatus(editor: TextEditor | undefined): void { } diff --git a/arduino-ide-extension/src/browser/editor/arduino-editor-manager.ts b/arduino-ide-extension/src/browser/theia/editor/editor-manager.ts similarity index 83% rename from arduino-ide-extension/src/browser/editor/arduino-editor-manager.ts rename to arduino-ide-extension/src/browser/theia/editor/editor-manager.ts index 30c33932..1681943f 100644 --- a/arduino-ide-extension/src/browser/editor/arduino-editor-manager.ts +++ b/arduino-ide-extension/src/browser/theia/editor/editor-manager.ts @@ -1,12 +1,12 @@ import { inject, injectable } from 'inversify'; import URI from '@theia/core/lib/common/uri'; -import { EditorManager, EditorOpenerOptions } from '@theia/editor/lib/browser/editor-manager'; -import { ConfigService } from '../../common/protocol/config-service'; +import { EditorManager as TheiaEditorManager, EditorOpenerOptions } from '@theia/editor/lib/browser/editor-manager'; +import { ConfigService } from '../../../common/protocol/config-service'; import { EditorWidget } from '@theia/editor/lib/browser'; import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor'; @injectable() -export class ArduinoEditorManager extends EditorManager { +export class EditorManager extends TheiaEditorManager { @inject(ConfigService) protected readonly configService: ConfigService; diff --git a/arduino-ide-extension/src/browser/customization/arduino-problem-contribution.ts b/arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts similarity index 80% rename from arduino-ide-extension/src/browser/customization/arduino-problem-contribution.ts rename to arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts index 9606dd1e..94186640 100644 --- a/arduino-ide-extension/src/browser/customization/arduino-problem-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts @@ -2,11 +2,11 @@ import { inject, injectable } from 'inversify'; import { KeybindingRegistry } from '@theia/core/lib/browser'; import { ProblemStat } from '@theia/markers/lib/browser/problem/problem-manager'; import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution'; -import { EditorMode } from '../editor-mode'; +import { ProblemContribution as TheiaProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution'; +import { EditorMode } from '../../editor-mode'; @injectable() -export class ArduinoProblemContribution extends ProblemContribution { +export class ProblemContribution extends TheiaProblemContribution { @inject(EditorMode) protected readonly editorMode: EditorMode; diff --git a/arduino-ide-extension/src/browser/markers/arduino-problem-manager.ts b/arduino-ide-extension/src/browser/theia/markers/problem-manager.ts similarity index 80% rename from arduino-ide-extension/src/browser/markers/arduino-problem-manager.ts rename to arduino-ide-extension/src/browser/theia/markers/problem-manager.ts index a15535b1..105c6d1a 100644 --- a/arduino-ide-extension/src/browser/markers/arduino-problem-manager.ts +++ b/arduino-ide-extension/src/browser/theia/markers/problem-manager.ts @@ -3,11 +3,11 @@ import { Diagnostic } from 'vscode-languageserver-types'; import URI from '@theia/core/lib/common/uri'; import { ILogger } from '@theia/core'; import { Marker } from '@theia/markers/lib/common/marker'; -import { ProblemManager } from '@theia/markers/lib/browser/problem/problem-manager'; -import { ConfigService } from '../../common/protocol/config-service'; +import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser/problem/problem-manager'; +import { ConfigService } from '../../../common/protocol/config-service'; @injectable() -export class ArduinoProblemManager extends ProblemManager { +export class ProblemManager extends TheiaProblemManager { @inject(ConfigService) protected readonly configService: ConfigService; diff --git a/arduino-ide-extension/src/browser/theia/monaco/comparers.ts b/arduino-ide-extension/src/browser/theia/monaco/comparers.ts new file mode 100644 index 00000000..25c893ce --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/monaco/comparers.ts @@ -0,0 +1,368 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Copied from https://github.com/microsoft/vscode/blob/724c307bf35646ac549a8533a255c51b63fea5c7/src/vs/base/common/comparers.ts +// We cannot customize the monaco loader for Theia: https://github.com/eclipse-theia/theia/issues/8220 + +import { isWindows } from '@theia/core/lib/common/os'; + +const sep = (isWindows ? '\\' : '/'); +interface IDisposable { + dispose(): void; +} +interface IdleDeadline { + readonly didTimeout: boolean; + timeRemaining(): number; +} +let runWhenIdle: (callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable; +declare function requestIdleCallback(callback: (args: IdleDeadline) => void, options?: { timeout: number }): number; +declare function cancelIdleCallback(handle: number): void; + +(function () { + if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') { + const dummyIdle: IdleDeadline = Object.freeze({ + didTimeout: true, + timeRemaining() { return 15; } + }); + runWhenIdle = (runner) => { + const handle = setTimeout(() => runner(dummyIdle)); + let disposed = false; + return { + dispose() { + if (disposed) { + return; + } + disposed = true; + clearTimeout(handle); + } + }; + }; + } else { + runWhenIdle = (runner, timeout?) => { + const handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); + let disposed = false; + return { + dispose() { + if (disposed) { + return; + } + disposed = true; + cancelIdleCallback(handle); + } + }; + }; + } +})(); + +/** + * An implementation of the "idle-until-urgent"-strategy as introduced + * here: https://philipwalton.com/articles/idle-until-urgent/ + */ +class IdleValue { + + private readonly _executor: () => void; + private readonly _handle: IDisposable; + + private _didRun: boolean = false; + private _value?: T; + private _error: any; + + constructor(executor: () => T) { + this._executor = () => { + try { + this._value = executor(); + } catch (err) { + this._error = err; + } finally { + this._didRun = true; + } + }; + this._handle = runWhenIdle(() => this._executor()); + } + + dispose(): void { + this._handle.dispose(); + } + + get value(): T { + if (!this._didRun) { + this._handle.dispose(); + this._executor(); + } + if (this._error) { + throw this._error; + } + return this._value!; + } +} + +// When comparing large numbers of strings, such as in sorting large arrays, is better for +// performance to create an Intl.Collator object and use the function provided by its compare +// property than it is to use String.prototype.localeCompare() + +// A collator with numeric sorting enabled, and no sensitivity to case or to accents +const intlFileNameCollatorBaseNumeric: IdleValue<{ collator: Intl.Collator, collatorIsNumeric: boolean }> = new IdleValue(() => { + const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); + return { + collator: collator, + collatorIsNumeric: collator.resolvedOptions().numeric + }; +}); + +// A collator with numeric sorting enabled. +const intlFileNameCollatorNumeric: IdleValue<{ collator: Intl.Collator }> = new IdleValue(() => { + const collator = new Intl.Collator(undefined, { numeric: true }); + return { + collator: collator + }; +}); + +// A collator with numeric sorting enabled, and sensitivity to accents and diacritics but not case. +const intlFileNameCollatorNumericCaseInsenstive: IdleValue<{ collator: Intl.Collator }> = new IdleValue(() => { + const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'accent' }); + return { + collator: collator + }; +}); + +export function compareFileNames(one: string | null, other: string | null, caseSensitive = false): number { + const a = one || ''; + const b = other || ''; + const result = intlFileNameCollatorBaseNumeric.value.collator.compare(a, b); + + // Using the numeric option in the collator will + // make compare(`foo1`, `foo01`) === 0. We must disambiguate. + if (intlFileNameCollatorBaseNumeric.value.collatorIsNumeric && result === 0 && a !== b) { + return a < b ? -1 : 1; + } + + return result; +} + +/** Compares filenames by name then extension, sorting numbers numerically instead of alphabetically. */ +export function compareFileNamesNumeric(one: string | null, other: string | null): number { + const [oneName, oneExtension] = extractNameAndExtension(one, true); + const [otherName, otherExtension] = extractNameAndExtension(other, true); + const collatorNumeric = intlFileNameCollatorNumeric.value.collator; + const collatorNumericCaseInsensitive = intlFileNameCollatorNumericCaseInsenstive.value.collator; + let result; + + // Check for name differences, comparing numbers numerically instead of alphabetically. + result = compareAndDisambiguateByLength(collatorNumeric, oneName, otherName); + if (result !== 0) { + return result; + } + + // Check for case insensitive extension differences, comparing numbers numerically instead of alphabetically. + result = compareAndDisambiguateByLength(collatorNumericCaseInsensitive, oneExtension, otherExtension); + if (result !== 0) { + return result; + } + + // Disambiguate the extension case if needed. + if (oneExtension !== otherExtension) { + return collatorNumeric.compare(oneExtension, otherExtension); + } + + return 0; +} + +const FileNameMatch = /^(.*?)(\.([^.]*))?$/; + +export function noIntlCompareFileNames(one: string | null, other: string | null, caseSensitive = false): number { + if (!caseSensitive) { + one = one && one.toLowerCase(); + other = other && other.toLowerCase(); + } + + const [oneName, oneExtension] = extractNameAndExtension(one); + const [otherName, otherExtension] = extractNameAndExtension(other); + + if (oneName !== otherName) { + return oneName < otherName ? -1 : 1; + } + + if (oneExtension === otherExtension) { + return 0; + } + + return oneExtension < otherExtension ? -1 : 1; +} + +export function compareFileExtensions(one: string | null, other: string | null): number { + const [oneName, oneExtension] = extractNameAndExtension(one); + const [otherName, otherExtension] = extractNameAndExtension(other); + + let result = intlFileNameCollatorBaseNumeric.value.collator.compare(oneExtension, otherExtension); + + if (result === 0) { + // Using the numeric option in the collator will + // make compare(`foo1`, `foo01`) === 0. We must disambiguate. + if (intlFileNameCollatorBaseNumeric.value.collatorIsNumeric && oneExtension !== otherExtension) { + return oneExtension < otherExtension ? -1 : 1; + } + + // Extensions are equal, compare filenames + result = intlFileNameCollatorBaseNumeric.value.collator.compare(oneName, otherName); + + if (intlFileNameCollatorBaseNumeric.value.collatorIsNumeric && result === 0 && oneName !== otherName) { + return oneName < otherName ? -1 : 1; + } + } + + return result; +} + +/** Compares filenames by extenson, then by name. Sorts numbers numerically, not alphabetically. */ +export function compareFileExtensionsNumeric(one: string | null, other: string | null): number { + const [oneName, oneExtension] = extractNameAndExtension(one, true); + const [otherName, otherExtension] = extractNameAndExtension(other, true); + const collatorNumeric = intlFileNameCollatorNumeric.value.collator; + const collatorNumericCaseInsensitive = intlFileNameCollatorNumericCaseInsenstive.value.collator; + let result; + + // Check for extension differences, ignoring differences in case and comparing numbers numerically. + result = compareAndDisambiguateByLength(collatorNumericCaseInsensitive, oneExtension, otherExtension); + if (result !== 0) { + return result; + } + + // Compare names. + result = compareAndDisambiguateByLength(collatorNumeric, oneName, otherName); + if (result !== 0) { + return result; + } + + // Disambiguate extension case if needed. + if (oneExtension !== otherExtension) { + return collatorNumeric.compare(oneExtension, otherExtension); + } + + return 0; +} + +/** Extracts the name and extension from a full filename, with optional special handling for dotfiles */ +function extractNameAndExtension(str?: string | null, dotfilesAsNames = false): [string, string] { + const match = str ? FileNameMatch.exec(str) as Array : ([] as Array); + + let result: [string, string] = [(match && match[1]) || '', (match && match[3]) || '']; + + // if the dotfilesAsNames option is selected, treat an empty filename with an extension, + // or a filename that starts with a dot, as a dotfile name + if (dotfilesAsNames && (!result[0] && result[1] || result[0] && result[0].charAt(0) === '.')) { + result = [result[0] + '.' + result[1], '']; + } + + return result; +} + +function compareAndDisambiguateByLength(collator: Intl.Collator, one: string, other: string) { + // Check for differences + let result = collator.compare(one, other); + if (result !== 0) { + return result; + } + + // In a numeric comparison, `foo1` and `foo01` will compare as equivalent. + // Disambiguate by sorting the shorter string first. + if (one.length !== other.length) { + return one.length < other.length ? -1 : 1; + } + + return 0; +} + +function comparePathComponents(one: string, other: string, caseSensitive = false): number { + if (!caseSensitive) { + one = one && one.toLowerCase(); + other = other && other.toLowerCase(); + } + + if (one === other) { + return 0; + } + + return one < other ? -1 : 1; +} + +export function comparePaths(one: string, other: string, caseSensitive = false): number { + const oneParts = one.split(sep); + const otherParts = other.split(sep); + + const lastOne = oneParts.length - 1; + const lastOther = otherParts.length - 1; + let endOne: boolean, endOther: boolean; + + for (let i = 0; ; i++) { + endOne = lastOne === i; + endOther = lastOther === i; + + if (endOne && endOther) { + return compareFileNames(oneParts[i], otherParts[i], caseSensitive); + } else if (endOne) { + return -1; + } else if (endOther) { + return 1; + } + + const result = comparePathComponents(oneParts[i], otherParts[i], caseSensitive); + + if (result !== 0) { + return result; + } + } +} + +export function compareAnything(one: string, other: string, lookFor: string): number { + const elementAName = one.toLowerCase(); + const elementBName = other.toLowerCase(); + + // Sort prefix matches over non prefix matches + const prefixCompare = compareByPrefix(one, other, lookFor); + if (prefixCompare) { + return prefixCompare; + } + + // Sort suffix matches over non suffix matches + const elementASuffixMatch = elementAName.endsWith(lookFor); + const elementBSuffixMatch = elementBName.endsWith(lookFor); + if (elementASuffixMatch !== elementBSuffixMatch) { + return elementASuffixMatch ? -1 : 1; + } + + // Understand file names + const r = compareFileNames(elementAName, elementBName); + if (r !== 0) { + return r; + } + + // Compare by name + return elementAName.localeCompare(elementBName); +} + +export function compareByPrefix(one: string, other: string, lookFor: string): number { + const elementAName = one.toLowerCase(); + const elementBName = other.toLowerCase(); + + // Sort prefix matches over non prefix matches + const elementAPrefixMatch = elementAName.startsWith(lookFor); + const elementBPrefixMatch = elementBName.startsWith(lookFor); + if (elementAPrefixMatch !== elementBPrefixMatch) { + return elementAPrefixMatch ? -1 : 1; + } + + // Same prefix: Sort shorter matches to the top to have those on top that match more precisely + // tslint:disable-next-line: one-line + else if (elementAPrefixMatch && elementBPrefixMatch) { + if (elementAName.length < elementBName.length) { + return -1; + } + + if (elementAName.length > elementBName.length) { + return 1; + } + } + + return 0; +} diff --git a/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts b/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts new file mode 100644 index 00000000..f673ed45 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts @@ -0,0 +1,13 @@ +import { injectable } from 'inversify'; +import { MonacoStatusBarContribution as TheiaMonacoStatusBarContribution } from '@theia/monaco/lib/browser/monaco-status-bar-contribution'; + +@injectable() +export class MonacoStatusBarContribution extends TheiaMonacoStatusBarContribution { + + protected setConfigTabSizeWidget() { + } + + protected setLineEndingWidget() { + } + +} diff --git a/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts b/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts new file mode 100644 index 00000000..58226058 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts @@ -0,0 +1,28 @@ +import { injectable, inject } from 'inversify'; +import { WorkspaceCommands } from '@theia/workspace/lib/browser/workspace-commands'; +import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; +import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; +import { FileNavigatorContribution as TheiaFileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; +import { EditorMode } from '../../editor-mode'; + +@injectable() +export class FileNavigatorContribution extends TheiaFileNavigatorContribution { + + @inject(EditorMode) + protected readonly editorMode: EditorMode; + + async initializeLayout(app: FrontendApplication): Promise { + if (this.editorMode.proMode) { + return super.initializeLayout(app); + } + } + + registerKeybindings(registry: KeybindingRegistry): void { + super.registerKeybindings(registry); + [ + WorkspaceCommands.FILE_RENAME, + WorkspaceCommands.FILE_DELETE + ].forEach(registry.unregisterKeybinding.bind(registry)); + } + +} diff --git a/arduino-ide-extension/src/browser/customization/arduino-outline-contribution.ts b/arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts similarity index 60% rename from arduino-ide-extension/src/browser/customization/arduino-outline-contribution.ts rename to arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts index 20081a5b..2bc7fd3a 100644 --- a/arduino-ide-extension/src/browser/customization/arduino-outline-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts @@ -1,10 +1,10 @@ import { injectable, inject } from 'inversify'; import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { OutlineViewContribution } from '@theia/outline-view/lib/browser/outline-view-contribution'; -import { EditorMode } from '../editor-mode'; +import { OutlineViewContribution as TheiaOutlineViewContribution } from '@theia/outline-view/lib/browser/outline-view-contribution'; +import { EditorMode } from '../../editor-mode'; @injectable() -export class ArduinoOutlineViewContribution extends OutlineViewContribution { +export class OutlineViewContribution extends TheiaOutlineViewContribution { @inject(EditorMode) protected readonly editorMode: EditorMode; diff --git a/arduino-ide-extension/src/browser/theia/preferences/preference-contribution.ts b/arduino-ide-extension/src/browser/theia/preferences/preference-contribution.ts new file mode 100644 index 00000000..9f1e0c6b --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/preferences/preference-contribution.ts @@ -0,0 +1,27 @@ +import { injectable } from 'inversify'; +import { isOSX } from '@theia/core/lib/common/os'; +import { MenuModelRegistry } from '@theia/core/lib/common/menu'; +import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; +import { CommonCommands, CommonMenus } from '@theia/core/lib/browser'; +import { PreferencesContribution as TheiaPreferencesContribution } from '@theia/preferences/lib/browser/preference-contribution'; + +@injectable() +export class PreferencesContribution extends TheiaPreferencesContribution { + + registerMenus(registry: MenuModelRegistry): void { + super.registerMenus(registry); + if (isOSX) { + // The settings group: preferences, CLI config is not part of the `File` menu on macOS. + registry.unregisterMenuAction(CommonCommands.OPEN_PREFERENCES.id, CommonMenus.FILE_SETTINGS_SUBMENU_OPEN); + } + } + + registerKeybindings(registry: KeybindingRegistry): void { + // https://github.com/eclipse-theia/theia/issues/8202 + registry.registerKeybinding({ + command: CommonCommands.OPEN_PREFERENCES.id, + keybinding: 'CtrlCmd+,', + }); + } + +} diff --git a/arduino-ide-extension/src/browser/customization/arduino-scm-contribution.ts b/arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts similarity index 72% rename from arduino-ide-extension/src/browser/customization/arduino-scm-contribution.ts rename to arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts index f299c2c6..30758d16 100644 --- a/arduino-ide-extension/src/browser/customization/arduino-scm-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts @@ -1,10 +1,10 @@ import { inject, injectable } from 'inversify'; -import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution'; +import { ScmContribution as TheiaScmContribution } from '@theia/scm/lib/browser/scm-contribution'; import { StatusBarEntry } from '@theia/core/lib/browser/status-bar/status-bar'; -import { EditorMode } from '../editor-mode'; +import { EditorMode } from '../../editor-mode'; @injectable() -export class ArduinoScmContribution extends ScmContribution { +export class ScmContribution extends TheiaScmContribution { @inject(EditorMode) protected readonly editorMode: EditorMode; diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts new file mode 100644 index 00000000..00738e5e --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts @@ -0,0 +1,24 @@ +import { inject, injectable } from 'inversify'; +import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; +import { SearchInWorkspaceFrontendContribution as TheiaSearchInWorkspaceFrontendContribution, SearchInWorkspaceCommands } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; +import { EditorMode } from '../../editor-mode'; +import { MenuModelRegistry } from '@theia/core'; + +@injectable() +export class SearchInWorkspaceFrontendContribution extends TheiaSearchInWorkspaceFrontendContribution { + + @inject(EditorMode) + protected readonly editorMode: EditorMode; + + async initializeLayout(app: FrontendApplication): Promise { + if (this.editorMode.proMode) { + return super.initializeLayout(app); + } + } + + registerMenus(registry: MenuModelRegistry): void { + super.registerMenus(registry); + registry.unregisterMenuAction(SearchInWorkspaceCommands.OPEN_SIW_WIDGET); + } + +} diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts new file mode 100644 index 00000000..b1409761 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts @@ -0,0 +1,48 @@ +import { injectable } from 'inversify'; +import { CommandRegistry } from '@theia/core/lib/common/command'; +import { MenuModelRegistry } from '@theia/core/lib/common/menu'; +import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; +import { WorkspaceCommands, FileMenuContribution } from '@theia/workspace/lib/browser/workspace-commands'; +import { WorkspaceFrontendContribution as TheiaWorkspaceFrontendContribution } from '@theia/workspace/lib/browser/workspace-frontend-contribution'; + +@injectable() +export class WorkspaceFrontendContribution extends TheiaWorkspaceFrontendContribution { + + registerCommands(registry: CommandRegistry): void { + super.registerCommands(registry); + // TODO: instead of blacklisting commands to remove, it would be more robust to whitelist the ones we want to keep + const commands = new Set(registry.commands); + [ + WorkspaceCommands.OPEN, + WorkspaceCommands.OPEN_FILE, + WorkspaceCommands.OPEN_FOLDER, + WorkspaceCommands.OPEN_WORKSPACE, + WorkspaceCommands.OPEN_RECENT_WORKSPACE, + WorkspaceCommands.SAVE_WORKSPACE_AS, + WorkspaceCommands.SAVE_AS, + WorkspaceCommands.CLOSE + ].filter(commands.has.bind(commands)).forEach(registry.unregisterCommand.bind(registry)); + } + + registerMenus(_: MenuModelRegistry): void { + } + + registerKeybindings(registry: KeybindingRegistry): void { + super.registerKeybindings(registry); + [ + WorkspaceCommands.NEW_FILE, + WorkspaceCommands.FILE_RENAME, + WorkspaceCommands.FILE_DELETE + ].map(({ id }) => id).forEach(registry.unregisterKeybinding.bind(registry)); + } + +} + +@injectable() +export class ArduinoFileMenuContribution extends FileMenuContribution { + + registerMenus(_: MenuModelRegistry): void { + // NOOP + } + +} diff --git a/arduino-ide-extension/src/browser/arduino-workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts similarity index 51% rename from arduino-ide-extension/src/browser/arduino-workspace-service.ts rename to arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 1c2881b4..cce01a80 100644 --- a/arduino-ide-extension/src/browser/arduino-workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -1,14 +1,19 @@ import { injectable, inject } from 'inversify'; -import { MessageService } from '@theia/core'; -import { LabelProvider } from '@theia/core/lib/browser'; -import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; -import { ConfigService } from '../common/protocol/config-service'; -import { SketchesService } from '../common/protocol/sketches-service'; -import { ArduinoWorkspaceRootResolver } from './arduino-workspace-resolver'; -import { EditorMode } from './editor-mode'; +import URI from '@theia/core/lib/common/uri'; +import { EditorWidget } from '@theia/editor/lib/browser'; +import { LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { MessageService } from '@theia/core/lib/common/message-service'; +import { ApplicationServer } from '@theia/core/lib/common/application-protocol'; +import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; +import { FocusTracker, Widget } from '@theia/core/lib/browser'; +import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; +import { EditorMode } from '../../editor-mode'; +import { ConfigService } from '../../../common/protocol/config-service'; +import { SketchesService } from '../../../common/protocol/sketches-service'; +import { ArduinoWorkspaceRootResolver } from '../../arduino-workspace-resolver'; @injectable() -export class ArduinoWorkspaceService extends WorkspaceService { +export class WorkspaceService extends TheiaWorkspaceService { @inject(SketchesService) protected readonly sketchService: SketchesService; @@ -25,7 +30,19 @@ export class ArduinoWorkspaceService extends WorkspaceService { @inject(MessageService) protected readonly messageService: MessageService; + @inject(ApplicationServer) + protected readonly applicationServer: ApplicationServer; + private workspaceUri?: Promise; + private version?: string + + async onStart(application: FrontendApplication): Promise { + const info = await this.applicationServer.getApplicationInfo(); + this.version = info?.version; + application.shell.onDidChangeCurrentWidget(this.onCurrentWidgetChange.bind(this)); + const newValue = application.shell.currentWidget ? application.shell.currentWidget : null; + this.onCurrentWidgetChange({ newValue, oldValue: null }); + } protected getDefaultWorkspaceUri(): Promise { if (this.workspaceUri) { @@ -47,9 +64,7 @@ export class ArduinoWorkspaceService extends WorkspaceService { await this.server.setMostRecentlyUsedWorkspace(uri); return toOpen.uri; } - const { sketchDirUri } = (await this.configService.getConfiguration()); - this.logger.info(`No valid workspace URI found. Creating new sketch in ${sketchDirUri}`) - return (await this.sketchService.createNewSketch(sketchDirUri)).uri; + return (await this.sketchService.createNewSketch()).uri; } catch (err) { this.logger.fatal(`Failed to determine the sketch directory: ${err}`) this.messageService.error( @@ -76,4 +91,32 @@ export class ArduinoWorkspaceService extends WorkspaceService { return sketchFolder; } + protected onCurrentWidgetChange({ newValue }: FocusTracker.IChangedArgs): void { + if (newValue instanceof EditorWidget) { + const { uri } = newValue.editor; + if (uri.toString().endsWith('.ino')) { + this.updateTitle(); + } else { + const title = this.workspaceTitle; + const fileName = this.labelProvider.getName(uri); + document.title = this.formatTitle(title ? `${title} - ${fileName}` : fileName); + } + } else { + this.updateTitle(); + } + } + + protected formatTitle(title?: string): string { + const version = this.version ? ` ${this.version}` : ''; + const name = `${this.applicationName} ${version}`; + return title ? `${title} | ${name}` : name; + } + + protected get workspaceTitle(): string | undefined { + if (this.workspace) { + const uri = new URI(this.workspace.uri); + return this.labelProvider.getName(uri); + } + } + } diff --git a/arduino-ide-extension/src/browser/tool-output/client-service-impl.ts b/arduino-ide-extension/src/browser/tool-output/client-service-impl.ts index 85140d97..d4dfc26c 100644 --- a/arduino-ide-extension/src/browser/tool-output/client-service-impl.ts +++ b/arduino-ide-extension/src/browser/tool-output/client-service-impl.ts @@ -1,7 +1,7 @@ -import { ToolOutputServiceClient } from "../../common/protocol/tool-output-service"; -import { injectable, inject } from "inversify"; -import { OutputChannelManager } from "@theia/output/lib/common/output-channel"; -import { OutputContribution } from "@theia/output/lib/browser/output-contribution"; +import { ToolOutputServiceClient } from '../../common/protocol/tool-output-service'; +import { injectable, inject } from 'inversify'; +import { OutputChannelManager } from '@theia/output/lib/common/output-channel'; +import { OutputContribution } from '@theia/output/lib/browser/output-contribution'; @injectable() export class ToolOutputServiceClientImpl implements ToolOutputServiceClient { @@ -13,9 +13,9 @@ export class ToolOutputServiceClientImpl implements ToolOutputServiceClient { protected readonly outputContribution: OutputContribution; onNewOutput(tool: string, chunk: string): void { - this.outputContribution.openView({ reveal: true }).then(() => { + this.outputContribution.openView().then(() => { const channel = this.outputChannelManager.getChannel(`Arduino: ${tool}`); - channel.setVisibility(true); + channel.show(); channel.append(chunk); }); } diff --git a/arduino-ide-extension/src/browser/components/arduino-select.tsx b/arduino-ide-extension/src/browser/widgets/arduino-select.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/arduino-select.tsx rename to arduino-ide-extension/src/browser/widgets/arduino-select.tsx diff --git a/arduino-ide-extension/src/browser/components/component-list/component-list-item.tsx b/arduino-ide-extension/src/browser/widgets/component-list/component-list-item.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/component-list-item.tsx rename to arduino-ide-extension/src/browser/widgets/component-list/component-list-item.tsx diff --git a/arduino-ide-extension/src/browser/components/component-list/component-list.tsx b/arduino-ide-extension/src/browser/widgets/component-list/component-list.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/component-list.tsx rename to arduino-ide-extension/src/browser/widgets/component-list/component-list.tsx diff --git a/arduino-ide-extension/src/browser/components/component-list/filterable-list-container.tsx b/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/filterable-list-container.tsx rename to arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx diff --git a/arduino-ide-extension/src/browser/components/component-list/list-item-renderer.tsx b/arduino-ide-extension/src/browser/widgets/component-list/list-item-renderer.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/list-item-renderer.tsx rename to arduino-ide-extension/src/browser/widgets/component-list/list-item-renderer.tsx diff --git a/arduino-ide-extension/src/browser/components/component-list/list-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/list-widget-frontend-contribution.ts rename to arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts diff --git a/arduino-ide-extension/src/browser/components/component-list/list-widget.tsx b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/list-widget.tsx rename to arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx diff --git a/arduino-ide-extension/src/browser/components/component-list/search-bar.tsx b/arduino-ide-extension/src/browser/widgets/component-list/search-bar.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/component-list/search-bar.tsx rename to arduino-ide-extension/src/browser/widgets/component-list/search-bar.tsx diff --git a/arduino-ide-extension/src/browser/components/progress-dialog.tsx b/arduino-ide-extension/src/browser/widgets/progress-dialog.tsx similarity index 100% rename from arduino-ide-extension/src/browser/components/progress-dialog.tsx rename to arduino-ide-extension/src/browser/widgets/progress-dialog.tsx diff --git a/arduino-ide-extension/src/browser/menu/main-menu-manager.ts b/arduino-ide-extension/src/common/main-menu-manager.ts similarity index 100% rename from arduino-ide-extension/src/browser/menu/main-menu-manager.ts rename to arduino-ide-extension/src/common/main-menu-manager.ts diff --git a/arduino-ide-extension/src/common/protocol/boards-service.ts b/arduino-ide-extension/src/common/protocol/boards-service.ts index a98094c7..0abbe29f 100644 --- a/arduino-ide-extension/src/common/protocol/boards-service.ts +++ b/arduino-ide-extension/src/common/protocol/boards-service.ts @@ -68,7 +68,9 @@ export interface BoardsService extends Installable, Searchable; getBoardPackage(options: { id: string }): Promise; getContainerBoardPackage(options: { fqbn: string }): Promise; - searchBoards(options: { query?: string }): Promise>; + // The CLI cannot do fuzzy search. This method provides all boards and we do the fuzzy search (with monaco) on the frontend. + // https://github.com/arduino/arduino-cli/issues/629 + allBoards(options: {}): Promise>; } export interface Port { @@ -94,6 +96,10 @@ export namespace Port { } } + export function is(arg: any): arg is Port { + return !!arg && 'address' in arg && typeof arg['address'] === 'string' && 'protocol' in arg && typeof arg['protocol'] === 'string'; + } + export function toString(port: Port, options: { useLabel: boolean } = { useLabel: false }): string { if (options.useLabel && port.label) { return `${port.address} ${port.label}` @@ -199,6 +205,7 @@ export interface BoardDetails { readonly fqbn: string; readonly requiredTools: Tool[]; readonly configOptions: ConfigOption[]; + readonly programmers: Programmer[]; } export interface Tool { @@ -223,18 +230,8 @@ export namespace ConfigOption { * Appends the configuration options to the `fqbn` argument. * Throws an error if the `fqbn` does not have the `segment(':'segment)*` format. * The provided output format is always segment(':'segment)*(':'option'='value(','option'='value)*)? - * Validation can be disabled with the `{ validation: false }` option. */ - export function decorate(fqbn: string, configOptions: ConfigOption[], { validate } = { validate: true }): string { - if (validate) { - if (!isValidFqbn(fqbn)) { - throw new ConfigOptionError(`${fqbn} is not a valid FQBN.`); - } - if (isValidFqbnWithOptions(fqbn)) { - throw new ConfigOptionError(`${fqbn} is already decorated with the configuration options.`); - } - } - + export function decorate(fqbn: string, configOptions: ConfigOption[]): string { if (!configOptions.length) { return fqbn; } @@ -256,14 +253,6 @@ export namespace ConfigOption { return `${fqbn}:${options}`; } - export function isValidFqbn(fqbn: string): boolean { - return /^\w+(:\w+)*$/.test(fqbn); - } - - export function isValidFqbnWithOptions(fqbn: string): boolean { - return /^\w+(:\w+)*(:\w+=\w+(,\w+=\w+)*)$/.test(fqbn); - } - export class ConfigOptionError extends Error { constructor(message: string) { super(message); @@ -281,6 +270,25 @@ export interface ConfigValue { readonly selected: boolean; } +export interface Programmer { + readonly name: string; + readonly platform: string; + readonly id: string; +} +export namespace Programmer { + + export function equals(left: Programmer | undefined, right: Programmer | undefined): boolean { + if (!left) { + return !right; + } + if (!right) { + return !left; + } + return left.id === right.id && left.name === right.name && left.platform === right.platform; + } + +} + export namespace Board { export function is(board: any): board is Board { @@ -351,5 +359,4 @@ export namespace Board { })); } - } diff --git a/arduino-ide-extension/src/common/protocol/core-service.ts b/arduino-ide-extension/src/common/protocol/core-service.ts index 97662cb9..a6baa0b4 100644 --- a/arduino-ide-extension/src/common/protocol/core-service.ts +++ b/arduino-ide-extension/src/common/protocol/core-service.ts @@ -1,4 +1,5 @@ import { JsonRpcServer } from '@theia/core/lib/common/messaging/proxy-factory'; +import { Programmer } from './boards-service'; export const CoreServiceClient = Symbol('CoreServiceClient'); export interface CoreServiceClient { @@ -19,6 +20,7 @@ export namespace CoreService { readonly sketchUri: string; readonly fqbn: string; readonly optimizeForDebug: boolean; + readonly programmer?: Programmer | undefined; } } diff --git a/arduino-ide-extension/src/common/protocol/filesystem-ext.ts b/arduino-ide-extension/src/common/protocol/filesystem-ext.ts new file mode 100644 index 00000000..6d8c0972 --- /dev/null +++ b/arduino-ide-extension/src/common/protocol/filesystem-ext.ts @@ -0,0 +1,5 @@ +export const FileSystemExtPath = '/services/file-system-ext'; +export const FileSystemExt = Symbol('FileSystemExt'); +export interface FileSystemExt { + getUri(fsPath: string): Promise; +} diff --git a/arduino-ide-extension/src/common/protocol/index.ts b/arduino-ide-extension/src/common/protocol/index.ts index 83c20492..306b3f9f 100644 --- a/arduino-ide-extension/src/common/protocol/index.ts +++ b/arduino-ide-extension/src/common/protocol/index.ts @@ -3,6 +3,7 @@ export * from './arduino-daemon'; export * from './boards-service'; export * from './config-service'; export * from './core-service'; +export * from './filesystem-ext'; export * from './installable'; export * from './library-service'; export * from './monitor-service'; diff --git a/arduino-ide-extension/src/common/protocol/sketches-service.ts b/arduino-ide-extension/src/common/protocol/sketches-service.ts index 8c883abf..9a092b1a 100644 --- a/arduino-ide-extension/src/common/protocol/sketches-service.ts +++ b/arduino-ide-extension/src/common/protocol/sketches-service.ts @@ -1,22 +1,49 @@ export const SketchesServicePath = '/services/sketches-service'; export const SketchesService = Symbol('SketchesService'); export interface SketchesService { + /** * Returns with the direct sketch folders from the location of the `fileStat`. * The sketches returns with inverse-chronological order, the first item is the most recent one. */ - getSketches(uri?: string): Promise - getSketchFiles(uri: string): Promise + getSketches(uri?: string): Promise; + + getSketchFiles(uri: string): Promise; + /** - * Creates a new sketch folder in the `parentUri` location. - * Normally, `parentUri` is the client's workspace root, or the default `sketchDirUri` from the CLI. - * Note, `parentUri` and `sketchDirUri` can be the same. + * Creates a new sketch folder in the temp location. */ - createNewSketch(parentUri: string): Promise - isSketchFolder(uri: string): Promise + createNewSketch(): Promise; + + isSketchFolder(uri: string): Promise; + + /** + * Sketches are created to the temp location by default and will be moved under `directories.user` on save. + * This method resolves to `true` if the `sketch` is still in the temp location. Otherwise, `false`. + */ + isTemp(sketch: Sketch): Promise; + + /** + * If `isTemp` is `true` for the `sketch`, you can call this method to move the sketch from the temp + * location to `directories.user`. Resolves with the URI of the sketch after the move. Rejects, when the sketch + * was not in the temp folder. This method always overrides. It's the callers responsibility to ask the user whether + * the files at the destination can be overwritten or not. + */ + copy(sketch: Sketch, options: { destinationUri: string }): Promise; + + /** + * Returns with the container sketch for the input `uri`. If the `uri` is not in a sketch folder, resolved `undefined`. + */ + getSketchFolder(uri: string): Promise; + } export interface Sketch { readonly name: string; - readonly uri: string -} \ No newline at end of file + readonly uri: string; +} +export namespace Sketch { + export function is(arg: any): arg is Sketch { + return !!arg && 'name' in arg && 'uri' in arg && typeof arg.name === 'string' && typeof arg.uri === 'string'; + } +} diff --git a/arduino-ide-extension/src/common/utils.ts b/arduino-ide-extension/src/common/utils.ts index 77dbaf54..7c438918 100644 --- a/arduino-ide-extension/src/common/utils.ts +++ b/arduino-ide-extension/src/common/utils.ts @@ -1 +1,5 @@ export const naturalCompare: (left: string, right: string) => number = require('string-natural-compare').caseInsensitive; + +export function notEmpty(arg: string | undefined | null): arg is string { + return !!arg; +} diff --git a/arduino-ide-extension/src/electron-browser/menu/electron-arduino-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/menu/electron-arduino-menu-contribution.ts deleted file mode 100644 index 251e89ec..00000000 --- a/arduino-ide-extension/src/electron-browser/menu/electron-arduino-menu-contribution.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { injectable } from 'inversify'; -import { ElectronMenuContribution } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution'; -import { MainMenuManager } from '../../browser/menu/main-menu-manager'; - -@injectable() -export class ElectronArduinoMenuContribution extends ElectronMenuContribution implements MainMenuManager { - - protected hideTopPanel(): void { - // NOOP - // We reuse the `div` for the Arduino toolbar. - } - - update(): void { - (this as any).setMenu(); - } - -} diff --git a/arduino-ide-extension/src/electron-browser/menu/electron-arduino-menu-module.ts b/arduino-ide-extension/src/electron-browser/menu/electron-arduino-menu-module.ts deleted file mode 100644 index 2849d103..00000000 --- a/arduino-ide-extension/src/electron-browser/menu/electron-arduino-menu-module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ContainerModule } from 'inversify'; -import { ElectronMenuContribution } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution' -import { ElectronArduinoMenuContribution } from './electron-arduino-menu-contribution'; -import { MainMenuManager } from '../../browser/menu/main-menu-manager'; - -export default new ContainerModule((bind, unbind, isBound, rebind) => { - bind(ElectronArduinoMenuContribution).toSelf().inSingletonScope(); - bind(MainMenuManager).toService(ElectronArduinoMenuContribution); - rebind(ElectronMenuContribution).to(ElectronArduinoMenuContribution); -}); diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts new file mode 100644 index 00000000..8d0ad110 --- /dev/null +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts @@ -0,0 +1,40 @@ +import { injectable } from 'inversify' +import { remote } from 'electron'; +import { Keybinding } from '@theia/core/lib/common/keybinding'; +import { ElectronMainMenuFactory as TheiaElectronMainMenuFactory } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory'; +import { ArduinoMenus } from '../../../browser/menu/arduino-menus'; + +@injectable() +export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { + + protected acceleratorFor(keybinding: Keybinding): string { + // TODO: https://github.com/eclipse-theia/theia/issues/8207 + return this.keybindingRegistry.resolveKeybinding(keybinding) + .map(binding => this.keybindingRegistry.acceleratorForKeyCode(binding, '+')) + .join('') + .replace('←', 'Left') + .replace('→', 'Right'); + } + + protected createOSXMenu(): Electron.MenuItemConstructorOptions { + const { submenu } = super.createOSXMenu(); + const label = 'Arduino Pro IDE'; + if (!!submenu && !(submenu instanceof remote.Menu)) { + const [about, , ...rest] = submenu; + const menuModel = this.menuProvider.getMenu(ArduinoMenus.FILE__SETTINGS_GROUP); + const settings = this.fillMenuTemplate([], menuModel); + return { + label, + submenu: [ + about, // TODO: we have two about dialogs! one from electron the other from Theia. + { type: 'separator' }, + ...settings, + { type: 'separator' }, + ...rest + ] + }; + } + return { label, submenu }; + } + +} diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts new file mode 100644 index 00000000..c201e761 --- /dev/null +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts @@ -0,0 +1,37 @@ +import { injectable } from 'inversify'; +import { CommandRegistry } from '@theia/core/lib/common/command'; +import { MenuModelRegistry } from '@theia/core/lib/common/menu'; +import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; +import { ElectronMenuContribution as TheiaElectronMenuContribution, ElectronCommands } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution'; +import { MainMenuManager } from '../../../common/main-menu-manager'; + +@injectable() +export class ElectronMenuContribution extends TheiaElectronMenuContribution implements MainMenuManager { + + protected hideTopPanel(): void { + // NOOP + // We reuse the `div` for the Arduino toolbar. + } + + update(): void { + (this as any).setMenu(); + } + + registerCommands(registry: CommandRegistry): void { + super.registerCommands(registry); + registry.unregisterCommand(ElectronCommands.CLOSE_WINDOW); + } + + registerMenus(registry: MenuModelRegistry): void { + super.registerMenus(registry); + registry.unregisterMenuAction(ElectronCommands.CLOSE_WINDOW); + } + + registerKeybindings(registry: KeybindingRegistry): void { + super.registerKeybindings(registry); + registry.unregisterKeybinding(ElectronCommands.CLOSE_WINDOW.id); + registry.unregisterKeybinding(ElectronCommands.ZOOM_IN.id); + registry.unregisterKeybinding(ElectronCommands.ZOOM_OUT.id); + } + +} diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts new file mode 100644 index 00000000..b39dee8c --- /dev/null +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts @@ -0,0 +1,14 @@ +import { ContainerModule } from 'inversify'; +import { ElectronMenuContribution as TheiaElectronMenuContribution } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution' +import { ElectronMenuContribution } from './electron-menu-contribution'; +import { MainMenuManager } from '../../../common/main-menu-manager'; +import { ElectronMainMenuFactory as TheiaElectronMainMenuFactory } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory'; +import { ElectronMainMenuFactory } from './electron-main-menu-factory'; + +export default new ContainerModule((bind, unbind, isBound, rebind) => { + bind(ElectronMenuContribution).toSelf().inSingletonScope(); + bind(MainMenuManager).toService(ElectronMenuContribution); + rebind(TheiaElectronMenuContribution).to(ElectronMenuContribution); + bind(ElectronMainMenuFactory).toSelf().inRequestScope(); + rebind(TheiaElectronMainMenuFactory).toService(ElectronMainMenuFactory); +}); diff --git a/arduino-ide-extension/src/node/arduino-daemon-impl.ts b/arduino-ide-extension/src/node/arduino-daemon-impl.ts index 791a2ec5..394d0412 100644 --- a/arduino-ide-extension/src/node/arduino-daemon-impl.ts +++ b/arduino-ide-extension/src/node/arduino-daemon-impl.ts @@ -166,9 +166,11 @@ export class ArduinoDaemonImpl implements ArduinoDaemon, BackendApplicationContr if (error) { ready.reject(error); } - if (message.includes('Daemon is listening on TCP port')) { - grpcServerIsReady = true; - ready.resolve(daemon); + for (const expected of ['Daemon is listening on TCP port', 'Daemon is now listening on 127.0.0.1']) { + if (message.includes(expected)) { + grpcServerIsReady = true; + ready.resolve(daemon); + } } } }); diff --git a/arduino-ide-extension/src/node/arduino-env-variables-server.ts b/arduino-ide-extension/src/node/arduino-env-variables-server.ts index 1976780a..2a0084e6 100644 --- a/arduino-ide-extension/src/node/arduino-env-variables-server.ts +++ b/arduino-ide-extension/src/node/arduino-env-variables-server.ts @@ -8,6 +8,6 @@ import { BackendApplicationConfigProvider } from '@theia/core/lib/node/backend-a @injectable() export class ArduinoEnvVariablesServer extends EnvVariablesServerImpl { - protected readonly configDirUri = FileUri.create(join(homedir(), BackendApplicationConfigProvider.get().configDirName)).toString(); + protected readonly configDirUri = Promise.resolve(FileUri.create(join(homedir(), BackendApplicationConfigProvider.get().configDirName)).toString()); } diff --git a/arduino-ide-extension/src/node/arduino-ide-backend-module.ts b/arduino-ide-extension/src/node/arduino-ide-backend-module.ts index a62daa12..22f1f052 100644 --- a/arduino-ide-extension/src/node/arduino-ide-backend-module.ts +++ b/arduino-ide-extension/src/node/arduino-ide-backend-module.ts @@ -33,6 +33,8 @@ import { HostedPluginReader } from '@theia/plugin-ext/lib/hosted/node/plugin-rea import { ConfigFileValidator } from './config-file-validator'; import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; import { ArduinoEnvVariablesServer } from './arduino-env-variables-server'; +import { NodeFileSystemExt } from './node-filesystem-ext'; +import { FileSystemExt, FileSystemExtPath } from '../common/protocol/filesystem-ext'; export default new ContainerModule((bind, unbind, isBound, rebind) => { rebind(EnvVariablesServer).to(ArduinoEnvVariablesServer).inSingletonScope(); @@ -185,4 +187,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ArduinoHostedPluginReader).toSelf().inSingletonScope(); rebind(HostedPluginReader).toService(ArduinoHostedPluginReader); + + // File-system extension for mapping paths to URIs + bind(NodeFileSystemExt).toSelf().inSingletonScope(); + bind(FileSystemExt).toDynamicValue(context => context.container.get(NodeFileSystemExt)); + bind(ConnectionHandler).toDynamicValue(context => new JsonRpcConnectionHandler(FileSystemExtPath, () => context.container.get(FileSystemExt))).inSingletonScope(); }); diff --git a/arduino-ide-extension/src/node/boards-service-impl.ts b/arduino-ide-extension/src/node/boards-service-impl.ts index 176895c5..a46e1360 100644 --- a/arduino-ide-extension/src/node/boards-service-impl.ts +++ b/arduino-ide-extension/src/node/boards-service-impl.ts @@ -1,7 +1,7 @@ import { injectable, inject, postConstruct, named } from 'inversify'; import { ILogger } from '@theia/core/lib/common/logger'; import { Deferred } from '@theia/core/lib/common/promise-util'; -import { BoardsService, BoardsPackage, Board, BoardsServiceClient, Port, BoardDetails, Tool, ConfigOption, ConfigValue } from '../common/protocol'; +import { BoardsService, BoardsPackage, Board, BoardsServiceClient, Port, BoardDetails, Tool, ConfigOption, ConfigValue, Programmer } from '../common/protocol'; import { PlatformSearchReq, PlatformSearchResp, PlatformInstallReq, PlatformInstallResp, PlatformListReq, PlatformListResp, Platform, PlatformUninstallResp, PlatformUninstallReq @@ -10,6 +10,7 @@ import { CoreClientProvider } from './core-client-provider'; import { BoardListReq, BoardListResp, BoardDetailsReq, BoardDetailsResp } from './cli-protocol/commands/board_pb'; import { ToolOutputServiceServer } from '../common/protocol/tool-output-service'; import { Installable } from '../common/protocol/installable'; +import { ListProgrammersAvailableForUploadReq, ListProgrammersAvailableForUploadResp } from './cli-protocol/commands/upload_pb'; @injectable() export class BoardsServiceImpl implements BoardsService { @@ -209,10 +210,10 @@ export class BoardsServiceImpl implements BoardsService { const { client, instance } = coreClient; const { fqbn } = options; - const req = new BoardDetailsReq(); - req.setInstance(instance); - req.setFqbn(fqbn); - const resp = await new Promise((resolve, reject) => client.boardDetails(req, (err, resp) => { + const detailsReq = new BoardDetailsReq(); + detailsReq.setInstance(instance); + detailsReq.setFqbn(fqbn); + const detailsResp = await new Promise((resolve, reject) => client.boardDetails(detailsReq, (err, resp) => { if (err) { reject(err); return; @@ -220,13 +221,13 @@ export class BoardsServiceImpl implements BoardsService { resolve(resp); })); - const requiredTools = resp.getToolsdependenciesList().map(t => { + const requiredTools = detailsResp.getToolsdependenciesList().map(t => { name: t.getName(), packager: t.getPackager(), version: t.getVersion() }); - const configOptions = resp.getConfigOptionsList().map(c => { + const configOptions = detailsResp.getConfigOptionsList().map(c => { label: c.getOptionLabel(), option: c.getOption(), values: c.getValuesList().map(v => { @@ -236,10 +237,28 @@ export class BoardsServiceImpl implements BoardsService { }) }); + const listReq = new ListProgrammersAvailableForUploadReq(); + listReq.setInstance(instance); + listReq.setFqbn(fqbn); + const listResp = await new Promise((resolve, reject) => client.listProgrammersAvailableForUpload(listReq, (err, resp) => { + if (err) { + reject(err); + return; + } + resolve(resp); + })); + + const programmers = listResp.getProgrammersList().map(p => { + id: p.getId(), + name: p.getName(), + platform: p.getPlatform() + }); + return { fqbn, requiredTools, - configOptions + configOptions, + programmers }; } @@ -261,13 +280,10 @@ export class BoardsServiceImpl implements BoardsService { return packages.find(({ boards }) => boards.some(({ fqbn }) => fqbn === expectedFqbn)); } - async searchBoards(options: { query?: string }): Promise> { - const query = (options.query || '').toLocaleLowerCase(); + async allBoards(options: {}): Promise> { const results = await this.search(options); return results.map(item => item.boards.map(board => ({ ...board, packageName: item.name }))) - .reduce((acc, curr) => acc.concat(curr), []) - .filter(board => board.name.toLocaleLowerCase().indexOf(query) !== -1) - .sort(Board.compare); + .reduce((acc, curr) => acc.concat(curr), []); } async search(options: { query?: string }): Promise { diff --git a/arduino-ide-extension/src/node/config-service-impl.ts b/arduino-ide-extension/src/node/config-service-impl.ts index a09b350e..81d83409 100644 --- a/arduino-ide-extension/src/node/config-service-impl.ts +++ b/arduino-ide-extension/src/node/config-service-impl.ts @@ -13,6 +13,7 @@ import * as fs from './fs-extra'; import { spawnCommand } from './exec-util'; import { RawData } from './cli-protocol/settings/settings_pb'; import { SettingsClient } from './cli-protocol/settings/settings_grpc_pb'; +import * as serviceGrpcPb from './cli-protocol/settings/settings_grpc_pb'; import { ConfigFileValidator } from './config-file-validator'; import { ArduinoDaemonImpl } from './arduino-daemon-impl'; import { DefaultCliConfig, CLI_CONFIG_SCHEMA_PATH, CLI_CONFIG } from './cli-config'; @@ -245,7 +246,10 @@ export class ConfigServiceImpl implements BackendApplicationContribution, Config } protected async updateDaemon(port: string | number, config: DefaultCliConfig): Promise { - const client = new SettingsClient(`localhost:${port}`, grpc.credentials.createInsecure()); + // https://github.com/agreatfool/grpc_tools_node_protoc_ts/blob/master/doc/grpcjs_support.md#usage + // @ts-ignore + const SettingsClient = grpc.makeClientConstructor(serviceGrpcPb['cc.arduino.cli.settings.Settings'], 'SettingsService') as any; + const client = new SettingsClient(`localhost:${port}`, grpc.credentials.createInsecure()) as SettingsClient; const data = new RawData(); data.setJsondata(JSON.stringify(config, null, 2)); return new Promise((resolve, reject) => { diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index e777d7f9..c19da8d6 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -35,7 +35,7 @@ export class CoreServiceImpl implements CoreService { } async compile(options: CoreService.Compile.Options): Promise { - console.log('compile', options); + this.toolOutputService.publishNewOutput('compile', 'Compiling...\n' + JSON.stringify(options, null, 2) + '\n'); const { sketchUri, fqbn } = options; const sketchFilePath = await this.fileSystem.getFsPath(sketchUri); if (!sketchFilePath) { @@ -61,27 +61,30 @@ export class CoreServiceImpl implements CoreService { compilerReq.setPreprocess(false); compilerReq.setVerbose(true); compilerReq.setQuiet(false); + if (options.programmer) { + compilerReq.setProgrammer(options.programmer.id); + } const result = client.compile(compilerReq); try { await new Promise((resolve, reject) => { result.on('data', (cr: CompileResp) => { this.toolOutputService.publishNewOutput("compile", Buffer.from(cr.getOutStream_asU8()).toString()); - this.toolOutputService.publishNewOutput("compile error", Buffer.from(cr.getErrStream_asU8()).toString()); + this.toolOutputService.publishNewOutput("compile", Buffer.from(cr.getErrStream_asU8()).toString()); }); result.on('error', error => reject(error)); result.on('end', () => resolve()); }); - this.toolOutputService.publishNewOutput("compile", "Compilation complete\n"); + this.toolOutputService.publishNewOutput("compile", "Compilation complete.\n"); } catch (e) { - this.toolOutputService.publishNewOutput("compile error", `Compilation error: ${e}\n`); + this.toolOutputService.publishNewOutput("compile", `Compilation error: ${e}\n`); throw e; } } async upload(options: CoreService.Upload.Options): Promise { await this.compile(options); - console.log('upload', options); + this.toolOutputService.publishNewOutput('upload', 'Uploading...\n' + JSON.stringify(options, null, 2) + '\n'); const { sketchUri, fqbn } = options; const sketchFilePath = await this.fileSystem.getFsPath(sketchUri); if (!sketchFilePath) { @@ -89,7 +92,6 @@ export class CoreServiceImpl implements CoreService { } const sketchpath = path.dirname(sketchFilePath); - const coreClient = await this.coreClientProvider.client(); if (!coreClient) { return; @@ -100,25 +102,28 @@ export class CoreServiceImpl implements CoreService { throw new Error('The selected board has no FQBN.'); } - const req = new UploadReq(); - req.setInstance(instance); - req.setSketchPath(sketchpath); - req.setFqbn(fqbn); - req.setPort(options.port); - const result = client.upload(req); + const uploadReq = new UploadReq(); + uploadReq.setInstance(instance); + uploadReq.setSketchPath(sketchpath); + uploadReq.setFqbn(fqbn); + uploadReq.setPort(options.port); + if (options.programmer) { + uploadReq.setProgrammer(options.programmer.id); + } + const result = client.upload(uploadReq); try { await new Promise((resolve, reject) => { result.on('data', (cr: UploadResp) => { this.toolOutputService.publishNewOutput("upload", Buffer.from(cr.getOutStream_asU8()).toString()); - this.toolOutputService.publishNewOutput("upload error", Buffer.from(cr.getErrStream_asU8()).toString()); + this.toolOutputService.publishNewOutput("upload", Buffer.from(cr.getErrStream_asU8()).toString()); }); result.on('error', error => reject(error)); result.on('end', () => resolve()); }); - this.toolOutputService.publishNewOutput("upload", "Upload complete\n"); + this.toolOutputService.publishNewOutput("upload", "Upload complete.\n"); } catch (e) { - this.toolOutputService.publishNewOutput("upload error", `Upload error: ${e}\n`); + this.toolOutputService.publishNewOutput("upload", `Upload error: ${e}\n`); throw e; } } diff --git a/arduino-ide-extension/src/node/node-filesystem-ext.ts b/arduino-ide-extension/src/node/node-filesystem-ext.ts new file mode 100644 index 00000000..93af5744 --- /dev/null +++ b/arduino-ide-extension/src/node/node-filesystem-ext.ts @@ -0,0 +1,12 @@ +import { injectable } from 'inversify'; +import { FileUri } from '@theia/core/lib/node/file-uri'; +import { FileSystemExt } from '../common/protocol/filesystem-ext'; + +@injectable() +export class NodeFileSystemExt implements FileSystemExt { + + async getUri(fsPath: string): Promise { + return FileUri.create(fsPath).toString() + } + +} diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index 108ac50d..500f4067 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -1,19 +1,29 @@ import { injectable, inject } from 'inversify'; +import * as os from 'os'; +import * as temp from 'temp'; import * as path from 'path'; import * as fs from './fs-extra'; -import { FileUri } from '@theia/core/lib/node'; +import { ncp } from 'ncp'; +import { FileUri, BackendApplicationContribution } from '@theia/core/lib/node'; import { ConfigService } from '../common/protocol/config-service'; import { SketchesService, Sketch } from '../common/protocol/sketches-service'; +import URI from '@theia/core/lib/common/uri'; export const ALLOWED_FILE_EXTENSIONS = ['.c', '.cpp', '.h', '.hh', '.hpp', '.s', '.pde', '.ino']; // TODO: `fs`: use async API @injectable() -export class SketchesServiceImpl implements SketchesService { +export class SketchesServiceImpl implements SketchesService, BackendApplicationContribution { + + protected readonly temp = temp.track(); @inject(ConfigService) protected readonly configService: ConfigService; + onStop(): void { + this.temp.cleanupSync(); + } + async getSketches(uri?: string): Promise { const sketches: Array = []; let fsPath: undefined | string; @@ -53,13 +63,19 @@ export class SketchesServiceImpl implements SketchesService { const fsPath = FileUri.fsPath(uri); if (fs.lstatSync(fsPath).isDirectory()) { if (await this.isSketchFolder(uri)) { + const basename = path.basename(fsPath) const fileNames = await fs.readdir(fsPath); for (const fileName of fileNames) { const filePath = path.join(fsPath, fileName); if (ALLOWED_FILE_EXTENSIONS.indexOf(path.extname(filePath)) !== -1 && fs.existsSync(filePath) && fs.lstatSync(filePath).isFile()) { - uris.push(FileUri.create(filePath).toString()) + const uri = FileUri.create(filePath).toString(); + if (fileName === basename + '.ino') { + uris.unshift(uri); // The sketch file is the first. + } else { + uris.push(uri); + } } } } @@ -69,19 +85,26 @@ export class SketchesServiceImpl implements SketchesService { return this.getSketchFiles(FileUri.create(sketchDir).toString()); } - async createNewSketch(parentUri?: string): Promise { - const monthNames = ['january', 'february', 'march', 'april', 'may', 'june', - 'july', 'august', 'september', 'october', 'november', 'december' - ]; + async createNewSketch(): Promise { + const monthNames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']; const today = new Date(); - const uri = !!parentUri ? parentUri : (await this.configService.getConfiguration()).sketchDirUri; - const parent = FileUri.fsPath(uri); - + const parent = await new Promise((resolve, reject) => { + this.temp.mkdir({ prefix: '.arduinoProIDE' }, (err, dirPath) => { + if (err) { + reject(err); + return; + } + resolve(dirPath); + }) + }) const sketchBaseName = `sketch_${monthNames[today.getMonth()]}${today.getDate()}`; + const config = await this.configService.getConfiguration(); + const user = FileUri.fsPath(config.sketchDirUri); let sketchName: string | undefined; for (let i = 97; i < 97 + 26; i++) { let sketchNameCandidate = `${sketchBaseName}${String.fromCharCode(i)}`; - if (fs.existsSync(path.join(parent, sketchNameCandidate))) { + // Note: we check the future destination folder (`directories.user`) for name collision and not the temp folder! + if (fs.existsSync(path.join(user, sketchNameCandidate))) { continue; } @@ -96,14 +119,13 @@ export class SketchesServiceImpl implements SketchesService { const sketchDir = path.join(parent, sketchName) const sketchFile = path.join(sketchDir, `${sketchName}.ino`); await fs.mkdirp(sketchDir); - await fs.writeFile(sketchFile, ` -void setup() { -// put your setup code here, to run once: + await fs.writeFile(sketchFile, `void setup() { + // put your setup code here, to run once: } void loop() { -// put your main code here, to run repeatedly: + // put your main code here, to run repeatedly: } `, { encoding: 'utf8' }); @@ -113,6 +135,23 @@ void loop() { } } + async getSketchFolder(uri: string): Promise { + if (!uri) { + return undefined; + } + let currentUri = new URI(uri); + while (currentUri && !currentUri.path.isRoot) { + if (await this.isSketchFolder(currentUri.toString())) { + return { + name: currentUri.path.base, + uri: currentUri.toString() + }; + } + currentUri = currentUri.parent; + } + return undefined; + } + async isSketchFolder(uri: string): Promise { const fsPath = FileUri.fsPath(uri); if (fs.existsSync(fsPath) && fs.lstatSync(fsPath).isDirectory()) { @@ -126,4 +165,28 @@ void loop() { } return false; } + + async isTemp(sketch: Sketch): Promise { + const sketchPath = FileUri.fsPath(sketch.uri); + return sketchPath.indexOf('.arduinoProIDE') !== -1 && sketchPath.startsWith(os.tmpdir()); + } + + async copy(sketch: Sketch, { destinationUri }: { destinationUri: string }): Promise { + const source = FileUri.fsPath(sketch.uri); + if (await !fs.exists(source)) { + throw new Error(`Sketch does not exist: ${sketch}`); + } + const destination = FileUri.fsPath(destinationUri); + await new Promise((resolve, reject) => { + ncp.ncp(source, destination, error => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }); + return FileUri.create(destination).toString(); + } + } diff --git a/arduino-ide-extension/src/test/browser/boards-service-client-impl.test.ts b/arduino-ide-extension/src/test/browser/boards-service-client-impl.test.ts index 59c3e8fa..992de377 100644 --- a/arduino-ide-extension/src/test/browser/boards-service-client-impl.test.ts +++ b/arduino-ide-extension/src/test/browser/boards-service-client-impl.test.ts @@ -268,7 +268,7 @@ export class MockBoardsService implements BoardsService { throw new Error('Method not implemented.'); } - searchBoards(): Promise> { + allBoards(): Promise> { throw new Error('Method not implemented.'); } diff --git a/arduino-ide-extension/src/test/common/boards-service.test.ts b/arduino-ide-extension/src/test/common/boards-service.test.ts index 62dc0781..26450f83 100644 --- a/arduino-ide-extension/src/test/common/boards-service.test.ts +++ b/arduino-ide-extension/src/test/common/boards-service.test.ts @@ -1,6 +1,5 @@ import { expect } from 'chai'; -import { ConfigOption, AttachedBoardsChangeEvent } from '../../common/protocol'; -import { fail } from 'assert'; +import { AttachedBoardsChangeEvent } from '../../common/protocol'; describe('boards-service', () => { @@ -46,71 +45,4 @@ describe('boards-service', () => { }); - - describe('ConfigOption', () => { - - ([ - ['', false], - ['foo', true], - ['foo:bar', true], - ['foo:bar:baz', true], - ['foo:', false], - [':foo', false], - [':foo:', false], - ['foo:bar:', false] - ] as Array<[string, boolean]>).forEach(([fqbn, expectation]) => { - it(`"${fqbn}" should ${expectation ? '' : 'not '}be a valid FQBN`, () => { - expect(ConfigOption.isValidFqbn(fqbn)).to.be.equal(expectation); - }); - }); - - ([ - ['', false], - ['foo:bar:option1', false], - ['foo:bar:option1=', false], - ['foo:bar:baz:option1=value1', true], - ['foo:bar:baz:option1=value1,option2=value2', true], - ['foo:bar:baz:option1=value1,option2=value2,', false], - ['foo:bar:baz,option1=value1,option2=value2', false], - ['foo:bar:baz:option1=value1,option2=value2,options3', false], - ['foo:bar:baz:option1=value1,option2=value2, options3=value3', false], - ] as Array<[string, boolean]>).forEach(([fqbn, expectation]) => { - it(`"${fqbn}" should ${expectation ? '' : 'not '}be a valid FQBN with options`, () => { - expect(ConfigOption.isValidFqbnWithOptions(fqbn)).to.be.equal(expectation); - }); - }); - - ([ - [ - 'foo:bar:baz', - JSON.parse('[{"label":"CPU Frequency","option":"xtal","values":[{"value":"80","label":"80 MHz","selected":true},{"value":"160","label":"160 MHz","selected":false}]},{"label":"VTables","option":"vt","values":[{"value":"flash","label":"Flash","selected":true},{"value":"heap","label":"Heap","selected":false},{"value":"iram","label":"IRAM","selected":false}]},{"label":"Exceptions","option":"exception","values":[{"value":"legacy","label":"Legacy (new can return nullptr)","selected":true},{"value":"disabled","label":"Disabled (new can abort)","selected":false},{"value":"enabled","label":"Enabled","selected":false}]},{"label":"SSL Support","option":"ssl","values":[{"value":"all","label":"All SSL ciphers (most compatible)","selected":true},{"value":"basic","label":"Basic SSL ciphers (lower ROM use)","selected":false}]},{"label":"Flash Size","option":"eesz","values":[{"value":"4M2M","label":"4MB (FS:2MB OTA:~1019KB)","selected":true},{"value":"4M3M","label":"4MB (FS:3MB OTA:~512KB)","selected":false},{"value":"4M1M","label":"4MB (FS:1MB OTA:~1019KB)","selected":false},{"value":"4M","label":"4MB (FS:none OTA:~1019KB)","selected":false}]},{"label":"lwIP Variant","option":"ip","values":[{"value":"lm2f","label":"v2 Lower Memory","selected":true},{"value":"hb2f","label":"v2 Higher Bandwidth","selected":false},{"value":"lm2n","label":"v2 Lower Memory (no features)","selected":false},{"value":"hb2n","label":"v2 Higher Bandwidth (no features)","selected":false},{"value":"lm6f","label":"v2 IPv6 Lower Memory","selected":false},{"value":"hb6f","label":"v2 IPv6 Higher Bandwidth","selected":false},{"value":"hb1","label":"v1.4 Higher Bandwidth","selected":false},{"value":"src","label":"v1.4 Compile from source","selected":false}]},{"label":"Debug port","option":"dbg","values":[{"value":"Disabled","label":"Disabled","selected":true},{"value":"Serial","label":"Serial","selected":false},{"value":"Serial1","label":"Serial1","selected":false}]},{"label":"Debug Level","option":"lvl","values":[{"value":"None____","label":"None","selected":true},{"value":"SSL","label":"SSL","selected":false},{"value":"TLS_MEM","label":"TLS_MEM","selected":false},{"value":"HTTP_CLIENT","label":"HTTP_CLIENT","selected":false},{"value":"HTTP_SERVER","label":"HTTP_SERVER","selected":false},{"value":"SSLTLS_MEM","label":"SSL+TLS_MEM","selected":false},{"value":"SSLHTTP_CLIENT","label":"SSL+HTTP_CLIENT","selected":false},{"value":"SSLHTTP_SERVER","label":"SSL+HTTP_SERVER","selected":false},{"value":"TLS_MEMHTTP_CLIENT","label":"TLS_MEM+HTTP_CLIENT","selected":false},{"value":"TLS_MEMHTTP_SERVER","label":"TLS_MEM+HTTP_SERVER","selected":false},{"value":"HTTP_CLIENTHTTP_SERVER","label":"HTTP_CLIENT+HTTP_SERVER","selected":false},{"value":"SSLTLS_MEMHTTP_CLIENT","label":"SSL+TLS_MEM+HTTP_CLIENT","selected":false},{"value":"SSLTLS_MEMHTTP_SERVER","label":"SSL+TLS_MEM+HTTP_SERVER","selected":false},{"value":"SSLHTTP_CLIENTHTTP_SERVER","label":"SSL+HTTP_CLIENT+HTTP_SERVER","selected":false},{"value":"TLS_MEMHTTP_CLIENTHTTP_SERVER","label":"TLS_MEM+HTTP_CLIENT+HTTP_SERVER","selected":false},{"value":"SSLTLS_MEMHTTP_CLIENTHTTP_SERVER","label":"SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER","selected":false},{"value":"CORE","label":"CORE","selected":false},{"value":"WIFI","label":"WIFI","selected":false},{"value":"HTTP_UPDATE","label":"HTTP_UPDATE","selected":false},{"value":"UPDATER","label":"UPDATER","selected":false},{"value":"OTA","label":"OTA","selected":false},{"value":"OOM","label":"OOM","selected":false},{"value":"MDNS","label":"MDNS","selected":false},{"value":"COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS","label":"CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS","selected":false},{"value":"SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS","label":"SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS","selected":false},{"value":"NoAssert-NDEBUG","label":"NoAssert-NDEBUG","selected":false}]},{"label":"Erase Flash","option":"wipe","values":[{"value":"none","label":"Only Sketch","selected":true},{"value":"sdk","label":"Sketch + WiFi Settings","selected":false},{"value":"all","label":"All Flash Contents","selected":false}]},{"label":"Upload Speed","option":"baud","values":[{"value":"115200","label":"115200","selected":true},{"value":"57600","label":"57600","selected":false},{"value":"230400","label":"230400","selected":false},{"value":"460800","label":"460800","selected":false},{"value":"921600","label":"921600","selected":false},{"value":"3000000","label":"3000000","selected":false}]}]'), - 'foo:bar:baz:xtal=80,vt=flash,exception=legacy,ssl=all,eesz=4M2M,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200' - ], - [ - 'foo:bar:baz', - JSON.parse('[]'), - 'foo:bar:baz' - ], - [ - 'foo:bar:baz:xtal=80', - {}, - undefined - ] - ] as Array<[string, Array, string | undefined]>).forEach(([fqbn, configOptions, expectation]) => { - it(`should ${expectation ? `append` : 'throw an error when appending'}config options to ${fqbn}`, () => { - if (!expectation) { - try { - ConfigOption.decorate(fqbn, configOptions); - fail(`Expected a failure when decorating ${fqbn} with config options.`); - } catch (e) { - expect(e).to.be.instanceOf(ConfigOption.ConfigOptionError); - } - } else { - expect(ConfigOption.decorate(fqbn, configOptions)).to.be.equal(expectation); - } - }); - }); - - }); - }); diff --git a/browser-app/package.json b/browser-app/package.json index cccdec00..ea85501a 100644 --- a/browser-app/package.json +++ b/browser-app/package.json @@ -5,7 +5,6 @@ "license": "MIT", "dependencies": { "@theia/core": "next", - "@theia/cpp": "next", "@theia/debug": "next", "@theia/editor": "next", "@theia/file-search": "next", @@ -37,7 +36,9 @@ "applicationName": "Arduino Pro IDE", "defaultTheme": "arduino-theme", "preferences": { - "editor.autoSave": "on" + "editor.autoSave": "on", + "editor.minimap.enabled": false, + "editor.scrollBeyondLastLine": false } } }, diff --git a/electron-app/package.json b/electron-app/package.json index 4d28cb37..a3274b39 100644 --- a/electron-app/package.json +++ b/electron-app/package.json @@ -6,7 +6,6 @@ "main": "src-gen/frontend/electron-main.js", "dependencies": { "@theia/core": "next", - "@theia/cpp": "next", "@theia/debug": "next", "@theia/editor": "next", "@theia/electron": "next", @@ -40,7 +39,9 @@ "applicationName": "Arduino Pro IDE", "defaultTheme": "arduino-theme", "preferences": { - "editor.autoSave": "on" + "editor.autoSave": "on", + "editor.minimap.enabled": false, + "editor.scrollBeyondLastLine": false } } }, diff --git a/electron/build/patch/electron-main.js b/electron/build/patch/electron-main.js new file mode 100644 index 00000000..7d98fb0d --- /dev/null +++ b/electron/build/patch/electron-main.js @@ -0,0 +1,289 @@ +// @ts-check + +// Useful for Electron/NW.js apps as GUI apps on macOS doesn't inherit the `$PATH` define +// in your dotfiles (.bashrc/.bash_profile/.zshrc/etc). +// https://github.com/electron/electron/issues/550#issuecomment-162037357 +// https://github.com/eclipse-theia/theia/pull/3534#issuecomment-439689082 +require('fix-path')(); + +// Workaround for https://github.com/electron/electron/issues/9225. Chrome has an issue where +// in certain locales (e.g. PL), image metrics are wrongly computed. We explicitly set the +// LC_NUMERIC to prevent this from happening (selects the numeric formatting category of the +// C locale, http://en.cppreference.com/w/cpp/locale/LC_categories). +if (process.env.LC_ALL) { + process.env.LC_ALL = 'C'; +} +process.env.LC_NUMERIC = 'C'; + +const { v4 } = require('uuid'); +const electron = require('electron'); +const { join, resolve } = require('path'); +const { fork } = require('child_process'); +const { app, dialog, shell, BrowserWindow, ipcMain, Menu, globalShortcut } = electron; +const { ElectronSecurityToken } = require('@theia/core/lib/electron-common/electron-token'); + +const applicationName = `Arduino Pro IDE`; +const isSingleInstance = false; +const disallowReloadKeybinding = false; +const defaultWindowOptionsAdditions = {}; + + +if (isSingleInstance && !app.requestSingleInstanceLock()) { + // There is another instance running, exit now. The other instance will request focus. + app.quit(); + return; +} + +const nativeKeymap = require('native-keymap'); +const Storage = require('electron-store'); +const electronStore = new Storage(); + +const electronSecurityToken = { + value: v4(), +}; + +// Make it easy for renderer process to fetch the ElectronSecurityToken: +global[ElectronSecurityToken] = electronSecurityToken; + +app.on('ready', () => { + + // Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit") + // See: https://github.com/electron-userland/electron-builder/issues/2468 + app.setName(applicationName); + + const { screen } = electron; + + // Remove the default electron menus, waiting for the application to set its own. + Menu.setApplicationMenu(Menu.buildFromTemplate([{ + role: 'help', submenu: [{ role: 'toggleDevTools' }] + }])); + + function createNewWindow(theUrl) { + + // We must center by hand because `browserWindow.center()` fails on multi-screen setups + // See: https://github.com/electron/electron/issues/3490 + const { bounds } = screen.getDisplayNearestPoint(screen.getCursorScreenPoint()); + const height = Math.floor(bounds.height * (2 / 3)); + const width = Math.floor(bounds.width * (2 / 3)); + + const y = Math.floor(bounds.y + (bounds.height - height) / 2); + const x = Math.floor(bounds.x + (bounds.width - width) / 2); + + const WINDOW_STATE = 'windowstate'; + const windowState = electronStore.get(WINDOW_STATE, { + width, height, x, y + }); + + const persistedWindowOptionsAdditions = electronStore.get('windowOptions', {}); + + const windowOptionsAdditions = { + ...defaultWindowOptionsAdditions, + ...persistedWindowOptionsAdditions + }; + + let windowOptions = { + show: false, + title: applicationName, + width: windowState.width, + height: windowState.height, + minWidth: 200, + minHeight: 120, + x: windowState.x, + y: windowState.y, + isMaximized: windowState.isMaximized, + ...windowOptionsAdditions, + webPreferences: { + nodeIntegration: true + } + }; + + // Always hide the window, we will show the window when it is ready to be shown in any case. + const newWindow = new BrowserWindow(windowOptions); + if (windowOptions.isMaximized) { + newWindow.maximize(); + } + newWindow.on('ready-to-show', () => newWindow.show()); + if (disallowReloadKeybinding) { + newWindow.on('focus', event => { + for (const accelerator of ['CmdOrCtrl+R', 'F5']) { + globalShortcut.register(accelerator, () => { }); + } + }); + newWindow.on('blur', event => globalShortcut.unregisterAll()); + } + + // Prevent calls to "window.open" from opening an ElectronBrowser window, + // and rather open in the OS default web browser. + newWindow.webContents.on('new-window', (event, url) => { + event.preventDefault(); + shell.openExternal(url); + }); + + // Save the window geometry state on every change + const saveWindowState = () => { + try { + let bounds; + if (newWindow.isMaximized()) { + bounds = electronStore.get(WINDOW_STATE, {}); + } else { + bounds = newWindow.getBounds(); + } + electronStore.set(WINDOW_STATE, { + isMaximized: newWindow.isMaximized(), + width: bounds.width, + height: bounds.height, + x: bounds.x, + y: bounds.y + }); + } catch (e) { + console.error("Error while saving window state.", e); + } + }; + let delayedSaveTimeout; + const saveWindowStateDelayed = () => { + if (delayedSaveTimeout) { + clearTimeout(delayedSaveTimeout); + } + delayedSaveTimeout = setTimeout(saveWindowState, 1000); + }; + newWindow.on('close', saveWindowState); + newWindow.on('resize', saveWindowStateDelayed); + newWindow.on('move', saveWindowStateDelayed); + + // Fired when a beforeunload handler tries to prevent the page unloading + newWindow.webContents.on('will-prevent-unload', async event => { + const { response } = await dialog.showMessageBox(newWindow, { + type: 'question', + buttons: ['Yes', 'No'], + title: 'Confirm', + message: 'Are you sure you want to quit?', + detail: 'Any unsaved changes will not be saved.' + }); + if (response === 0) { // 'Yes' + // This ignores the beforeunload callback, allowing the page to unload + event.preventDefault(); + } + }); + + // Notify the renderer process on keyboard layout change + nativeKeymap.onDidChangeKeyboardLayout(() => { + if (!newWindow.isDestroyed()) { + const newLayout = { + info: nativeKeymap.getCurrentKeyboardLayout(), + mapping: nativeKeymap.getKeyMap() + }; + newWindow.webContents.send('keyboardLayoutChanged', newLayout); + } + }); + + if (!!theUrl) { + newWindow.loadURL(theUrl); + } + return newWindow; + } + + app.on('window-all-closed', () => { + app.quit(); + }); + ipcMain.on('create-new-window', (event, url) => { + createNewWindow(url); + }); + ipcMain.on('open-external', (event, url) => { + shell.openExternal(url); + }); + ipcMain.on('set-window-options', (event, options) => { + electronStore.set('windowOptions', options); + }); + ipcMain.on('get-persisted-window-options-additions', event => { + event.returnValue = electronStore.get('windowOptions', {}); + }); + + // Check whether we are in bundled application or development mode. + // @ts-ignore + const devMode = process.defaultApp || /node_modules[/]electron[/]/.test(process.execPath); + // Check if we should run everything as one process. + const noBackendFork = process.argv.includes('--no-cluster'); + const mainWindow = createNewWindow(); + + if (isSingleInstance) { + app.on('second-instance', (event, commandLine, workingDirectory) => { + // Someone tried to run a second instance, we should focus our window. + if (mainWindow && !mainWindow.isDestroyed()) { + if (mainWindow.isMinimized()) { + mainWindow.restore(); + } + mainWindow.focus() + } + }) + } + + const setElectronSecurityToken = async port => { + await electron.session.defaultSession.cookies.set({ + url: `http://localhost:${port}/`, + name: ElectronSecurityToken, + value: JSON.stringify(electronSecurityToken), + httpOnly: true + }); + }; + + const loadMainWindow = port => { + if (!mainWindow.isDestroyed()) { + mainWindow.loadURL('file://' + join(__dirname, '../../lib/index.html') + '?port=' + port); + } + }; + + // We cannot use the `process.cwd()` as the application project path (the location of the `package.json` in other words) + // in a bundled electron application because it depends on the way we start it. For instance, on OS X, these are a differences: + // https://github.com/eclipse-theia/theia/issues/3297#issuecomment-439172274 + process.env.THEIA_APP_PROJECT_PATH = resolve(__dirname, '..', '..'); + + // Set the electron version for both the dev and the production mode. (https://github.com/eclipse-theia/theia/issues/3254) + // Otherwise, the forked backend processes will not know that they're serving the electron frontend. + // The forked backend should patch its `process.versions.electron` with this value if it is missing. + process.env.THEIA_ELECTRON_VERSION = process.versions.electron; + + const mainPath = join(__dirname, '..', 'backend', 'main'); + // We spawn a separate process for the backend for Express to not run in the Electron main process. + // See: https://github.com/eclipse-theia/theia/pull/7361#issuecomment-601272212 + // But when in debugging we want to run everything in the same process to make things easier. + if (noBackendFork) { + process.env[ElectronSecurityToken] = JSON.stringify(electronSecurityToken); + require(mainPath).then(async (address) => { + await setElectronSecurityToken(address.port); + loadMainWindow(address.port); + }).catch((error) => { + console.error(error); + app.exit(1); + }); + } else { + // We want to pass flags passed to the Electron app to the backend process. + // Quirk: When developing from sources, we execute Electron as `electron.exe electron-main.js ...args`, but when bundled, + // the command looks like `bundled-application.exe ...args`. + let args = process.argv.slice(devMode ? 2 : 1); + if (process.platform === 'darwin') { + // https://github.com/electron/electron/issues/3657 + // https://stackoverflow.com/questions/10242115/os-x-strange-psn-command-line-parameter-when-launched-from-finder#comment102377986_10242200 + // macOS appends an extra `-psn_0_someNumber` arg if a file is opened from Finder after downloading from the Internet. + // "AppName" is an app downloaded from the Internet. Are you sure you want to open it? + args = args.filter(arg => !arg.startsWith('-psn')); + } + const cp = fork(mainPath, args, { + env: Object.assign({ + [ElectronSecurityToken]: JSON.stringify(electronSecurityToken), + }, process.env) + }); + cp.on('message', async (address) => { + await setElectronSecurityToken(address.port); + loadMainWindow(address.port); + }); + cp.on('error', (error) => { + console.error(error); + app.exit(1); + }); + app.on('quit', () => { + // If we forked the process for the clusters, we need to manually terminate it. + // See: https://github.com/eclipse-theia/theia/issues/835 + process.kill(cp.pid); + }); + } +}); diff --git a/electron/build/template-package.json b/electron/build/template-package.json index c4a8b0cc..98831e9a 100644 --- a/electron/build/template-package.json +++ b/electron/build/template-package.json @@ -10,17 +10,19 @@ "electron-builder": "^22.4.1", "electron-notarize": "^0.3.0", "is-ci": "^2.0.0", + "ncp": "^2.0.0", "shelljs": "^0.8.3" }, "scripts": { - "build": "yarn download:plugins && theia build --mode development", - "build:publish": "yarn download:plugins && theia build --mode production", + "build": "yarn download:plugins && theia build --mode development && yarn patch", + "build:publish": "yarn download:plugins && theia build --mode production && yarn patch", "package": "cross-env DEBUG=* && electron-builder --publish=never", "package:publish": "cross-env DEBUG=* && electron-builder --publish=always", - "download:plugins": "theia download:plugins" + "download:plugins": "theia download:plugins", + "patch": "ncp ./patch/electron-main.js ./src-gen/frontend/electron-main.js" }, "engines": { - "node": ">=10.11.0 <12" + "node": ">=10.11.0 <13" }, "repository": { "type": "git", diff --git a/electron/packager/package.json b/electron/packager/package.json index 0193ee50..c2637786 100644 --- a/electron/packager/package.json +++ b/electron/packager/package.json @@ -31,7 +31,7 @@ "yargs": "^12.0.5" }, "engines": { - "node": ">=10.11.0 <12" + "node": ">=10.11.0 <13" }, "mocha": { "reporter": "spec", diff --git a/package.json b/package.json index b1605b76..ebf0d349 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "author": "Arduino SA", "license": "MIT", "private": true, + "engines": { + "node": ">=10.11.0 <13" + }, "devDependencies": { "@theia/cli": "next", "cross-env": "^7.0.2", diff --git a/yarn.lock b/yarn.lock index 9995a965..8bb2f8b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,44 +10,43 @@ "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.4.tgz#706a6484ee6f910b719b696a9194f8da7d7ac241" - integrity sha512-t+rjExOrSVvjQQXNp5zAIYDp00KjdvGl/TpDX5REPr0S9IAIPQMTilcfG6q8c0QFmj9lSTVySV2VTsyggvtNIw== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.5.tgz#d38425e67ea96b1480a3f50404d1bf85676301a6" + integrity sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw== dependencies: browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" -"@babel/core@^7.5.5": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" - integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== +"@babel/core@^7.10.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" + integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-module-transforms" "^7.10.5" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.4" + "@babel/parser" "^7.10.5" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/traverse" "^7.10.5" + "@babel/types" "^7.10.5" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" - integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng== +"@babel/generator@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" + integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.10.5" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/helper-annotate-as-pure@^7.10.4": @@ -77,12 +76,12 @@ semver "^5.5.0" "@babel/helper-create-class-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz#2d4015d0136bd314103a70d84a7183e4b344a355" - integrity sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== dependencies: "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" "@babel/helper-optimise-call-expression" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-replace-supers" "^7.10.4" @@ -98,13 +97,13 @@ regexpu-core "^4.7.0" "@babel/helper-define-map@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.4.tgz#f037ad794264f729eda1889f4ee210b870999092" - integrity sha512-nIij0oKErfCnLUCWaCaHW0Bmtl2RO9cN7+u2QT8yqTywgALKlyUVOvHDElh+b5DwVC6YB1FOYFOTWcN/+41EDA== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: "@babel/helper-function-name" "^7.10.4" - "@babel/types" "^7.10.4" - lodash "^4.17.13" + "@babel/types" "^7.10.5" + lodash "^4.17.19" "@babel/helper-explode-assignable-expression@^7.10.4": version "7.10.4" @@ -137,12 +136,12 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz#7cd04b57dfcf82fce9aeae7d4e4452fa31b8c7c4" - integrity sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A== +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz#172f56e7a63e78112f3a04055f24365af702e7ee" + integrity sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.10.5" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4": version "7.10.4" @@ -151,18 +150,18 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz#ca1f01fdb84e48c24d7506bb818c961f1da8805d" - integrity sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q== +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz#120c271c0b3353673fcdfd8c053db3c544a260d6" + integrity sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA== dependencies: "@babel/helper-module-imports" "^7.10.4" "@babel/helper-replace-supers" "^7.10.4" "@babel/helper-simple-access" "^7.10.4" "@babel/helper-split-export-declaration" "^7.10.4" "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - lodash "^4.17.13" + "@babel/types" "^7.10.5" + lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" @@ -177,11 +176,11 @@ integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== "@babel/helper-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.4.tgz#59b373daaf3458e5747dece71bbaf45f9676af6d" - integrity sha512-inWpnHGgtg5NOF0eyHlC0/74/VkdRITY9dtTpB2PrxKKn+AkVMRiZz/Adrx+Ssg+MLDesi2zohBW6MVq6b4pOQ== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== dependencies: - lodash "^4.17.13" + lodash "^4.17.19" "@babel/helper-remap-async-to-generator@^7.10.4": version "7.10.4" @@ -252,15 +251,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" - integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== +"@babel/parser@^7.10.4", "@babel/parser@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" + integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== "@babel/plugin-proposal-async-generator-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" - integrity sha512-MJbxGSmejEFVOANAezdO39SObkURO5o/8b6fSH6D1pi9RZQt+ldppKPXfqgUWpSQ9asM6xaSaSJIaeWMDRP0Zg== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-remap-async-to-generator" "^7.10.4" @@ -441,14 +440,13 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoping@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.4.tgz#a670d1364bb5019a621b9ea2001482876d734787" - integrity sha512-J3b5CluMg3hPUii2onJDRiaVbPtKFPLEaV5dOPY5OeAbDi1iU/UbbFFTgwb7WnanaDy7bjU35kc26W3eM5Qa0A== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz#b81b8aafefbfe68f0f65f7ef397b9ece68a6037d" + integrity sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.10.4", "@babel/plugin-transform-classes@^7.5.5": +"@babel/plugin-transform-classes@^7.10.0", "@babel/plugin-transform-classes@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== @@ -529,11 +527,11 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-modules-amd@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.4.tgz#cb407c68b862e4c1d13a2fc738c7ec5ed75fc520" - integrity sha512-3Fw+H3WLUrTlzi3zMiZWp3AR4xadAEMv6XRCYnd5jAlLM61Rn+CRJaZMaNvIpcJpQ3vs1kyifYvEVPFfoSkKOA== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" @@ -548,12 +546,12 @@ babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.4.tgz#8f576afd943ac2f789b35ded0a6312f929c633f9" - integrity sha512-Tb28LlfxrTiOTGtZFsvkjpyjCl9IoaRI52AEU/VIwOwvDQWtbNJsAqTXzh+5R7i74e/OZHH2c2w2fsOqAfnQYQ== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" @@ -588,9 +586,9 @@ "@babel/helper-replace-supers" "^7.10.4" "@babel/plugin-transform-parameters@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.4.tgz#7b4d137c87ea7adc2a0f3ebf53266871daa6fced" - integrity sha512-RurVtZ/D5nYfEg0iVERXYKEgDFeesHrHfx8RT05Sq57ucj2eOYAP6eu5fynL4Adju4I/mP/I6SO0DqNWAXjfLQ== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: "@babel/helper-get-function-arity" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" @@ -616,10 +614,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-runtime@^7.5.5": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.4.tgz#594fb53453ea1b6f0779cceb48ce0718a447feb7" - integrity sha512-8ULlGv8p+Vuxu+kz2Y1dk6MYS2b/Dki+NO6/0ZlfSj5tMalfDL7jI/o/2a+rrWLqSXvnadEqc2WguB4gdQIxZw== +"@babel/plugin-transform-runtime@^7.10.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.5.tgz#3b39b7b24830e0c2d8ff7a4489fe5cf99fbace86" + integrity sha512-tV4V/FjElJ9lQtyjr5xD2IFFbgY46r7EeVu5a8CpEKT5laheHKSlFeHjpkPppW3PqzGLAuv5k2qZX5LgVZIX5w== dependencies: "@babel/helper-module-imports" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" @@ -649,9 +647,9 @@ "@babel/helper-regex" "^7.10.4" "@babel/plugin-transform-template-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.4.tgz#e6375407b30fcb7fcfdbba3bb98ef3e9d36df7bc" - integrity sha512-4NErciJkAYe+xI5cqfS8pV/0ntlY5N5Ske/4ImxAVX7mk9Rxt2bwDTGv1Msc2BRJvWQcmYEC+yoMLdX22aE4VQ== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" @@ -678,7 +676,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/preset-env@^7.5.5": +"@babel/preset-env@^7.10.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.4.tgz#fbf57f9a803afd97f4f32e4f798bb62e4b2bef5f" integrity sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw== @@ -759,10 +757,10 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" - integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== +"@babel/runtime@^7.10.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" + integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== dependencies: regenerator-runtime "^0.13.4" @@ -775,30 +773,46 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818" - integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q== +"@babel/traverse@^7.10.4", "@babel/traverse@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" + integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.4" + "@babel/generator" "^7.10.5" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/parser" "^7.10.5" + "@babel/types" "^7.10.5" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" - integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg== +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.4.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" + integrity sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q== dependencies: "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.13" + lodash "^4.17.19" to-fast-properties "^2.0.0" +"@electron/get@^1.0.1": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3" + integrity sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + progress "^2.0.3" + sanitize-filename "^1.6.2" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^2.0.2" + global-tunnel-ng "^2.7.1" + "@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": version "10.0.29" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" @@ -951,9 +965,9 @@ which "^1.3.1" "@grpc/grpc-js@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.1.tgz#56069fee48ba0667a0577a021504c573a6b613f0" - integrity sha512-mhZRszS0SKwnWPJaNyrECePZ9U7vaHFGqrzxQbWinWR3WznBIU+nmh2L5J3elF+lp5DEUIzARXkifbs6LQVAHA== + version "1.1.2" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.2.tgz#3125484c19fd1c9e3f4dc7a880f9fa1b872b46c8" + integrity sha512-k2u86Bkm/3xrjUaSWeIyzXScBt/cC8uE7BznR0cpueQi11R33W6qfJdMrkrsmSHirp5likR55JSXUrcWG6ybHA== dependencies: semver "^6.2.0" @@ -1663,13 +1677,13 @@ "@octokit/types" "^5.0.0" "@octokit/endpoint@^6.0.1": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.3.tgz#dd09b599662d7e1b66374a177ab620d8cdf73487" - integrity sha512-Y900+r0gIz+cWp6ytnkibbD95ucEzDSKzlEnaWS52hbCDNcCJYO5mRmWW7HRAnDc7am+N/5Lnd8MppSaTYx1Yg== + version "6.0.5" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.5.tgz#43a6adee813c5ffd2f719e20cfd14a1fee7c193a" + integrity sha512-70K5u6zd45ItOny6aHQAsea8HHQjlQq85yqOMe+Aj8dkhN2qSJ9T+Q3YjUjEYfPRBcuUWNgMn62DQnP/4LAIiQ== dependencies: "@octokit/types" "^5.0.0" - is-plain-object "^3.0.0" - universal-user-agent "^5.0.0" + is-plain-object "^4.0.0" + universal-user-agent "^6.0.0" "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" @@ -1715,18 +1729,18 @@ once "^1.4.0" "@octokit/request@^5.2.0": - version "5.4.5" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.5.tgz#8df65bd812047521f7e9db6ff118c06ba84ac10b" - integrity sha512-atAs5GAGbZedvJXXdjtKljin+e2SltEs48B3naJjqWupYl2IUBbB/CJisyjbNHcKpHzb3E+OYEZ46G8eakXgQg== + version "5.4.7" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.7.tgz#fd703ee092e0463ceba49ff7a3e61cb4cf8a0fde" + integrity sha512-FN22xUDP0i0uF38YMbOfx6TotpcENP5W8yJM1e/LieGXn6IoRxDMnBf7tx5RKSW4xuUZ/1P04NFZy5iY3Rax1A== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.0.0" "@octokit/types" "^5.0.0" deprecation "^2.0.0" - is-plain-object "^3.0.0" + is-plain-object "^4.0.0" node-fetch "^2.3.0" once "^1.4.0" - universal-user-agent "^5.0.0" + universal-user-agent "^6.0.0" "@octokit/rest@^16.28.4": version "16.43.2" @@ -1758,9 +1772,9 @@ "@types/node" ">= 8" "@octokit/types@^5.0.0", "@octokit/types@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.0.1.tgz#5459e9a5e9df8565dcc62c17a34491904d71971e" - integrity sha512-GorvORVwp244fGKEt3cgt/P+M0MGy4xEDbckw+K5ojEezxyMDgCaYPKVct+/eWQfZXOT7uq0xRpmrl/+hliabA== + version "5.1.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.1.0.tgz#4377a3f39edad3e60753fb5c3c310756f1ded57f" + integrity sha512-OFxUBgrEllAbdEmWp/wNmKIu5EuumKHG4sgy56vjZ8lXPgMhF05c76hmulfOdFHHYRpPj49ygOZJ8wgVsPecuA== dependencies: "@types/node" ">= 8" @@ -1882,15 +1896,20 @@ dependencies: execa "^0.2.2" +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "@sindresorhus/is@^0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== "@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.7.2": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" - integrity sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q== + version "1.8.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" + integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== dependencies: type-detect "4.0.8" @@ -1923,16 +1942,23 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== -"@theia/application-manager@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/application-manager/-/application-manager-1.4.0-next.64244a58.tgz#f47d2c8f0a3abca41d1fad1e027bf28f4474fd3d" - integrity sha512-i2uiuc3i86tNOkGuCAEi0qtj2UargYLudNdOdBkO3xOyTBjpf1ScaodEHcNTYOXAsoP6yuk7H6ZCup0wHH8Fbw== +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== dependencies: - "@babel/core" "^7.5.5" - "@babel/plugin-transform-classes" "^7.5.5" - "@babel/plugin-transform-runtime" "^7.5.5" - "@babel/preset-env" "^7.5.5" - "@theia/application-package" "1.4.0-next.64244a58" + defer-to-connect "^1.0.1" + +"@theia/application-manager@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/application-manager/-/application-manager-1.4.0-next.a833e50f.tgz#12ee76537717385f4445d33a16ffd6986ed31fd8" + integrity sha512-1ZepAAsyAm2bgsr1lAztWRhw5WVAQk/GuXuvEhA25/1guNIUmD0EqRZSsToCixq1KuMNlsdK+oCje0sgc5dTBw== + dependencies: + "@babel/core" "^7.10.0" + "@babel/plugin-transform-classes" "^7.10.0" + "@babel/plugin-transform-runtime" "^7.10.0" + "@babel/preset-env" "^7.10.0" + "@theia/application-package" "1.4.0-next.a833e50f" "@theia/compression-webpack-plugin" "^3.0.0" "@types/fs-extra" "^4.0.2" "@types/webpack" "^4.41.2" @@ -1955,10 +1981,10 @@ webpack-cli "2.0.12" worker-loader "^1.1.1" -"@theia/application-package@1.4.0-next.64244a58", "@theia/application-package@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/application-package/-/application-package-1.4.0-next.64244a58.tgz#2081ad862a8b47545c55bb1cfdc5519106dfd00d" - integrity sha512-A6vsaZ6cmvVc/4hAkzOPBcFx4obgfeMNoYvzynqptR59I91niSeBlDG63qYt9q0Pg1Xh7qd5jM2sQips1gWWpg== +"@theia/application-package@1.4.0-next.a833e50f", "@theia/application-package@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/application-package/-/application-package-1.4.0-next.a833e50f.tgz#85884a7bbe5ced4b44cf67041fd637546ab4782d" + integrity sha512-rqHVXEO1yLvcnr2oHmxGq/VcrzfbgDxwwj/0JO+tlImOUUhPrwkRVVPZA5CCm7L/KX3J/C80RCKDVSIkDdwToQ== dependencies: "@types/fs-extra" "^4.0.2" "@types/request" "^2.0.3" @@ -1971,24 +1997,24 @@ semver "^5.4.1" write-json-file "^2.2.0" -"@theia/callhierarchy@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/callhierarchy/-/callhierarchy-1.4.0-next.64244a58.tgz#4bc07c5e8322cfcbfecef172a6b76045c15089fd" - integrity sha512-0LZD9YRT7OcylZheP3L+jd0UB0opmT1YWp+DZeTJj0pm8vF2z8qvzTHeoCukmKJz5ko9Va/hROXFw0hPSrWn/w== +"@theia/callhierarchy@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/callhierarchy/-/callhierarchy-1.4.0-next.a833e50f.tgz#f9dd99a3f4bae1078e25239bf1bd3dd19f3d52c1" + integrity sha512-mARHkScrehVR8vobiizFd2ZfsIQ6rQVJ0TmNPe76K+7vqjrEpbe8OKcdtUB8f+KY2zn7UtzcXpDBncIhojT66g== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/languages" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/languages" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" ts-md5 "^1.2.2" "@theia/cli@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/cli/-/cli-1.4.0-next.64244a58.tgz#08662cdf14ec8892726c3a760ff71529b12e3c61" - integrity sha512-zQhcuONt8tqc6dCfCRlaigKrcptyiYFlAyN+kKH13ahY7e/SeYxh/3fQ8egX0CpMzodMmWZX1lhJxRbyghwvsg== + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/cli/-/cli-1.4.0-next.a833e50f.tgz#b06789d9dc2a78a8e31d97b3b78b4138d9ecc021" + integrity sha512-kbszlY3CsVd0swEV3Ed9IWXkFCvy0MTBW4dY9QnKCXZ9KMFDkaQl50zA6udQtbVHVtg7QdiH0oH4W6RQJDYmHQ== dependencies: - "@theia/application-manager" "1.4.0-next.64244a58" - "@theia/application-package" "1.4.0-next.64244a58" + "@theia/application-manager" "1.4.0-next.a833e50f" + "@theia/application-package" "1.4.0-next.a833e50f" "@types/chai" "^4.2.7" "@types/mkdirp" "^0.5.2" "@types/mocha" "^5.2.7" @@ -2006,6 +2032,7 @@ puppeteer "^2.0.0" puppeteer-to-istanbul "^1.2.2" tar "^4.0.0" + temp "^0.9.1" unzip-stream "^0.3.0" yargs "^11.1.0" @@ -2021,24 +2048,24 @@ serialize-javascript "^1.4.0" webpack-sources "^1.0.1" -"@theia/console@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/console/-/console-1.4.0-next.64244a58.tgz#dec754f90051cdf532515b8cb2194655381f3ea6" - integrity sha512-mmuD8FpkPbUmdgah4eiKGAPcY+jGzM+2LVJoX2PeBv/GPCvXbwHP+cXxhFhQ/4UG3h80m7QcUyCvqxiVk2lP/Q== +"@theia/console@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/console/-/console-1.4.0-next.a833e50f.tgz#a13de87470d3029bc6abb19973f5e4e2cea068e8" + integrity sha512-VZWqMdcS8c0dwyTPUpgd2XXE8N8sJZLFqCOivWAfZzSbsSChIbT3tBSdzZk8nXq1HGKZ+5E+wx/1EgJDDoDyvA== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" anser "^1.4.7" -"@theia/core@1.4.0-next.64244a58", "@theia/core@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/core/-/core-1.4.0-next.64244a58.tgz#065934d17bf05045bdc2114eab43d8a7940ec584" - integrity sha512-kiQxYW/HCxUX9N7JG1MS0ob84A8H8NgA9ypV5XHvY5q9+9UZZJaOrt//EK5/CE5giPzq7PQuIJ+E/mgd7GJ7bw== +"@theia/core@1.4.0-next.a833e50f", "@theia/core@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/core/-/core-1.4.0-next.a833e50f.tgz#7cfcbfdba2130aa1f2a9da17fb6a6402bb177ffb" + integrity sha512-o+9GQLlvxnGtyAAcaZMuPTQci5JkaxUutDuQ8VVbuA8qXUmea+N3AT1tqCGT4kxTfLp29xLQH8cNpwqcM8c//A== dependencies: - "@babel/runtime" "^7.5.5" + "@babel/runtime" "^7.10.0" "@phosphor/widgets" "^1.9.3" "@primer/octicons-react" "^9.0.0" - "@theia/application-package" "1.4.0-next.64244a58" + "@theia/application-package" "1.4.0-next.a833e50f" "@types/body-parser" "^1.16.4" "@types/cookie" "^0.3.3" "@types/express" "^4.16.0" @@ -2079,44 +2106,27 @@ ws "^7.1.2" yargs "^11.1.0" -"@theia/cpp@next": - version "1.1.0-next.184f7751" - resolved "https://registry.yarnpkg.com/@theia/cpp/-/cpp-1.1.0-next.184f7751.tgz#96c5ca20d24e1285599d2decfa425d1100f6c8e9" - integrity sha512-TAp0TS5YCUl1z3Avl7BrZF/LrZZmbbR+oMyeOwauVKkoc05k1+fKiH8qVVLeWPkvTmnAKfB/rVxVnmCKLE+O5w== +"@theia/debug@1.4.0-next.a833e50f", "@theia/debug@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/debug/-/debug-1.4.0-next.a833e50f.tgz#423cdb890ce37b19968edf7c9491102d0ed040d2" + integrity sha512-DxQwqAVEtB1Cqrj4Fzpuu83awFnd6ZvCMq4JqmVIslyIhvCDG8r9XgJpBF1/D4EDR917XdILfTNAZGrzueXTmA== dependencies: - "@theia/core" next - "@theia/editor" next - "@theia/filesystem" next - "@theia/languages" next - "@theia/monaco" next - "@theia/preferences" next - "@theia/process" next - "@theia/task" next - "@theia/variable-resolver" next - "@theia/workspace" next - string-argv "^0.1.1" - -"@theia/debug@1.4.0-next.64244a58", "@theia/debug@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/debug/-/debug-1.4.0-next.64244a58.tgz#94847388ae9c17fffdbe11c9d6ce34243e4a6088" - integrity sha512-yR1pnrI7xutvwqxvyrzE1FEncTg/F/OJas63GwRSapprPJiZr16baiW/ZFBiH9PTo5IVb3r2E+4Eu7FTpMSolw== - dependencies: - "@theia/application-package" "1.4.0-next.64244a58" - "@theia/console" "1.4.0-next.64244a58" - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/languages" "1.4.0-next.64244a58" - "@theia/markers" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" - "@theia/output" "1.4.0-next.64244a58" - "@theia/preferences" "1.4.0-next.64244a58" - "@theia/process" "1.4.0-next.64244a58" - "@theia/task" "1.4.0-next.64244a58" - "@theia/terminal" "1.4.0-next.64244a58" - "@theia/userstorage" "1.4.0-next.64244a58" - "@theia/variable-resolver" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/application-package" "1.4.0-next.a833e50f" + "@theia/console" "1.4.0-next.a833e50f" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/languages" "1.4.0-next.a833e50f" + "@theia/markers" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" + "@theia/output" "1.4.0-next.a833e50f" + "@theia/preferences" "1.4.0-next.a833e50f" + "@theia/process" "1.4.0-next.a833e50f" + "@theia/task" "1.4.0-next.a833e50f" + "@theia/terminal" "1.4.0-next.a833e50f" + "@theia/userstorage" "1.4.0-next.a833e50f" + "@theia/variable-resolver" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" jsonc-parser "^2.0.2" mkdirp "^0.5.0" p-debounce "^2.1.0" @@ -2125,51 +2135,51 @@ unzip-stream "^0.3.0" vscode-debugprotocol "^1.32.0" -"@theia/editor@1.4.0-next.64244a58", "@theia/editor@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/editor/-/editor-1.4.0-next.64244a58.tgz#87cf5aa42b746da807df193f467d3606025c1468" - integrity sha512-ZYWQJdV/nJSka9LokrzYABsk/aU8SYoerkZHhW5JmMuMcGuIVPUYliDgnIXQiS1ukT1dfSOWzxJK1EqlEw8PNg== +"@theia/editor@1.4.0-next.a833e50f", "@theia/editor@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/editor/-/editor-1.4.0-next.a833e50f.tgz#8b91fba223bcc077754124fb10fd272dec8fd031" + integrity sha512-nDgxpKj1NUcETfuxbHl7Q1U5I9au1N6WI1CEG/YWj/W4/Pr55AiWofPoj4CoHCn5gTXAIeY/Qh8qvjYx1ts1LQ== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/languages" "1.4.0-next.64244a58" - "@theia/variable-resolver" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/languages" "1.4.0-next.a833e50f" + "@theia/variable-resolver" "1.4.0-next.a833e50f" "@types/base64-arraybuffer" "0.1.0" base64-arraybuffer "^0.1.5" "@theia/electron@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/electron/-/electron-1.4.0-next.64244a58.tgz#b69f5ff5e16c5d01c17364d86e383591526e57c5" - integrity sha512-1gbS9C0ojr1ZWromyBeDQOco38Kt7P5FDfki/xUOTcWRZGmdLHIped9MYqsnAruFcSmuvcDRjN4YyE/o2aAOvA== + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/electron/-/electron-1.4.0-next.a833e50f.tgz#392dcf958a8df5c321fa59f75fb084ec908adabe" + integrity sha512-v63m8K9k/RiTaou6TSpjey6x4FZ2RwTSFGzeZH6+bXyo8T8Mn8+u3ePlrKFd4K2HSR5UczxsX1a5QM6MOJT6Bg== dependencies: - electron "^4.2.11" + electron "^9.0.2" electron-download "^4.1.1" - electron-store "^2.0.0" - fix-path "^2.1.0" - native-keymap "^1.2.5" + electron-store "^5.1.1" + fix-path "^3.0.0" + native-keymap "^2.1.2" node-gyp "^3.6.0" unzipper "^0.9.11" yargs "^11.1.0" -"@theia/file-search@1.4.0-next.64244a58", "@theia/file-search@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/file-search/-/file-search-1.4.0-next.64244a58.tgz#ce18cd4d5283340b18836e365a25390b0b9052ef" - integrity sha512-uXBOYKvgsY1jxUCqKZC/UEUnVHCKWoaHS2JhnjOElbQf5KHQEpeoLiajVqf0mKFU5N1WQrImZJBD/z9JQwHi6g== +"@theia/file-search@1.4.0-next.a833e50f", "@theia/file-search@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/file-search/-/file-search-1.4.0-next.a833e50f.tgz#7063948db7b52c3c4ecab762be3bae80a64e4e89" + integrity sha512-XE1Wv2HMcPBTFRtvYgqyP5UWEgv6OIPtauYwdDPywZfkXlXlR08IctsA8beV42Zdd8YWHZXQ7sxzog06uFjtIA== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/process" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/process" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" fuzzy "^0.1.3" vscode-ripgrep "^1.2.4" -"@theia/filesystem@1.4.0-next.64244a58", "@theia/filesystem@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/filesystem/-/filesystem-1.4.0-next.64244a58.tgz#ddf0906b8e0ef1e782297906dacac416940cb989" - integrity sha512-jaSVGF8rCOBJmV2WK+XwTcnIliS3vx7D08kk53X4BRwirP9PDOGoho7JSbIi6agpawO0bR3Tv3dOGYep+5YE0w== +"@theia/filesystem@1.4.0-next.a833e50f", "@theia/filesystem@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/filesystem/-/filesystem-1.4.0-next.a833e50f.tgz#9baf39cbba7e46ca2b6bea477a7645c61f7f4769" + integrity sha512-vvmQAeVai7cVkUg8PDssNC+miSDoCfhCYnrOxI4LA6vzRRwqo9suLjiDgT6rObQqYz7SYdOQZVWrOxXQflgg+w== dependencies: - "@theia/application-package" "1.4.0-next.64244a58" - "@theia/core" "1.4.0-next.64244a58" + "@theia/application-package" "1.4.0-next.a833e50f" + "@theia/core" "1.4.0-next.a833e50f" "@types/body-parser" "^1.17.0" "@types/rimraf" "^2.0.2" "@types/tar-fs" "^1.16.1" @@ -2190,59 +2200,59 @@ zip-dir "^1.0.2" "@theia/git@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/git/-/git-1.4.0-next.64244a58.tgz#430d00d67e96dff7827b89021c1c43acbe0c933c" - integrity sha512-UQZLAVl3R+F/TOA34I7QGGAf8JqOCUYQTigqm+c6dIL7JYDZCgBTjvnDGYKjpa1y6KXap++95ApNawHK9wLUKw== + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/git/-/git-1.4.0-next.a833e50f.tgz#dd9feaf763e41c55a3f8e3dc2be5cdd427258c25" + integrity sha512-wvag8UAmTvOwUuxJ2fzmcIzkLoHs4F+snyrtzOllwoIBATuDse1i1iHpw4eD4RKVAFhdBp/rUNfPCXKU30peCA== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/languages" "1.4.0-next.64244a58" - "@theia/navigator" "1.4.0-next.64244a58" - "@theia/scm" "1.4.0-next.64244a58" - "@theia/scm-extra" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/languages" "1.4.0-next.a833e50f" + "@theia/navigator" "1.4.0-next.a833e50f" + "@theia/scm" "1.4.0-next.a833e50f" + "@theia/scm-extra" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" "@types/diff" "^3.2.2" "@types/p-queue" "^2.3.1" diff "^3.4.0" - dugite-extra "0.1.12" - find-git-exec "^0.0.2" + dugite-extra "0.1.14" + find-git-exec "^0.0.3" find-git-repositories "^0.1.1" moment "2.24.0" octicons "^7.1.0" p-queue "^2.4.2" ts-md5 "^1.2.2" -"@theia/languages@1.4.0-next.64244a58", "@theia/languages@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/languages/-/languages-1.4.0-next.64244a58.tgz#a7d8e30f9ea50f2f663a621221da0ac0f92519ad" - integrity sha512-yqJoat1h9ZIPIkU/QpGfqDQob0EcESu9iYxJwwEfpMln5ThE38Qa+nMwvHnZGSY8UDE9yCJx65/ZzONmzSkseg== +"@theia/languages@1.4.0-next.a833e50f", "@theia/languages@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/languages/-/languages-1.4.0-next.a833e50f.tgz#553e235f02f39b60bacc9da19b4f4685398a5ecd" + integrity sha512-FYxK30WJIQ+IsuDpVFHiq5ewu1/ytEd+BjkBS5tgKZ0yKVJuEQGjZ44+rtYTprgVnNk0rI78BRdsUTZv0oRfkw== dependencies: - "@theia/application-package" "1.4.0-next.64244a58" - "@theia/core" "1.4.0-next.64244a58" + "@theia/application-package" "1.4.0-next.a833e50f" + "@theia/core" "1.4.0-next.a833e50f" "@theia/monaco-editor-core" "^0.19.3" - "@theia/process" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/process" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" "@types/uuid" "^7.0.3" monaco-languageclient "^0.13.0" uuid "^8.0.0" -"@theia/markers@1.4.0-next.64244a58", "@theia/markers@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/markers/-/markers-1.4.0-next.64244a58.tgz#8c028b86b05400900dd799707999519b8d4e52dc" - integrity sha512-r8m5mnaqZHdhbZ3elo177BwkYchmyBDbkmnkCb7uVcv2dROE/athw5kXRwWUODQD61EVtS8C+P5xHMzp12vBDw== +"@theia/markers@1.4.0-next.a833e50f", "@theia/markers@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/markers/-/markers-1.4.0-next.a833e50f.tgz#77102373cebeabf42b8a2199e7a91d84c020ef07" + integrity sha512-YUBbXvLt2i9C39n5q4tCZzjVtwvWIvFpPee258CwuPeFbi/CSBXlyVmEGS48zufrTIcAaV5+sQ/L7XmfhX3OAg== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/navigator" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/navigator" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" -"@theia/messages@1.4.0-next.64244a58", "@theia/messages@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/messages/-/messages-1.4.0-next.64244a58.tgz#4935de1a8e111d54b4bed1d9c381d0eb7fe73643" - integrity sha512-LyG2iane3OG3b2IqBgSPTGEo9B6ivSDBZ0DWojNoHweAN47Hskp3xQ4ojZmby0R5Xc+OKHPwF4lhk6Eodr/u1A== +"@theia/messages@1.4.0-next.a833e50f", "@theia/messages@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/messages/-/messages-1.4.0-next.a833e50f.tgz#fe27de7fee3fadbe8fec9624a3b7dbbd3a536bc4" + integrity sha512-EyQlPfGUUXbcCtBvrl5vQrNbgdN+V3EymsiyAaA7WHIlJuKzproroNqBhvxSYVh4p63URaKVQ66ALmAYQ7syMA== dependencies: - "@theia/core" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" lodash.throttle "^4.1.1" markdown-it "^8.4.0" react-perfect-scrollbar "^1.5.3" @@ -2253,18 +2263,18 @@ resolved "https://registry.yarnpkg.com/@theia/monaco-editor-core/-/monaco-editor-core-0.19.3.tgz#8456aaa52f4cdc87c78697a0edfcccb9696a374d" integrity sha512-+2I5pvbK9qxWs+bLFUwto8nYubyI759/p0z86r2w0HnFdcMQ6rcqvcTupO/Cd/YAJ1/IU38PBWS7hwIoVnvCsQ== -"@theia/monaco@1.4.0-next.64244a58", "@theia/monaco@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/monaco/-/monaco-1.4.0-next.64244a58.tgz#81c4843ba9ef6547a41b5f531bd4660e0618ebfb" - integrity sha512-vLcjxqObq9gMdnT/T1GPb/5JEiHUxcjcklHFfKzByoCvjLh6K+3MYewn8zXDWtgc8oqmoZ1d7xbPfB6AQUVdBA== +"@theia/monaco@1.4.0-next.a833e50f", "@theia/monaco@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/monaco/-/monaco-1.4.0-next.a833e50f.tgz#57af5f8084d4278aa27ffc7688caed6fc3e279cd" + integrity sha512-XMRhoErRR921aNFDZtwfG9hNpAwiIm8yMoyLglym93V3+NoepATk0LOAzXekBLT3id3R+mbl/7B7JEphNPhnKQ== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/languages" "1.4.0-next.64244a58" - "@theia/markers" "1.4.0-next.64244a58" - "@theia/outline-view" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/languages" "1.4.0-next.a833e50f" + "@theia/markers" "1.4.0-next.a833e50f" + "@theia/outline-view" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" deepmerge "2.0.1" fast-plist "^0.1.2" idb "^4.0.5" @@ -2272,14 +2282,14 @@ onigasm "^2.2.0" vscode-textmate "^4.0.1" -"@theia/navigator@1.4.0-next.64244a58", "@theia/navigator@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/navigator/-/navigator-1.4.0-next.64244a58.tgz#9452f2952eba55f11274a76bc21cd2b46650eb12" - integrity sha512-v3FET/31jbV/GSKoCRdKiJE4Az/VcIpAyH03V/kkLRz3zn4FAeNylAM550VbXHPZfWkjPXJ/JhnPQD5jDUh3hA== +"@theia/navigator@1.4.0-next.a833e50f", "@theia/navigator@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/navigator/-/navigator-1.4.0-next.a833e50f.tgz#51aa3ad0b3c910933e4ac0534d84d5d429fc0a0a" + integrity sha512-mB9yC9Unxxt82pEAkVp35G0xpIkwm/ulAwPOF4qcgLZ53x3/rP1RQVaBRfUs0mVkN3B2aFKZ0a3C3fAmVWUKlQ== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" fuzzy "^0.1.3" minimatch "^3.0.4" @@ -2290,63 +2300,63 @@ dependencies: nan "^2.14.0" -"@theia/outline-view@1.4.0-next.64244a58", "@theia/outline-view@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/outline-view/-/outline-view-1.4.0-next.64244a58.tgz#e181dd73f80eb0b5c72ed811d76e4c3bc9541c95" - integrity sha512-6r6580iiwNFsm3X4PD2/mzl6aB9sHDZno3jd9kFWMDQ8P7OvC+qqMw2ib2SYWopLPqx+kpBFbZCctZXTT1DKKA== +"@theia/outline-view@1.4.0-next.a833e50f", "@theia/outline-view@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/outline-view/-/outline-view-1.4.0-next.a833e50f.tgz#cfc7e3f7c61a192975a013877344bd44e7ae8cc8" + integrity sha512-PIQPUW0gOI4ghbSQl9BQ7xcqzNaQXZzxdaFuHYa+FxzQ0KwE641fqDs76PPMxGE+J159HyxHnh3ZF3Wf3Pbybg== dependencies: - "@theia/core" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" -"@theia/output@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/output/-/output-1.4.0-next.64244a58.tgz#b3772710befb61de6fbcd07ab81915824a4927db" - integrity sha512-X1HQklw3SbTsn9ZcJG76rrbK9GUyiLujj3JJCXxyKbhU9njQN9lwX95fu1T/jCHt8vKnYQPvR4tr6c4ssM9DXg== +"@theia/output@1.4.0-next.a833e50f", "@theia/output@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/output/-/output-1.4.0-next.a833e50f.tgz#d38b09117740dd954b57e953ef91813a3c7c7a3d" + integrity sha512-Iw1y0b+0Uourd/PhtV27ehAPc2/iML3lxVIdxXd57o9JCzmBq4ceFZ1EhzbLh6rvFIpRFtz3FedfMbLX0LgsCg== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" "@types/p-queue" "^2.3.1" p-queue "^2.4.2" "@theia/plugin-ext-vscode@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/plugin-ext-vscode/-/plugin-ext-vscode-1.4.0-next.64244a58.tgz#60df37e3cc731e799af3de4b5bbc9eed849656fc" - integrity sha512-BQVIKVavS9XXdXr86t+o5ABX7hz+SmTQqb1Bxpab0cbsKbRSJyhuqV72He9E4WD8kX/oc8/4dinLKhmIkun9yA== + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/plugin-ext-vscode/-/plugin-ext-vscode-1.4.0-next.a833e50f.tgz#0fc53e3d0a7f3c841617c7b8596cced0e48a6fd6" + integrity sha512-fOrmUsZD73kADQzsUSU5K4veDZ/2WVeFTBFYMuULXbhxGodEi2VKFDYmraZ/2jleiGg/4YFhkKE9mn8ZmNcJIg== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" - "@theia/plugin" "1.4.0-next.64244a58" - "@theia/plugin-ext" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" + "@theia/plugin" "1.4.0-next.a833e50f" + "@theia/plugin-ext" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" "@types/request" "^2.0.3" filenamify "^4.1.0" request "^2.82.0" -"@theia/plugin-ext@1.4.0-next.64244a58", "@theia/plugin-ext@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/plugin-ext/-/plugin-ext-1.4.0-next.64244a58.tgz#2565d1aa44f6924b87b9ec38fa88a462122b3f1e" - integrity sha512-blPalYFPwcJD84QJr0Ce9nc/XKcEl9qrLIM6JGQ6LbPOcHmF0WeHOfgR6DudiVbHMLc5r2tIyAgrBgyf4WqbPA== +"@theia/plugin-ext@1.4.0-next.a833e50f", "@theia/plugin-ext@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/plugin-ext/-/plugin-ext-1.4.0-next.a833e50f.tgz#1e02ce2aef301f80d1b92170a63e5020abd41049" + integrity sha512-NtEDz6Bzxp32e7F90iFd9iRnBqOkFxSnG4HKYorFPrusedBw5KctMguyFKmAjE4j/SuFOhZtF65Zb7KzRiYF5A== dependencies: - "@theia/callhierarchy" "1.4.0-next.64244a58" - "@theia/core" "1.4.0-next.64244a58" - "@theia/debug" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/file-search" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/languages" "1.4.0-next.64244a58" - "@theia/markers" "1.4.0-next.64244a58" - "@theia/messages" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" - "@theia/navigator" "1.4.0-next.64244a58" - "@theia/output" "1.4.0-next.64244a58" - "@theia/plugin" "1.4.0-next.64244a58" - "@theia/preferences" "1.4.0-next.64244a58" - "@theia/scm" "1.4.0-next.64244a58" - "@theia/search-in-workspace" "1.4.0-next.64244a58" - "@theia/task" "1.4.0-next.64244a58" - "@theia/terminal" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/callhierarchy" "1.4.0-next.a833e50f" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/debug" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/file-search" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/languages" "1.4.0-next.a833e50f" + "@theia/markers" "1.4.0-next.a833e50f" + "@theia/messages" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" + "@theia/navigator" "1.4.0-next.a833e50f" + "@theia/output" "1.4.0-next.a833e50f" + "@theia/plugin" "1.4.0-next.a833e50f" + "@theia/preferences" "1.4.0-next.a833e50f" + "@theia/scm" "1.4.0-next.a833e50f" + "@theia/search-in-workspace" "1.4.0-next.a833e50f" + "@theia/task" "1.4.0-next.a833e50f" + "@theia/terminal" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" "@types/connect" "^3.4.32" "@types/mime" "^2.0.1" "@types/serve-static" "^1.13.3" @@ -2366,128 +2376,128 @@ vscode-debugprotocol "^1.32.0" vscode-textmate "^4.0.1" -"@theia/plugin@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/plugin/-/plugin-1.4.0-next.64244a58.tgz#e695e7a8b2f86ebcaaa04679056f108d860d3fef" - integrity sha512-qBkL2oCZ4/GxyOQo70s3tTz2ABGsGj6ZsT9h8WODWJpqwxbvXaaoXVnjz+oJHpBHl2nz5La4WAku/I5wwc59gA== +"@theia/plugin@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/plugin/-/plugin-1.4.0-next.a833e50f.tgz#25fc626d12fcbad97a5b1d81cebf3051875e8d2f" + integrity sha512-Rfnp92nXOw0NABO4IM4nN2qOo5510CEaD9C4U4FXtLgjTxol3AVcyaLdF0fUencQz2/aM9ayzrOB2fGQPtvGWA== -"@theia/preferences@1.4.0-next.64244a58", "@theia/preferences@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/preferences/-/preferences-1.4.0-next.64244a58.tgz#8d6dfef41f433ec4113bdb9fd0331143e5ce3365" - integrity sha512-eGXViUiXE/ObleOA0uXM/mTsqWXrDMMvD9yJ1oDqA3A3mxBD866SSCNfhxZQ4VKHQakJFQECHnUxcEvK8e7jjQ== +"@theia/preferences@1.4.0-next.a833e50f", "@theia/preferences@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/preferences/-/preferences-1.4.0-next.a833e50f.tgz#5e2e3b98a09064961616a75291a21f262f75f3d1" + integrity sha512-svwqOfJVTsa+t96I2CC/dxv8Af/jyET0IQypieNr5BdK9YTcHTaGGQlMiQIEVS5ZV0Vs102FOINTP/Iwmq/fdg== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" - "@theia/userstorage" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" + "@theia/userstorage" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" jsonc-parser "^2.0.2" -"@theia/process@1.4.0-next.64244a58", "@theia/process@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/process/-/process-1.4.0-next.64244a58.tgz#8498077f346448a74bfc8696b937481d4daf055b" - integrity sha512-IHNyfeA1XUKoKyFIsCyqCj73MTMp9EJyZSLaq5/8MBLZGu4IFne5SmMHIbeSkCnn9LQ+yt+AL7zVRjg6vLK0NQ== +"@theia/process@1.4.0-next.a833e50f", "@theia/process@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/process/-/process-1.4.0-next.a833e50f.tgz#716522b92f9c4ed0afcbdff3939b035c8a903907" + integrity sha512-oz+jLYoWCg0vsJPMOlNF8yaqdcFGhURZYSB8WSfiLOmDEZMZswv+mLB2u9/t1zndWUkZbClvHup1f4tqyS1qZw== dependencies: - "@theia/core" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" "@theia/node-pty" "0.9.0-theia.6" string-argv "^0.1.1" -"@theia/scm-extra@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/scm-extra/-/scm-extra-1.4.0-next.64244a58.tgz#de73dcf2208d3d00ed9e09528c72fdc5cfe45943" - integrity sha512-KHUziQ43xH25GxEgSMFuh+fdCFOAazy7MbRvtYUKO9E14SM4SSz6ZtpHs7yEl/XNe4TXhZftu2oDDK6G/CxwFw== +"@theia/scm-extra@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/scm-extra/-/scm-extra-1.4.0-next.a833e50f.tgz#fda02a294b8750a7895f8551f4ce27240435b18a" + integrity sha512-LpUCujGLwHqEPQiQj6KK9OICVCpAdPC9NBGqqSL0zmCweyAptdCWISAdmlP58bxYzWWyATgLMnz4uKM69Intzw== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/navigator" "1.4.0-next.64244a58" - "@theia/scm" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/navigator" "1.4.0-next.a833e50f" + "@theia/scm" "1.4.0-next.a833e50f" -"@theia/scm@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/scm/-/scm-1.4.0-next.64244a58.tgz#6cbdc8a0a9c20d434cd00e9f17f0bfb5ef9093cd" - integrity sha512-kVmt6z41PMcxf5MuTBYJwBkY37+l4ZPrc58Du5xYShk7hjz+WAKrYOKIVPhZMHZpQgV6P/CNzE0wSrHQl4DKZQ== +"@theia/scm@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/scm/-/scm-1.4.0-next.a833e50f.tgz#e84d9d1091df830e7145f15483668434a3cdabeb" + integrity sha512-I1N344mivjKMB6ATe0EvUQ65jr0VrMwwKrCc49Zbkd/Lr8Qg6icCP9VQV5iQw8fb7a5u2AU3LYfRCPWdYAG4yw== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/navigator" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/navigator" "1.4.0-next.a833e50f" "@types/diff" "^3.2.2" diff "^3.4.0" p-debounce "^2.1.0" react-autosize-textarea "^7.0.0" ts-md5 "^1.2.2" -"@theia/search-in-workspace@1.4.0-next.64244a58", "@theia/search-in-workspace@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/search-in-workspace/-/search-in-workspace-1.4.0-next.64244a58.tgz#299edfed50a0a7ce6da4465714a1de0b32f218de" - integrity sha512-C/G8FxMijys0rVgBs0DAu9Fhm5HLBKZgl7C3Sd1aaiCWwF5krXy5qMzXNyYwVxFW/14Zme6MFSKxtNdVthTvKw== +"@theia/search-in-workspace@1.4.0-next.a833e50f", "@theia/search-in-workspace@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/search-in-workspace/-/search-in-workspace-1.4.0-next.a833e50f.tgz#dc15c9d7f64b1e4cf3b5dac32661f72deb39fdcc" + integrity sha512-YeCHgbJxRo/XE24mJd828wyRTPLr44LsDDF2HjOHEd9aXsvoPyP70KqFMOBDlpRY4A/2mqRRGwSGnh4oTU5NaA== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/navigator" "1.4.0-next.64244a58" - "@theia/process" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/navigator" "1.4.0-next.a833e50f" + "@theia/process" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" vscode-ripgrep "^1.2.4" -"@theia/task@1.4.0-next.64244a58", "@theia/task@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/task/-/task-1.4.0-next.64244a58.tgz#3ca46a71a395a98bcf93638693aea96dfd50796f" - integrity sha512-Lc9gV4un6YSMjQENSbCVN4k8ddq8tWRo/PTkSKHNpWIBRt7pP76ExehDm/unzhNADEwUX4/piPINH8W0TJ+zmQ== +"@theia/task@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/task/-/task-1.4.0-next.a833e50f.tgz#4a72433c08cd20a1f92b2ff29421db9786318550" + integrity sha512-nCC5qjoKv/FRbxoK+97TKDo5ixaNj0xpWdm7oKvfLbg+fzX4vhbw+4rkjbU9/BiLiBc0Vz1vNWHeSWB54zALhw== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/markers" "1.4.0-next.64244a58" - "@theia/monaco" "1.4.0-next.64244a58" - "@theia/preferences" "1.4.0-next.64244a58" - "@theia/process" "1.4.0-next.64244a58" - "@theia/terminal" "1.4.0-next.64244a58" - "@theia/variable-resolver" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/markers" "1.4.0-next.a833e50f" + "@theia/monaco" "1.4.0-next.a833e50f" + "@theia/preferences" "1.4.0-next.a833e50f" + "@theia/process" "1.4.0-next.a833e50f" + "@theia/terminal" "1.4.0-next.a833e50f" + "@theia/variable-resolver" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" ajv "^6.5.3" jsonc-parser "^2.0.2" p-debounce "^2.1.0" -"@theia/terminal@1.4.0-next.64244a58", "@theia/terminal@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/terminal/-/terminal-1.4.0-next.64244a58.tgz#625c94797248bfe5ad23478e155a42ba4ceaa442" - integrity sha512-11J/JPZpjhOpj/utG4hgZMvsSPLVUR+c3Y9yapxnCz/W4hgut8GVHej4sKh+m5TMz+9YIBKrUGBMluPlLI+75w== +"@theia/terminal@1.4.0-next.a833e50f", "@theia/terminal@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/terminal/-/terminal-1.4.0-next.a833e50f.tgz#0e96407417d65873ada95b7525909c00da4f66bc" + integrity sha512-BVdCC4BVffOgG9L7v5gleQJHQ7Beg+aqJ4AgSsYuSD7DDk8lzmd9khBPGNVas8OnKBdPEIeRIYdd7HexbuOcAA== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/editor" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/process" "1.4.0-next.64244a58" - "@theia/workspace" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/editor" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/process" "1.4.0-next.a833e50f" + "@theia/workspace" "1.4.0-next.a833e50f" xterm "^4.4.0" xterm-addon-fit "^0.3.0" xterm-addon-search "^0.5.0" -"@theia/userstorage@1.4.0-next.64244a58": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/userstorage/-/userstorage-1.4.0-next.64244a58.tgz#7ecf72a4d9da9107c8201038e4090d9813f15b67" - integrity sha512-+yt6o/u101BTqRovfovKHLks0qx4qtp9c4nnBJ37uNNLjBepZLNCxA1GxZZflOzU7yO/iONFn3A48AriYHMBPA== +"@theia/userstorage@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/userstorage/-/userstorage-1.4.0-next.a833e50f.tgz#e7ce18fb9e355801372f1826e118b48bf5ba61cc" + integrity sha512-jQj2/l7KEvFV3IUu840qhztx5JT3JsH5WPnxmzsyCiLdFdiOWuQyvQ3hCty7QDaJt6SJXuAh7Qx/qNyqesuGNg== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" -"@theia/variable-resolver@1.4.0-next.64244a58", "@theia/variable-resolver@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/variable-resolver/-/variable-resolver-1.4.0-next.64244a58.tgz#c37d79094c2ff82b366367b56a51473a8f4077b6" - integrity sha512-UQEsfQQZZT8g7pid+d2ako1xUAmi6fskI01LmhPzAz/i0P40BsWc1f4uSclmPYqJDIYuUjj/WEDKEvjN6buCJA== +"@theia/variable-resolver@1.4.0-next.a833e50f": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/variable-resolver/-/variable-resolver-1.4.0-next.a833e50f.tgz#454ea2d045416278865d4898b7b437e6d27f74e0" + integrity sha512-Heupaiepr4x6/fwK2WVD6zxSrXFfpaksiIULoMbNCjzYK7wZQ+TVdOsYuxsAFGydr2StHOywikZEh7nI7PnVFQ== dependencies: - "@theia/core" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" -"@theia/workspace@1.4.0-next.64244a58", "@theia/workspace@next": - version "1.4.0-next.64244a58" - resolved "https://registry.yarnpkg.com/@theia/workspace/-/workspace-1.4.0-next.64244a58.tgz#b53d553386edd5a4e2387baafc0e63aca664a977" - integrity sha512-eewgizmxiYdBdwjLtSwQpV6+XQ0Z5g9SIGlOmPo1q1doIQkgXrKub9qn0FEqU8S9jV7dG1EZwMSjCUcU0rA/Ag== +"@theia/workspace@1.4.0-next.a833e50f", "@theia/workspace@next": + version "1.4.0-next.a833e50f" + resolved "https://registry.yarnpkg.com/@theia/workspace/-/workspace-1.4.0-next.a833e50f.tgz#810ac9e922df51c6a9946fe335e729274df425c1" + integrity sha512-eXIwkqmnO64JG1JqcE2cNdfO0Z11+dN6MGvDem8mY6FUDOLF92K2QAI7h+z4MaK5j+2PyqGvp8NL3ow5+aq31A== dependencies: - "@theia/core" "1.4.0-next.64244a58" - "@theia/filesystem" "1.4.0-next.64244a58" - "@theia/variable-resolver" "1.4.0-next.64244a58" + "@theia/core" "1.4.0-next.a833e50f" + "@theia/filesystem" "1.4.0-next.a833e50f" + "@theia/variable-resolver" "1.4.0-next.a833e50f" ajv "^6.5.3" jsonc-parser "^2.0.2" moment "2.24.0" @@ -2577,9 +2587,9 @@ "@types/range-parser" "*" "@types/express@^4.16.0": - version "4.17.6" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.6.tgz#6bce49e49570507b86ea1b07b806f04697fac45e" - integrity sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w== + version "4.17.7" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59" + integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "*" @@ -2594,9 +2604,9 @@ "@types/node" "*" "@types/glob@*", "@types/glob@^7.1.1": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987" - integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA== + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" + integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== dependencies: "@types/minimatch" "*" "@types/node" "*" @@ -2647,9 +2657,9 @@ "@types/lodash" "*" "@types/lodash@*": - version "4.14.157" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.157.tgz#fdac1c52448861dfde1a2e1515dbc46e54926dc8" - integrity sha512-Ft5BNFmv2pHDgxV5JDsndOWTRJ+56zte0ZpYLowp03tW+K+t8u8YMOzAnpuqPgzX6WO1XpDIUm7u04M8vdDiVQ== + version "4.14.158" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.158.tgz#b38ea8b6fe799acd076d7a8d7ab71c26ef77f785" + integrity sha512-InCEXJNTv/59yO4VSfuvNrZHt7eeNtWQEgnieIA+mIC+MOWM9arOWG2eQ8Vhk6NbOre6/BidiXhkZYeDY9U35w== "@types/mime-types@^2.1.0": version "2.1.0" @@ -2690,6 +2700,13 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== +"@types/ncp@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/ncp/-/ncp-2.0.4.tgz#16c9e7fa2c849d429a1b142648987164b06bf490" + integrity sha512-erpimpT1pH8QfeNg77ypnjwz6CGMqrnL4DewVbqFzD9FXzSULjmG3KzjZnLNe7bzTSZm2W9DpkHyqop1g1KmgQ== + dependencies: + "@types/node" "*" + "@types/node-fetch@^2.5.7": version "2.5.7" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" @@ -2699,14 +2716,19 @@ form-data "^3.0.0" "@types/node@*", "@types/node@>= 8": - version "14.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" - integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ== + version "14.0.24" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.24.tgz#b0f86f58564fa02a28b68f8b55d4cdec42e3b9d6" + integrity sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA== -"@types/node@^10.12.18", "@types/node@^10.14.22": - version "10.17.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.26.tgz#a8a119960bff16b823be4c617da028570779bcfd" - integrity sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw== +"@types/node@^10.14.22": + version "10.17.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.27.tgz#391cb391c75646c8ad2a7b6ed3bbcee52d1bdf19" + integrity sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg== + +"@types/node@^12.0.12": + version "12.12.51" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.51.tgz#446a67af8c5ff98947d7cef296484c6ad47ddb16" + integrity sha512-6ILqt8iNThALrxDv2Q4LyYFQxULQz96HKNIFd4s9QRQaiHINYeUpLqeU/2IU7YMtvipG1fQVAy//vY8/fX1Y9w== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2782,9 +2804,9 @@ "@types/react" "*" "@types/react@*", "@types/react@^16.8.0": - version "16.9.41" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.41.tgz#925137ee4d2ff406a0ecf29e8e9237390844002e" - integrity sha512-6cFei7F7L4wwuM+IND/Q2cV1koQUvJ8iSV+Gwn0c3kvABZ691g7sp3hfEQHOUBJtccl1gPi+EyNjMIl9nGA0ug== + version "16.9.43" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" + integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -2889,9 +2911,9 @@ integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== "@types/uglify-js@*": - version "3.9.2" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.2.tgz#01992579debba674e1e359cd6bcb1a1d0ab2e02b" - integrity sha512-d6dIfpPbF+8B7WiCi2ELY7m0w1joD8cRW4ms88Emdb2w062NeEpbNCeWwVCgzLRpVG+5e74VFSg4rgJ2xXjEiQ== + version "3.9.3" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.3.tgz#d94ed608e295bc5424c9600e6b8565407b6b4b6b" + integrity sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w== dependencies: source-map "^0.6.1" @@ -2910,9 +2932,9 @@ source-map "^0.7.3" "@types/webpack@^4.41.2": - version "4.41.18" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.18.tgz#2945202617866ecdffa582087f1b6de04a7eed55" - integrity sha512-mQm2R8vV2BZE/qIDVYqmBVLfX73a8muwjs74SpjEyJWJxeXBbsI9L65Pcia9XfYLYWzD1c1V8m+L0p30y2N7MA== + version "4.41.21" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.21.tgz#cc685b332c33f153bb2f5fc1fa3ac8adeb592dee" + integrity sha512-2j9WVnNrr/8PLAB5csW44xzQSJwS26aOnICsP3pSGCEdsu6KYtfQ6QJsVUKHWRnm1bL7HziJsfh5fHqth87yKA== dependencies: "@types/anymatch" "*" "@types/node" "*" @@ -3147,9 +3169,9 @@ agent-base@5: integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== agent-base@6: - version "6.0.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a" - integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw== + version "6.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" + integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== dependencies: debug "4" @@ -3173,14 +3195,14 @@ ajv-errors@^1.0.0: integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.0.tgz#5c894537098785926d71e696114a53ce768ed773" - integrity sha512-eyoaac3btgU8eJlvh01En8OCKzRqlLe2G5jDsCr3RiE2uLGMEEB1aaGwVVpwR8M95956tGH6R+9edC++OvzaVw== + version "3.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.1.tgz#b83ca89c5d42d69031f424cad49aada0236c6957" + integrity sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA== ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.5.3, ajv@^6.5.5: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -3640,7 +3662,7 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -asap@^2.0.0, asap@~2.0.3: +asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -4644,6 +4666,11 @@ body-parser@1.19.0, body-parser@^1.17.2, body-parser@^1.18.3: raw-body "2.4.0" type-is "~1.6.17" +boolean@^3.0.0, boolean@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.1.tgz#35ecf2b4a2ee191b0b44986f14eb5f052a5cbb4f" + integrity sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -4764,12 +4791,12 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: electron-to-chromium "^1.2.7" browserslist@^4.12.0, browserslist@^4.8.5: - version "4.12.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.2.tgz#76653d7e4c57caa8a1a28513e2f4e197dc11a711" - integrity sha512-MfZaeYqR8StRZdstAK9hCKDd2StvePCYp5rHzQCPicUjfFliDgmuaBNPHYUTpAywBN8+Wc/d7NYVFkO0aqaBUw== + version "4.13.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" + integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== dependencies: - caniuse-lite "^1.0.30001088" - electron-to-chromium "^1.3.483" + caniuse-lite "^1.0.30001093" + electron-to-chromium "^1.3.488" escalade "^3.0.1" node-releases "^1.1.58" @@ -4956,6 +4983,19 @@ cacheable-request@^2.1.1: normalize-url "2.0.1" responselike "1.0.2" +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -5042,14 +5082,14 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30001093" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001093.tgz#5a1cae72d94df1156f40f15d9079456e1b29d050" - integrity sha512-XqXxHR6Z9IN0BXLKMaTJ1NZ+US74cbKritholD6uaDLUWHiDj0QilpSb708wOcoGz0PmPRsXT/6zE+bjx+QSMw== + version "1.0.30001105" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001105.tgz#5cc03239a9d4540b3fa9a1dc8b5e3bda50226e96" + integrity sha512-GZytZn8lOiru/Tw+/X5sFxrFt2uPdSvkxVKzRMJyX20JGwfwOuTiRg5IMVF9II8Lao/7C4YeHR8YnZzpTvYXdQ== -caniuse-lite@^1.0.30001088: - version "1.0.30001093" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001093.tgz#833e80f64b1a0455cbceed2a4a3baf19e4abd312" - integrity sha512-0+ODNoOjtWD5eS9aaIpf4K0gQqZfILNY4WSNuYzeT1sXni+lMrrVjc0odEobJt6wrODofDZUX8XYi/5y7+xl8g== +caniuse-lite@^1.0.30001093: + version "1.0.30001105" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001105.tgz#d2cb0b31e5cf2f3ce845033b61c5c01566549abf" + integrity sha512-JupOe6+dGMr7E20siZHIZQwYqrllxotAhiaej96y6x00b/48rPt42o+SzOSCPbrpsDWvRja40Hwrj0g0q6LZJg== capture-stack-trace@^1.0.0: version "1.0.1" @@ -5208,9 +5248,9 @@ chokidar@^2.1.8: fsevents "^1.2.7" chokidar@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== + version "3.4.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" + integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -5296,9 +5336,9 @@ cli-spinners@^0.1.2: integrity sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw= cli-spinners@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5" - integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w== + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== cli-table@^0.3.1: version "0.3.1" @@ -5366,7 +5406,7 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone-response@1.0.2: +clone-response@1.0.2, clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= @@ -5568,16 +5608,21 @@ concat-with-sourcemaps@*: dependencies: source-map "^0.6.1" -conf@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/conf/-/conf-2.2.0.tgz#ee282efafc1450b61e205372041ad7d866802d9a" - integrity sha512-93Kz74FOMo6aWRVpAZsonOdl2I57jKtHrNmxhumehFQw4X8Sk37SohNY11PG7Q8Okta+UnrVaI006WLeyp8/XA== +conf@^6.2.1: + version "6.2.4" + resolved "https://registry.yarnpkg.com/conf/-/conf-6.2.4.tgz#49d23c4e21ef2ac2860f7b5ed25b7b7e484f769f" + integrity sha512-GjgyPRLo1qK1LR9RWAdUagqo+DP18f5HWCFk4va7GS+wpxQTOzfuKTwKOvGW2c01/YXNicAyyoyuSddmdkBzZQ== dependencies: - dot-prop "^4.1.0" - env-paths "^1.0.0" - make-dir "^1.0.0" - pkg-up "^2.0.0" - write-file-atomic "^2.3.0" + ajv "^6.10.2" + debounce-fn "^3.0.1" + dot-prop "^5.0.0" + env-paths "^2.2.0" + json-schema-typed "^7.0.1" + make-dir "^3.0.0" + onetime "^5.1.0" + pkg-up "^3.0.1" + semver "^6.2.0" + write-file-atomic "^3.0.0" config-chain@^1.1.11: version "1.1.12" @@ -5773,6 +5818,11 @@ core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== +core-js@^3.6.5: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -5956,13 +6006,12 @@ css-loader@~0.26.1: source-list-map "^0.1.7" css-selector-tokenizer@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.2.tgz#11e5e27c9a48d90284f22d45061c303d7a25ad87" - integrity sha512-yj856NGuAymN6r8bn8/Jl46pR+OC3eEvAhfGYDUe7YPtTPAYrSSw4oAniZ9Y8T5B92hjhwTBLUen0/vKPxf6pw== + version "0.7.3" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1" + integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg== dependencies: cssesc "^3.0.0" fastparse "^1.1.2" - regexpu-core "^4.6.0" cssesc@^3.0.0: version "3.0.0" @@ -6073,6 +6122,13 @@ dateformat@^3.0.0, dateformat@^3.0.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +debounce-fn@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-3.0.1.tgz#034afe8b904d985d1ec1aa589cd15f388741d680" + integrity sha512-aBoJh5AhpqlRoHZjHmOzZlRx+wz2xVwGL9rjs+Kj0EWUrL4/h4K7OD176thl2Tdoqui/AaA4xhHrNArGLAaI3Q== + dependencies: + mimic-fn "^2.1.0" + debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.5.1, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -6249,6 +6305,11 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -6338,6 +6399,11 @@ detect-libc@^1.0.2, detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-node@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" + integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -6400,13 +6466,20 @@ dot-prop@^3.0.0: dependencies: is-obj "^1.0.0" -dot-prop@^4.1.0, dot-prop@^4.2.0: +dot-prop@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== dependencies: is-obj "^1.0.0" +dot-prop@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + dependencies: + is-obj "^2.0.0" + download-stats@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/download-stats/-/download-stats-0.3.4.tgz#67ea0c32f14acd9f639da704eef509684ba2dae7" @@ -6445,14 +6518,14 @@ drivelist@^6.4.3: nan "^2.10.0" prebuild-install "^4.0.0" -dugite-extra@0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/dugite-extra/-/dugite-extra-0.1.12.tgz#fc2f5e2fb288e688aaec7a770a24a21293831175" - integrity sha512-bYcOoa1l1HqD23lfUJIctrL/DSYIdj1JUD9gNdQB+Y3albl67G1HZsGQueoT/sNE7ijr7pGxOI7NmKtoe5zJjA== +dugite-extra@0.1.14: + version "0.1.14" + resolved "https://registry.yarnpkg.com/dugite-extra/-/dugite-extra-0.1.14.tgz#514c89b6c597bf8b748b4febd53382559a2a8fdd" + integrity sha512-apUiaj322iSSBx5X7/8Dg3GP6mDLl5y6RaeEWBpLUHfBKxQyTTVHG0YpzYCKe2ke1EbrSmreVNo1FwDnIb3qlw== dependencies: byline "^5.0.0" dugite-no-gpl "1.69.0" - find-git-exec "^0.0.2" + find-git-exec "^0.0.3" upath "^1.0.0" dugite-no-gpl@1.69.0: @@ -6527,7 +6600,7 @@ ejs@^3.0.1: dependencies: jake "^10.6.1" -electron-download@^4.1.0, electron-download@^4.1.1: +electron-download@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg== @@ -6557,25 +6630,26 @@ electron-rebuild@^1.8.6: spawn-rx "^3.0.0" yargs "^14.2.0" -electron-store@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-2.0.0.tgz#1035cca2a95409d1f54c7466606345852450d64a" - integrity sha512-1WCFYHsYvZBqDsoaS0Relnz0rd81ZkBAI0Fgx7Nq2UWU77rSNs1qxm4S6uH7TCZ0bV3LQpJFk7id/is/ZgoOPA== +electron-store@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-5.2.0.tgz#a15718fc1fa21acfd07af55f9b94f9fa6a536665" + integrity sha512-iU3WDqEDAYNYR9XV7p0tJajq/zs9z7Nrn0sAoR5nDyn8h/9dr9kusKbTxD8NtVEBD1TB1pkGMqcbIt/y6knDwQ== dependencies: - conf "^2.0.0" + conf "^6.2.1" + type-fest "^0.7.1" -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.483: - version "1.3.484" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.484.tgz#75f5a1eee5fe3168758b7c2cf375ae73c1ccf5e6" - integrity sha512-esh5mmjAGl6HhAaYgHlDZme+jCIc+XIrLrBTwxviE+pM64UBmdLUIHLlrPzJGbit7hQI1TR/oGDQWCvQZ5yrFA== +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.488: + version "1.3.503" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.503.tgz#3b2fc07b7e3ea0262c395984579ddabee1c9e0cd" + integrity sha512-Rh4+JP+5a+HeCg+77/BOLKzA6pLf8WZMd+DqiduEWCPyvSdY6KWzfkZXa2JRxrLO/aaB1YjTXenQdamZYzWfUw== -electron@^4.2.11: - version "4.2.12" - resolved "https://registry.yarnpkg.com/electron/-/electron-4.2.12.tgz#8e8926a6a6654cde5eb0612952fed98a56941875" - integrity sha512-EES8eMztoW8gEP5E4GQLP8slrfS2jqTYtHbu36mlu3k1xYAaNPyQQr6mCILkYxqj4l3la4CT2Vcs89CUG62vcQ== +electron@^9.0.2: + version "9.1.1" + resolved "https://registry.yarnpkg.com/electron/-/electron-9.1.1.tgz#d52c9873be4113287c3eb2b02f85bad6644b100e" + integrity sha512-BYvroBLV9x7G4iN33P/IxeZqwjl62/9VuBAF1CoM0m6OeheaiLog1ZMKLlCqVXycJvvrAvLHc454DDEmwnqqhA== dependencies: - "@types/node" "^10.12.18" - electron-download "^4.1.0" + "@electron/get" "^1.0.1" + "@types/node" "^12.0.12" extract-zip "^1.0.3" elegant-spinner@^1.0.1: @@ -6616,17 +6690,17 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -encodeurl@~1.0.2: +encodeurl@^1.0.2, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: - iconv-lite "~0.4.13" + iconv-lite "^0.6.2" end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" @@ -6636,9 +6710,9 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: once "^1.4.0" enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz#5d43bda4a0fd447cb0ebbe71bef8deff8805ad0d" - integrity sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" @@ -6665,9 +6739,9 @@ env-paths@^2.2.0: integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== envinfo@^7.3.1: - version "7.5.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.1.tgz#93c26897225a00457c75e734d354ea9106a72236" - integrity sha512-hQBkDf2iO4Nv0CNHpCuSBeaSrveU6nThVxFGTrq/eDlV716UQk09zChaJae4mZRsos1x4YLY2TaH3LHUae3ZmQ== + version "7.7.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.0.tgz#fbfa46d739dec0554ef40220cd91fb20f64c9698" + integrity sha512-XX0+kACx7HcIFhar/JjsDtDIVcC8hnzQO1Asehq+abs+v9MtzpUuujFb6eBTT4lF9j2Bh6d2XFngbFRryjUAeQ== err-code@^1.0.0: version "1.1.2" @@ -6731,6 +6805,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-error@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + es6-promise@^4.0.3, es6-promise@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" @@ -6744,9 +6823,9 @@ es6-promisify@^5.0.0: es6-promise "^4.0.3" escalade@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.1.tgz#52568a77443f6927cd0ab9c73129137533c965ed" - integrity sha512-DR6NO3h9niOT+MZs7bjxlj2a1k+POu5RN8CLTPX2+i78bRi9eLe7+0zXgUHMnGXWybYcL61E9hGhPKqedy8tQA== + version "3.0.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" + integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" @@ -6763,6 +6842,11 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -6890,9 +6974,9 @@ execa@^1.0.0: strip-eof "^1.0.0" execa@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" - integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== + version "4.0.3" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" + integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -7297,10 +7381,10 @@ find-cache-dir@^3.0.0: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-git-exec@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/find-git-exec/-/find-git-exec-0.0.2.tgz#be97e5fd2b1d6f9a3d0528dae9eb1687de255a7a" - integrity sha512-QspUJn996F9UyKDSG4C+G5/epoAZw9p/j2RPIcg8L8izxFccwjJtMd545TWGO0GqJFe+hW1NJKa/1ij3rM/ynw== +find-git-exec@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/find-git-exec/-/find-git-exec-0.0.3.tgz#4ce941859ebe7f359fb8e56aafd2acf3c955b52c" + integrity sha512-cGsuku5hwdOpToV6axI0fRCABuw1yozFtQv13pVK0j7BjILU8buDtHKmSrsZN340Sjj3Z42n8fcF1Xu4nRuBbA== dependencies: "@types/node" "^10.14.22" "@types/which" "^1.3.2" @@ -7355,12 +7439,12 @@ first-chunk-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -fix-path@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fix-path/-/fix-path-2.1.0.tgz#72ece739de9af4bd63fd02da23e9a70c619b4c38" - integrity sha1-cuznOd6a9L1j/QLaI+mnDGGbTDg= +fix-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fix-path/-/fix-path-3.0.0.tgz#c6b82fd5f5928e520b392a63565ebfef0ddf037e" + integrity sha512-opGAl4+ip5jUikHR2C8Jo7czZ80pz8EK/0gMlAZu7xgDmBqIynlX8SMYg9KowYjAU6HT0nxsSJEWru0u+n+N2Q== dependencies: - shell-path "^2.0.0" + shell-path "^2.1.0" flat@^4.1.0: version "4.1.0" @@ -7375,9 +7459,9 @@ flatten@^1.0.2: integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== flow-parser@^0.*: - version "0.128.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.128.0.tgz#6bee9bc4f578c8b66f59ad52dd769464a36a029d" - integrity sha512-BOqwccrxdGQjR09H9/YvmgrY6xCyhfRqqZ6HOiDuPBYkSVd5rKamCLs2S4D7Yd0ltwBtnP3rp7vzaBTIJK1+Iw== + version "0.129.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.129.0.tgz#5924357da8f4982c11e02883a6ed10e954e61ea4" + integrity sha512-kzxyoEl8vG0JF0/h/u0UjALXmsGvwU2NBfKczCSNO/It2fKb8hz1gMt05OuZAlMLYXcvgjntWJadIABeKGPK4g== flush-write-stream@^1.0.0: version "1.1.1" @@ -7678,7 +7762,7 @@ get-stream@^4.0.0, get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.0.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== @@ -7859,6 +7943,19 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl once "^1.3.0" path-is-absolute "^1.0.0" +global-agent@^2.0.2: + version "2.1.12" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.12.tgz#e4ae3812b731a9e81cbf825f9377ef450a8e4195" + integrity sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg== + dependencies: + boolean "^3.0.1" + core-js "^3.6.5" + es6-error "^4.1.1" + matcher "^3.0.0" + roarr "^2.15.3" + semver "^7.3.2" + serialize-error "^7.0.1" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -7879,6 +7976,16 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" +global-tunnel-ng@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" + integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg== + dependencies: + encodeurl "^1.0.2" + lodash "^4.17.10" + npm-conf "^1.1.3" + tunnel "^0.0.6" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -7889,6 +7996,13 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalthis@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" + integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw== + dependencies: + define-properties "^1.1.3" + globby@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" @@ -7998,6 +8112,23 @@ got@^8.2.0, got@^8.3.1: url-parse-lax "^3.0.0" url-to-options "^1.0.1" +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -8021,11 +8152,11 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== grpc-tools@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.9.0.tgz#57fd0f577dbf842e03215857582f5dc808d96cad" - integrity sha512-du10qytFNDVNYGJQ/AxXTF6lXchgCZ7ls8BtBDCtnuinjGbnPFHpOIzoEAT8NsmgFg4RCpsWW8vsQ+RCyQ3SXA== + version "1.9.1" + resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.9.1.tgz#e43be478860a21781ce9a535647985cd365b1e06" + integrity sha512-t2JFMPLjxcgwVSJwFEauFaoEiO56kijxSwehQDgZNR/hrStJCH0pHGsjqJNuCOvmI9Z31pYOfgj4zeInTQWh5A== dependencies: - node-pre-gyp "^0.12.0" + node-pre-gyp "^0.15.0" grpc_tools_node_protoc_ts@^4.1.0: version "4.1.0" @@ -8325,6 +8456,11 @@ http-cache-semantics@3.8.1, http-cache-semantics@^3.8.1: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + http-errors@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" @@ -8422,13 +8558,20 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" @@ -8625,9 +8768,9 @@ inquirer@^6.2.0: through "^2.3.6" inquirer@^7.1.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.0.tgz#aa3e7cb0c18a410c3c16cdd2bc9dcbe83c4d333e" - integrity sha512-K+LZp6L/6eE5swqIcVXrxl21aGDU4S50gKH0/d96OMQnSBCyGyZl/oZhbkVmdp5sBoINHd4xZvFSARh2dk6DWA== + version "7.3.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.2.tgz#25245d2e32dc9f33dbe26eeaada231daa66e9c7c" + integrity sha512-DF4osh1FM6l0RJc5YWYhSDB6TawiBRlbV9Cox8MWlidU218Tb7fm3lQTULyUJDfJ0tjbzl0W4q651mrCCEM55w== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.0" @@ -8635,7 +8778,7 @@ inquirer@^7.1.0: cli-width "^3.0.0" external-editor "^3.0.3" figures "^3.0.0" - lodash "^4.17.15" + lodash "^4.17.16" mute-stream "0.0.8" run-async "^2.4.0" rxjs "^6.6.0" @@ -8908,6 +9051,11 @@ is-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" @@ -8939,10 +9087,10 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" - integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== +is-plain-object@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-4.1.0.tgz#00196ad308ebb7de9d1fb57ae92ef1c38d5a740e" + integrity sha512-1N1OpoS8S4Ua+FsH6Mhvgaj0di3uRXgulcv2dnFu2J/WcEsDNbBoiUX6mYmhQ2cAzZ+B/lTJtX1qUSL5RwsGug== is-posix-bracket@^0.1.0: version "0.1.1" @@ -9028,7 +9176,7 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -9125,9 +9273,9 @@ jake@^10.6.1: minimatch "^3.0.4" js-base64@^2.1.9: - version "2.6.2" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.2.tgz#cf9301bc5cc756892a9a6c8d7138322e5944fb0d" - integrity sha512-1hgLrLIrmCgZG+ID3VoLNLOSwjGnoZa8tyrUdEteMeIzsT6PH7PMLyUvbDwzNE56P3PNxyvuIOx4Uh2E5rzQIw== + version "2.6.3" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.3.tgz#7afdb9b57aa7717e15d370b66e8f36a9cb835dc3" + integrity sha512-fiUvdfCaAXoQTHdKMgTvg6IkecXDcVz6V5rlftUTclF9IKBjMizvSdQaCl/z/6TApDeby5NL+axYou3i0mu1Pg== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -9245,6 +9393,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-typed@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9" + integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -9275,9 +9428,9 @@ json5@^2.1.2: minimist "^1.2.5" jsonc-parser@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc" - integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w== + version "2.3.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee" + integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA== jsonfile@^2.1.0: version "2.4.0" @@ -9327,6 +9480,13 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -9404,11 +9564,10 @@ less-loader@~2.2.3: loader-utils "^0.2.5" less@^3.0.3: - version "3.11.3" - resolved "https://registry.yarnpkg.com/less/-/less-3.11.3.tgz#2d853954fcfe0169a8af869620bcaa16563dcc1c" - integrity sha512-VkZiTDdtNEzXA3LgjQiC3D7/ejleBPFVvq+aRI9mIj+Zhmif5TvFPM244bT4rzkvOCvJ9q4zAztok1M7Nygagw== + version "3.12.2" + resolved "https://registry.yarnpkg.com/less/-/less-3.12.2.tgz#157e6dd32a68869df8859314ad38e70211af3ab4" + integrity sha512-+1V2PCMFkL+OIj2/HrtrvZw0BC0sYLMICJfbQjuj/K8CEnlrFX6R5cKKgzzttsZDHyxQNL1jqMREjKN3ja/E3Q== dependencies: - clone "^2.1.2" tslib "^1.10.0" optionalDependencies: errno "^0.1.1" @@ -9416,8 +9575,7 @@ less@^3.0.3: image-size "~0.5.0" make-dir "^2.1.0" mime "^1.4.1" - promise "^7.1.1" - request "^2.83.0" + native-request "^1.0.5" source-map "~0.6.0" leven@^3.1.0: @@ -9662,10 +9820,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== log-ok@^0.1.1: version "0.1.1" @@ -9745,11 +9903,16 @@ lowercase-keys@1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= -lowercase-keys@^1.0.0: +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -9864,6 +10027,13 @@ markdown-it@^8.4.0: mdurl "^1.0.1" uc.micro "^1.0.5" +matcher@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" + integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng== + dependencies: + escape-string-regexp "^4.0.0" + math-expression-evaluator@^1.2.14: version "1.2.22" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz#c14dcb3d8b4d150e5dcea9c68c8dad80309b0d5e" @@ -10131,7 +10301,7 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0: +mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== @@ -10426,17 +10596,22 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -native-keymap@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/native-keymap/-/native-keymap-1.2.6.tgz#93d1b4c4ae0e9136bc14538cafe02c0bbe95bebf" - integrity sha512-8hEr6wNkb7OmGPFLFk1cAsnOt2Y3F4mtBffr8uOyX0kKOjr2JVetSt9TKjk0xyJw/B/HcEgMhXmjFKzGN+9JjA== +native-keymap@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/native-keymap/-/native-keymap-2.1.2.tgz#9773313f619d4c2b66b452cf036310a145523b59" + integrity sha512-n+oe+sxaauCFxomkl9Xrw1iUp88jTamMaGJSHNSGZ8rkIN9N+Wi6KIvBO8x3nmFxLI27KWu1d8IrLBxFKPNQag== + +native-request@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.7.tgz#ff742dc555b4c8f2f1c14b548639ba174e573856" + integrity sha512-9nRjinI9bmz+S7dgNtf4A70+/vPhnd+2krGpy4SUlADuOuSa24IDkNaZ+R/QT1wQ6S8jBdi6wE7fLekFZNfUpQ== ncp@^2.0.0, ncp@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= -needle@^2.2.1: +needle@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/needle/-/needle-2.5.0.tgz#e6fc4b3cc6c25caed7554bd613a5cf0bac8c31c0" integrity sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA== @@ -10451,9 +10626,9 @@ negotiator@0.6.2: integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" @@ -10591,26 +10766,26 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== +node-pre-gyp@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz#c2fc383276b74c7ffa842925241553e8b40f1087" + integrity sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA== dependencies: detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" + mkdirp "^0.5.3" + needle "^2.5.0" nopt "^4.0.1" npm-packlist "^1.1.6" npmlog "^4.0.2" rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" - tar "^4" + tar "^4.4.2" node-releases@^1.1.58: - version "1.1.58" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935" - integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg== + version "1.1.59" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.59.tgz#4d648330641cec704bff10f8e4fe28e453ab8e8e" + integrity sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw== node-uuid@^1.4.8: version "1.4.8" @@ -10703,6 +10878,11 @@ normalize-url@^3.3.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + npm-api@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/npm-api/-/npm-api-1.0.0.tgz#6033c283bb04ddb0185344c1ad07ed4f67c77989" @@ -10722,7 +10902,7 @@ npm-bundled@^1.0.1: dependencies: npm-normalize-package-bin "^1.0.1" -npm-conf@^1.1.0: +npm-conf@^1.1.0, npm-conf@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== @@ -11051,6 +11231,11 @@ p-cancelable@^0.4.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + p-debounce@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-debounce/-/p-debounce-2.1.0.tgz#e79f70c6e325cbb9bddbcbec0b81025084671ad3" @@ -11496,12 +11681,12 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= +pkg-up@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== dependencies: - find-up "^2.1.0" + find-up "^3.0.0" posix-character-classes@^0.1.0: version "0.1.1" @@ -11869,7 +12054,7 @@ progress-stream@^1.1.0: speedometer "~0.1.2" through2 "~0.2.3" -progress@^2.0.0, progress@^2.0.1: +progress@^2.0.0, progress@^2.0.1, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -11887,13 +12072,6 @@ promise-retry@^1.1.1: err-code "^1.0.0" retry "^0.10.0" -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - promzard@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" @@ -12163,9 +12341,9 @@ rc@^1.1.6, rc@^1.2.1, rc@^1.2.7: strip-json-comments "~2.0.1" react-autosize-textarea@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/react-autosize-textarea/-/react-autosize-textarea-7.0.0.tgz#4f633e4238de7ba73c1da8fdc307353c50f1c5ab" - integrity sha512-rGQLpGUaELvzy3NKzp0kkcppaUtZTptsyR0PGuLotaJDjwRbT0DpD000yCzETpXseJQ/eMsyVGDDHXjXP93u8w== + version "7.1.0" + resolved "https://registry.yarnpkg.com/react-autosize-textarea/-/react-autosize-textarea-7.1.0.tgz#902c84fc395a689ca3a484dfb6bc2be9ba3694d1" + integrity sha512-BHpjCDkuOlllZn3nLazY2F8oYO1tS2jHnWhcjTWQdcKiiMU6gHLNt/fzmqMSyerR0eTdKtfSIqtSeTtghNwS+g== dependencies: autosize "^4.0.2" line-height "^0.3.1" @@ -12544,9 +12722,9 @@ regenerator-runtime@^0.11.0: integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + version "0.13.6" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.6.tgz#d236043c46ffab2968c1ef651803d8acdea8ed65" + integrity sha512-GmwlGiazQEbOwQWDdbbaP10i15pGtScYWLbMZuu+RKRz0cZ+g8IUONazBnaZqe7j1670IV1HgE4/8iy7CQPf4Q== regenerator-transform@^0.10.0: version "0.10.1" @@ -12588,7 +12766,7 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.6.0, regexpu-core@^4.7.0: +regexpu-core@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== @@ -12666,7 +12844,7 @@ replace-ext@^1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== -request@^2.45.0, request@^2.82.0, request@^2.83.0, request@^2.86.0, request@^2.87.0, request@^2.88.0: +request@^2.45.0, request@^2.82.0, request@^2.86.0, request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -12753,7 +12931,7 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.8.1 dependencies: path-parse "^1.0.6" -responselike@1.0.2: +responselike@1.0.2, responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= @@ -12830,6 +13008,18 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +roarr@^2.15.3: + version "2.15.3" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" + integrity sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA== + dependencies: + boolean "^3.0.0" + detect-node "^2.0.4" + globalthis "^1.0.1" + json-stringify-safe "^5.0.1" + semver-compare "^1.0.0" + sprintf-js "^1.1.2" + route-parser@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/route-parser/-/route-parser-0.0.5.tgz#7d1d09d335e49094031ea16991a4a79b01bbe1f4" @@ -12885,11 +13075,18 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sanitize-filename@^1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + sax@^1.2.4, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -12946,6 +13143,11 @@ self-closing-tags@^1.0.1: resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d" integrity sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA== +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -12961,7 +13163,7 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.1.3, semver@^7.2.1: +semver@^7.1.3, semver@^7.2.1, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -12990,6 +13192,13 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-error@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" + integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw== + dependencies: + type-fest "^0.13.1" + serialize-javascript@^1.4.0: version "1.9.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" @@ -13092,7 +13301,7 @@ shell-env@^0.3.0: execa "^0.5.0" strip-ansi "^3.0.0" -shell-path@^2.0.0: +shell-path@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/shell-path/-/shell-path-2.1.0.tgz#ea7d06ae1070874a1bac5c65bb9bdd62e4f67a38" integrity sha1-6n0GrhBwh0obrFxlu5vdYuT2ejg= @@ -13114,9 +13323,9 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^2.7.0: version "2.8.1" @@ -13371,6 +13580,11 @@ split@^1.0.0: dependencies: through "2" +sprintf-js@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -13703,6 +13917,13 @@ sumchecker@^2.0.2: dependencies: debug "^2.2.0" +sumchecker@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" + integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg== + dependencies: + debug "^4.1.0" + supports-color@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" @@ -13796,7 +14017,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4, tar@^4.0.0, tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: +tar@^4.0.0, tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.2, tar@^4.4.8: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -13983,6 +14204,11 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -14092,6 +14318,13 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= + dependencies: + utf8-byte-length "^1.0.1" + ts-md5@^1.2.2: version "1.2.7" resolved "https://registry.yarnpkg.com/ts-md5/-/ts-md5-1.2.7.tgz#b76471fc2fd38f0502441f6c3b9494ed04537401" @@ -14140,6 +14373,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -14170,6 +14408,11 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -14183,6 +14426,13 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -14196,9 +14446,9 @@ typeof-article@^0.1.1: kind-of "^3.1.0" typescript@^3.9.2: - version "3.9.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" - integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== + version "3.9.7" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" + integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -14306,12 +14556,10 @@ universal-user-agent@^4.0.0: dependencies: os-name "^3.1.0" -universal-user-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9" - integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q== - dependencies: - os-name "^3.1.0" +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== universalify@^0.1.0: version "0.1.2" @@ -14445,6 +14693,11 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -14571,11 +14824,11 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vscode-debugadapter@^1.26.0, vscode-debugadapter@^1.37.1: - version "1.41.0" - resolved "https://registry.yarnpkg.com/vscode-debugadapter/-/vscode-debugadapter-1.41.0.tgz#2414b48b6f9925fd6cbc53ef5ce9dd8c6f41a9e2" - integrity sha512-b+J8wmsa3NCxJ+L9DAMpRfPM+8bmp4gFBoFp9lhkpwqn3UMs3sYvdcwugQr/T4lDaCCEr807HKMppRsD1EHhPQ== + version "1.41.1" + resolved "https://registry.yarnpkg.com/vscode-debugadapter/-/vscode-debugadapter-1.41.1.tgz#4a0433127ad5ac9164e1efae4feaf614ea1a594c" + integrity sha512-GTgbYEmfKlkAAad+7Lv1Hr7FvCzU8BEaYbEaq2/JSkG40GOaAM1ZqIX2gtxjVSk+ClWgDAb8PqQnUyxV+hGqiA== dependencies: - mkdirp "^0.5.1" + mkdirp "^1.0.4" vscode-debugprotocol "1.41.0" vscode-debugprotocol@1.41.0, vscode-debugprotocol@^1.26.0, vscode-debugprotocol@^1.32.0, vscode-debugprotocol@^1.37.0: @@ -14610,9 +14863,9 @@ vscode-languageserver-types@3.15.1, vscode-languageserver-types@^3.15.0-next: integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ== vscode-ripgrep@^1.2.4: - version "1.7.0" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.7.0.tgz#ec912e04aa29f7d73bcef04b7576b792f12c9b38" - integrity sha512-sQY/u0ymc9YMiPaSsMmdZSFQ6PTS2UxcGuiQkF7aoIezDxZcGE1sMarqftWEl9wYWYc9hElYm00WpoFgzj1oUg== + version "1.8.0" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.8.0.tgz#dfe7c2ae2a2032df8a8108765c2feef73474888a" + integrity sha512-/Q5XtePkTLLi8yplr5ai24pVEymRF62xH9xXrtj35GTaDCJg3zq1s1/L1UqhVbfNDv4OcMBYjyIAt/quEi3d5w== dependencies: https-proxy-agent "^4.0.0" proxy-from-env "^1.1.0" @@ -14886,6 +15139,16 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.2: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write-json-file@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f" @@ -14926,9 +15189,9 @@ ws@^6.1.0: async-limiter "~1.0.0" ws@^7.1.2: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" - integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== + version "7.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" + integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== xdg-basedir@^2.0.0: version "2.0.0" @@ -14971,9 +15234,9 @@ xterm-addon-search@^0.5.0: integrity sha512-zLVqVTrg5w2nk9fRj3UuVKCPo/dmFe/cLf3EM9Is5Dm6cgOoXmeo9eq2KgD8A0gquAflTFTf0ya2NaFmShHwyg== xterm@^4.4.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.7.0.tgz#254485811146b03fbea10c911f7f68a99e1d3bfd" - integrity sha512-UeH6U/1iknCBP94/AcKAFBeQz6ZicMugJHGXruTmsY8RcZt+mkx+vl8jLLOqNYweXdBbywCg2kK88WDKjcmSmg== + version "4.8.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.8.1.tgz#155a1729a43e1a89b406524e22c5634339e39ca1" + integrity sha512-ax91ny4tI5eklqIfH79OUSGE2PUX2rGbwONmB6DfqpyhSZO8/cf++sqiaMWEVCMjACyMfnISW7C3gGMoNvNolQ== y18n@^3.2.1: version "3.2.1" @@ -15016,7 +15279,7 @@ yargs-parser@^15.0.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.1, yargs-parser@^18.1.3: +yargs-parser@^18.1.2, yargs-parser@^18.1.3: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== @@ -15092,9 +15355,9 @@ yargs@^14.2.0, yargs@^14.2.2: yargs-parser "^15.0.1" yargs@^15.3.1: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -15106,7 +15369,7 @@ yargs@^15.3.1: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^18.1.1" + yargs-parser "^18.1.2" yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0"