mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-12 22:06:34 +00:00
Merge pull request #58 from bcmi-labs/use-sketch-as-ws
Use sketch folder as workspace
This commit is contained in:
commit
206b65f138
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,7 +6,8 @@ build/
|
||||
downloads/
|
||||
!electron/build/
|
||||
src-gen/
|
||||
arduino-ide-*/webpack.config.js
|
||||
browser-app/webpack.config.js
|
||||
electron-app/webpack.config.js
|
||||
.DS_Store
|
||||
/workspace/static
|
||||
# switching from `electron` to `browser` in dev mode.
|
||||
|
@ -8,7 +8,7 @@ ports:
|
||||
tasks:
|
||||
- init: >
|
||||
yarn &&
|
||||
yarn --cwd ./arduino-ide-browser start
|
||||
yarn --cwd ./browser-app start
|
||||
|
||||
github:
|
||||
prebuilds:
|
||||
|
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@ -14,7 +14,7 @@
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Backend",
|
||||
"program": "${workspaceRoot}/arduino-ide-browser/src-gen/backend/main.js",
|
||||
"program": "${workspaceRoot}/browser-app/src-gen/backend/main.js",
|
||||
"args": [
|
||||
"--hostname=0.0.0.0",
|
||||
"--port=3000",
|
||||
@ -26,8 +26,8 @@
|
||||
},
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/arduino-ide-browser/src-gen/backend/*.js",
|
||||
"${workspaceRoot}/arduino-ide-browser/lib/**/*.js",
|
||||
"${workspaceRoot}/browser-app/src-gen/backend/*.js",
|
||||
"${workspaceRoot}/browser-app/lib/**/*.js",
|
||||
"${workspaceRoot}/arduino-ide-extension/*/lib/**/*.js"
|
||||
],
|
||||
"smartStep": true,
|
||||
|
16
.vscode/tasks.json
vendored
16
.vscode/tasks.json
vendored
@ -4,9 +4,9 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Arduino-PoC - Start Browser Example",
|
||||
"label": "Arduino Editor - Start Browser Example",
|
||||
"type": "shell",
|
||||
"command": "yarn --cwd ./arduino-ide-browser start",
|
||||
"command": "yarn --cwd ./browser-app start",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
@ -15,7 +15,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Arduino-PoC - Watch Theia Extension",
|
||||
"label": "Arduino Editor - Watch Theia Extension",
|
||||
"type": "shell",
|
||||
"command": "yarn --cwd ./arduino-ide-extension watch",
|
||||
"group": "build",
|
||||
@ -26,9 +26,9 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Arduino-PoC - Watch Browser Example",
|
||||
"label": "Arduino Editor - Watch Browser Example",
|
||||
"type": "shell",
|
||||
"command": "yarn --cwd ./arduino-ide-browser watch",
|
||||
"command": "yarn --cwd ./browser-app watch",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
@ -37,11 +37,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Arduino-PoC - Watch All",
|
||||
"label": "Arduino Editor - Watch All",
|
||||
"type": "shell",
|
||||
"dependsOn": [
|
||||
"Arduino-PoC - Watch Theia Extension",
|
||||
"Arduino-PoC - Watch Browser Example"
|
||||
"Arduino Editor - Watch Theia Extension",
|
||||
"Arduino Editor - Watch Browser Example"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -17,7 +17,7 @@ git clone https://github.com/bcmi-labs/arduino-editor
|
||||
cd arduino-editor
|
||||
yarn
|
||||
yarn rebuild:electron
|
||||
yarn --cwd arduino-ide-electron start
|
||||
yarn --cwd electron-app start
|
||||
```
|
||||
|
||||
If you want to switch back to the browser-based example, execute the following in the repository root
|
||||
@ -26,7 +26,7 @@ yarn rebuild:browser
|
||||
```
|
||||
Then you can start the browser example again:
|
||||
```
|
||||
yarn --cwd arduino-ide-browser start
|
||||
yarn --cwd browser-app start
|
||||
```
|
||||
|
||||
## Arduino-PoC Electron Application
|
||||
|
@ -12,6 +12,7 @@
|
||||
"@theia/core": "next",
|
||||
"@theia/editor": "next",
|
||||
"@theia/filesystem": "next",
|
||||
"@theia/git": "next",
|
||||
"@theia/languages": "next",
|
||||
"@theia/markers": "next",
|
||||
"@theia/monaco": "next",
|
||||
@ -19,7 +20,6 @@
|
||||
"@theia/workspace": "next",
|
||||
"@theia/navigator": "next",
|
||||
"@theia/terminal": "next",
|
||||
"@theia/git": "next",
|
||||
"@theia/search-in-workspace": "next",
|
||||
"@types/ps-tree": "^1.1.0",
|
||||
"@types/which": "^1.3.1",
|
||||
@ -40,11 +40,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"decompress": "^4.2.0",
|
||||
"decompress-tarbz2": "^4.1.1",
|
||||
"decompress-targz": "^4.1.1",
|
||||
"decompress-unzip": "^4.0.1",
|
||||
"download": "^7.1.0",
|
||||
"grpc-tools": "^1.7.3",
|
||||
"grpc_tools_node_protoc_ts": "^2.5.0",
|
||||
"moment": "^2.24.0",
|
||||
"ncp": "^2.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"shelljs": "^0.8.3",
|
||||
|
@ -1,11 +1,16 @@
|
||||
// @ts-check
|
||||
// The links to the downloads as of today (11.08.) are the followings:
|
||||
// - https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli-nightly-latest-${FILE_NAME}
|
||||
// - https://downloads.arduino.cc/arduino-cli/arduino-cli-latest-${FILE_NAME}
|
||||
// The links to the downloads as of today (02.09.) are the followings:
|
||||
// In order to get the latest nightly build for your platform use the following links replacing <DATE> with the current date, using the format YYYYMMDD (i.e for 2019/Aug/06 use 20190806 )
|
||||
// Linux 64 bit: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-<DATE>_Linux_64bit.tar.gz
|
||||
// Linux ARM 64 bit: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-<DATE>_Linux_ARM64.tar.gz
|
||||
// Windows 64 bit: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-<DATE>_Windows_64bit.zip
|
||||
// Mac OSX: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-<DATE>_macOS_64bit.tar.gz
|
||||
// [...]
|
||||
// redirecting to latest generated builds by replacing latest with the latest available build date, using the format YYYYMMDD (i.e for 2019/Aug/06 latest is replaced with 20190806
|
||||
|
||||
(async () => {
|
||||
|
||||
const DEFAULT_VERSION = 'nightly';
|
||||
const DEFAULT_VERSION = 'latest'; // require('moment')().format('YYYYMMDD');
|
||||
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
@ -14,7 +19,7 @@
|
||||
const download = require('download');
|
||||
const decompress = require('decompress');
|
||||
const unzip = require('decompress-unzip');
|
||||
const untarbz = require('decompress-tarbz2');
|
||||
const untargz = require('decompress-targz');
|
||||
|
||||
process.on('unhandledRejection', (reason, _) => {
|
||||
shell.echo(String(reason));
|
||||
@ -31,11 +36,7 @@
|
||||
.option('cli-version', {
|
||||
alias: 'cv',
|
||||
default: DEFAULT_VERSION,
|
||||
choices: [
|
||||
// 'latest', // TODO: How do we get the source for `latest`. Currently, `latest` is the `0.3.7-alpha.preview`.
|
||||
'nightly'
|
||||
],
|
||||
describe: `The version of the 'arduino-cli' to download. Defaults to ${DEFAULT_VERSION}.`
|
||||
describe: `The version of the 'arduino-cli' to download with the YYYYMMDD format, or 'latest'. Defaults to ${DEFAULT_VERSION}.`
|
||||
})
|
||||
.option('force-download', {
|
||||
alias: 'fd',
|
||||
@ -68,13 +69,12 @@
|
||||
|
||||
const suffix = (() => {
|
||||
switch (platform) {
|
||||
case 'darwin': return 'macosx.zip';
|
||||
case 'win32': return 'windows.zip';
|
||||
case 'darwin': return 'macOS_64bit.tar.gz';
|
||||
case 'win32': return 'Windows_64bit.zip';
|
||||
case 'linux': {
|
||||
switch (arch) {
|
||||
case 'arm64': return 'linuxarm.tar.bz2';
|
||||
case 'x32': return 'linux32.tar.bz2';
|
||||
case 'x64': return 'linux64.tar.bz2';
|
||||
case 'arm64': return 'Linux_ARM64.tar.gz';
|
||||
case 'x64': return 'Linux_64bit.tar.gz';
|
||||
default: return undefined;
|
||||
}
|
||||
}
|
||||
@ -86,7 +86,7 @@
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/${version === 'nightly' ? 'nightly/' : ''}arduino-cli-${version}-latest-${suffix}`;
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-${version}_${suffix}`;
|
||||
shell.echo(`>>> Downloading 'arduino-cli' from '${url}'...`);
|
||||
const data = await download(url);
|
||||
shell.echo(`<<< Download succeeded.`);
|
||||
@ -94,16 +94,21 @@
|
||||
const files = await decompress(data, downloads, {
|
||||
plugins: [
|
||||
unzip(),
|
||||
untarbz()
|
||||
untargz()
|
||||
]
|
||||
});
|
||||
shell.echo('<<< Decompressing succeeded.');
|
||||
|
||||
if (files.length !== 1) {
|
||||
if (files.length === 0) {
|
||||
shell.echo('Error ocurred when decompressing the CLI.');
|
||||
shell.exit(1);
|
||||
}
|
||||
if (shell.mv('-f', path.join(downloads, files[0].path), cli).code !== 0) {
|
||||
const cliIndex = files.findIndex(f => f.path.startsWith('arduino-cli'));
|
||||
if (cliIndex === -1) {
|
||||
shell.echo('The downloaded artifact does not contains the CLI.');
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo('<<< Decompressing succeeded.');
|
||||
|
||||
if (shell.mv('-f', path.join(downloads, files[cliIndex].path), cli).code !== 0) {
|
||||
shell.echo(`Could not move file to ${cli}.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import { BoardsConfigDialog } from './boards/boards-config-dialog';
|
||||
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
|
||||
import { BoardsConfig } from './boards/boards-config';
|
||||
import { MonitorService } from '../common/protocol/monitor-service';
|
||||
import { ConfigService } from '../common/protocol/config-service';
|
||||
|
||||
export namespace ArduinoMenus {
|
||||
export const SKETCH = [...MAIN_MENU_BAR, '3_sketch'];
|
||||
@ -133,21 +134,19 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
|
||||
@inject(LabelProvider)
|
||||
protected readonly labelProvider: LabelProvider;
|
||||
|
||||
|
||||
@inject(QuickOpenService)
|
||||
protected readonly quickOpenService: QuickOpenService;
|
||||
|
||||
@inject(WorkspaceService)
|
||||
protected readonly workspaceService: WorkspaceService;
|
||||
|
||||
@inject(ConfigService)
|
||||
protected readonly configService: ConfigService;
|
||||
|
||||
protected boardsToolbarItem: BoardsToolBarItem | null;
|
||||
protected wsSketchCount: number = 0;
|
||||
|
||||
constructor(@inject(WorkspaceService) protected readonly workspaceService: WorkspaceService) {
|
||||
this.workspaceService.onWorkspaceChanged(() => {
|
||||
if (this.workspaceService.workspace) {
|
||||
this.registerSketchesInMenu(this.menuRegistry);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
// This is a hack. Otherwise, the backend services won't bind.
|
||||
@ -161,6 +160,8 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
}
|
||||
this.boardsServiceClient.onBoardsConfigChanged(updateStatusBar);
|
||||
updateStatusBar(this.boardsServiceClient.boardsConfig);
|
||||
|
||||
this.registerSketchesInMenu(this.menuRegistry);
|
||||
}
|
||||
|
||||
registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
@ -453,7 +454,13 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
}
|
||||
|
||||
protected async getWorkspaceSketches(): Promise<Sketch[]> {
|
||||
const sketches = this.sketches.getSketches(this.workspaceService.workspace);
|
||||
|
||||
let sketches: Sketch[] = [];
|
||||
const config = await this.configService.getConfiguration();
|
||||
const stat = await this.fileSystem.getFileStat(config.sketchDirUri);
|
||||
if (!!stat) {
|
||||
sketches = await this.sketches.getSketches(stat);
|
||||
}
|
||||
return sketches;
|
||||
}
|
||||
|
||||
@ -461,13 +468,18 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
const url = new URL(window.location.href);
|
||||
const currentSketch = url.searchParams.get('sketch');
|
||||
// Nothing to do if we want to open the same sketch which is already opened.
|
||||
if (!!currentSketch && new URI(currentSketch).toString() === new URI(uri).toString()) {
|
||||
this.messageService.info(`The '${this.labelProvider.getLongName(new URI(uri))}' is already opened.`);
|
||||
const sketchUri = new URI(uri);
|
||||
if (!!currentSketch && new URI(currentSketch).toString() === sketchUri.toString()) {
|
||||
this.messageService.info(`The '${this.labelProvider.getLongName(sketchUri)}' is already opened.`);
|
||||
// NOOP.
|
||||
return;
|
||||
}
|
||||
// Preserve the current window if the `sketch` is not in the `searchParams`.
|
||||
url.searchParams.set('sketch', uri);
|
||||
const hash = await this.fileSystem.getFsPath(sketchUri.toString());
|
||||
if (hash) {
|
||||
url.hash = hash;
|
||||
}
|
||||
if (!currentSketch) {
|
||||
setTimeout(() => window.location.href = url.toString(), 100);
|
||||
return;
|
||||
@ -543,25 +555,6 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// private async onNoBoardsInstalled() {
|
||||
// const action = await this.messageService.info("You have no boards installed. Use the boards manager to install one.", "Open Boards Manager");
|
||||
// if (!action) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this.boardsListWidgetFrontendContribution.openView({ reveal: true });
|
||||
// }
|
||||
|
||||
// private async onUnknownBoard() {
|
||||
// const action = await this.messageService.warn("There's a board connected for which you need to install software." +
|
||||
// " If this were not a PoC we would offer you the right package now.", "Open Boards Manager");
|
||||
// if (!action) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this.boardsListWidgetFrontendContribution.openView({ reveal: true });
|
||||
// }
|
||||
|
||||
private isArduinoToolbar(maybeToolbarWidget: any): boolean {
|
||||
if (maybeToolbarWidget instanceof ArduinoToolbar) {
|
||||
return true;
|
||||
|
@ -56,6 +56,7 @@ import { LibraryItemRenderer } from './library/library-item-renderer';
|
||||
import { BoardItemRenderer } from './boards/boards-item-renderer';
|
||||
import { MonitorServiceClientImpl } from './monitor/monitor-service-client-impl';
|
||||
import { MonitorServicePath, MonitorService, MonitorServiceClient } from '../common/protocol/monitor-service';
|
||||
import { ConfigService, ConfigServicePath } from '../common/protocol/config-service';
|
||||
const ElementQueries = require('css-element-queries/src/ElementQueries');
|
||||
|
||||
if (!ARDUINO_PRO_MODE) {
|
||||
@ -96,6 +97,9 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
|
||||
// Sketch list service
|
||||
bind(SketchesService).toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, SketchesServicePath)).inSingletonScope();
|
||||
|
||||
// Config service
|
||||
bind(ConfigService).toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, ConfigServicePath)).inSingletonScope();
|
||||
|
||||
// Boards service
|
||||
bind(BoardsService).toDynamicValue(context => {
|
||||
const connection = context.container.get(WebSocketConnectionProvider);
|
||||
|
@ -4,6 +4,7 @@ import { WorkspaceServer } from "@theia/workspace/lib/common";
|
||||
import { FileSystem, FileStat } from "@theia/filesystem/lib/common";
|
||||
import URI from "@theia/core/lib/common/uri";
|
||||
import { SketchFactory } from "./sketch-factory";
|
||||
import { ConfigService } from "../common/protocol/config-service";
|
||||
|
||||
/**
|
||||
* This is workaround to have custom frontend binding for the default workspace, although we
|
||||
@ -21,16 +22,14 @@ export class AWorkspaceService extends WorkspaceService {
|
||||
@inject(SketchFactory)
|
||||
protected readonly sketchFactory: SketchFactory;
|
||||
|
||||
@inject(ConfigService)
|
||||
protected readonly configService: ConfigService;
|
||||
|
||||
protected async getDefaultWorkspacePath(): Promise<string | undefined> {
|
||||
let result = await super.getDefaultWorkspacePath();
|
||||
if (!result) {
|
||||
const userHome = await this.fileSystem.getCurrentUserHome();
|
||||
if (!userHome) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The backend has created this location if it was missing.
|
||||
result = new URI(userHome.uri).resolve('Arduino-PoC').resolve('Sketches').toString();
|
||||
const config = await this.configService.getConfiguration();
|
||||
result = config.sketchDirUri;
|
||||
}
|
||||
|
||||
const stat = await this.fileSystem.getFileStat(result);
|
||||
|
@ -38,7 +38,8 @@ export class SketchFactory {
|
||||
const sketchDir = parent.resolve(sketchName);
|
||||
const sketchFile = sketchDir.resolve(`${sketchName}.ino`);
|
||||
this.fileSystem.createFolder(sketchDir.toString());
|
||||
this.fileSystem.createFile(sketchFile.toString(), { content: `
|
||||
this.fileSystem.createFile(sketchFile.toString(), {
|
||||
content: `
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
|
||||
@ -50,7 +51,11 @@ void loop() {
|
||||
}
|
||||
` });
|
||||
const location = new URL(window.location.href);
|
||||
location.searchParams.set('sketch', sketchFile.toString());
|
||||
location.searchParams.set('sketch', sketchDir.toString());
|
||||
const hash = await this.fileSystem.getFsPath(sketchDir.toString());
|
||||
if (hash) {
|
||||
location.hash = hash;
|
||||
}
|
||||
this.windowService.openNewWindow(location.toString());
|
||||
} catch (e) {
|
||||
throw new Error("Cannot create new sketch: " + e);
|
||||
|
11
arduino-ide-extension/src/common/protocol/config-service.ts
Normal file
11
arduino-ide-extension/src/common/protocol/config-service.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export const ConfigServicePath = '/services/config-service';
|
||||
export const ConfigService = Symbol('ConfigService');
|
||||
|
||||
export interface ConfigService {
|
||||
getConfiguration(): Promise<Config>;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
sketchDirUri: string;
|
||||
dataDirUri: string;
|
||||
}
|
@ -19,11 +19,24 @@ import { DefaultWorkspaceServerExt } from './default-workspace-server-ext';
|
||||
import { WorkspaceServer } from '@theia/workspace/lib/common';
|
||||
import { SketchesServiceImpl } from './sketches-service-impl';
|
||||
import { SketchesService, SketchesServicePath } from '../common/protocol/sketches-service';
|
||||
import { ConfigService, ConfigServicePath } from '../common/protocol/config-service';
|
||||
import { MonitorServiceImpl } from './monitor/monitor-service-impl';
|
||||
import { MonitorService, MonitorServicePath, MonitorServiceClient } from '../common/protocol/monitor-service';
|
||||
import { MonitorClientProvider } from './monitor/monitor-client-provider';
|
||||
import { ArduinoCli } from './arduino-cli';
|
||||
import { ArduinoCliContribution } from './arduino-cli-contribution';
|
||||
import { CliContribution } from '@theia/core/lib/node';
|
||||
import { ConfigServiceImpl } from './config-service-impl';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
// Theia backend CLI contribution.
|
||||
bind(ArduinoCliContribution).toSelf().inSingletonScope();
|
||||
bind(CliContribution).toService(ArduinoCliContribution);
|
||||
|
||||
// Provides the path of the Ardunio CLI.
|
||||
bind(ArduinoCli).toSelf().inSingletonScope();
|
||||
|
||||
// Shared daemonn
|
||||
bind(ArduinoDaemon).toSelf().inSingletonScope();
|
||||
bind(BackendApplicationContribution).toService(ArduinoDaemon);
|
||||
|
||||
@ -42,6 +55,15 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bindBackendService(SketchesServicePath, SketchesService);
|
||||
});
|
||||
bind(ConnectionContainerModule).toConstantValue(sketchesServiceConnectionModule);
|
||||
|
||||
bind(ConfigServiceImpl).toSelf().inSingletonScope();
|
||||
bind(ConfigService).toService(ConfigServiceImpl);
|
||||
|
||||
// Config service
|
||||
const configServiceConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
|
||||
bindBackendService(ConfigServicePath, ConfigService);
|
||||
});
|
||||
bind(ConnectionContainerModule).toConstantValue(configServiceConnectionModule);
|
||||
|
||||
// Boards service
|
||||
const boardsServiceConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
|
||||
|
27
arduino-ide-extension/src/node/arduino-cli-contribution.ts
Normal file
27
arduino-ide-extension/src/node/arduino-cli-contribution.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { injectable } from 'inversify';
|
||||
import { Argv, Arguments } from 'yargs';
|
||||
import { CliContribution } from '@theia/core/lib/node';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoCliContribution implements CliContribution {
|
||||
|
||||
protected _debugCli = false
|
||||
|
||||
configure(conf: Argv): void {
|
||||
conf.option('debug-cli', {
|
||||
description: 'Can be specified if the CLI daemon process was started externally.',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
nargs: 1
|
||||
});
|
||||
}
|
||||
|
||||
setArguments(args: Arguments): void {
|
||||
this._debugCli = args['debug-cli'];
|
||||
}
|
||||
|
||||
get debugCli(): boolean {
|
||||
return this._debugCli;
|
||||
}
|
||||
|
||||
}
|
66
arduino-ide-extension/src/node/arduino-cli.ts
Normal file
66
arduino-ide-extension/src/node/arduino-cli.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import * as os from 'os';
|
||||
import * as which from 'which';
|
||||
import * as cp from 'child_process';
|
||||
import { join, delimiter } from 'path';
|
||||
import { injectable, inject } from 'inversify';
|
||||
import { ILogger } from '@theia/core';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { Config } from '../common/protocol/config-service';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoCli {
|
||||
|
||||
@inject(ILogger)
|
||||
protected logger: ILogger;
|
||||
|
||||
async getExecPath(): Promise<string> {
|
||||
const build = join(__dirname, '..', '..', 'build');
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
which(`arduino-cli${os.platform() === 'win32' ? '.exe' : ''}`, { path: `${process.env.PATH}${delimiter}${build}` }, (err, path) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(path);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async getDefaultConfig(): Promise<Config> {
|
||||
const command = await this.getExecPath();
|
||||
return new Promise<Config>((resolve, reject) => {
|
||||
cp.execFile(
|
||||
command,
|
||||
['config', 'dump', '--format', 'json'],
|
||||
{ encoding: 'utf8' },
|
||||
(error, stdout, stderr) => {
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
throw new Error(stderr);
|
||||
}
|
||||
|
||||
const { sketchbook_path, arduino_data } = JSON.parse(stdout.trim());
|
||||
|
||||
if (!sketchbook_path) {
|
||||
reject(new Error(`Could not parse config. 'sketchbook_path' was missing from: ${stdout}`));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!arduino_data) {
|
||||
reject(new Error(`Could not parse config. 'arduino_data' was missing from: ${stdout}`));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve({
|
||||
sketchDirUri: FileUri.create(sketchbook_path).toString(),
|
||||
dataDirUri: FileUri.create(arduino_data).toString()
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
import * as which from 'which';
|
||||
import * as os from 'os';
|
||||
import { join, delimiter } from 'path';
|
||||
import { join } from 'path';
|
||||
import { exec, spawn, SpawnOptions } from 'child_process';
|
||||
import { inject, injectable, named } from 'inversify';
|
||||
import { ILogger } from '@theia/core/lib/common/logger';
|
||||
@ -9,17 +7,22 @@ import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { environment } from '@theia/application-package/lib/environment';
|
||||
import { DaemonLog } from './daemon-log';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
import { ArduinoCliContribution } from './arduino-cli-contribution';
|
||||
import { ArduinoCli } from './arduino-cli';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoDaemon implements BackendApplicationContribution {
|
||||
|
||||
// Set this to `true` if you want to connect to a CLI running in debug mode.
|
||||
static DEBUG_CLI = false;
|
||||
|
||||
@inject(ILogger)
|
||||
@named('daemon')
|
||||
protected readonly logger: ILogger
|
||||
|
||||
@inject(ArduinoCli)
|
||||
protected readonly cli: ArduinoCli;
|
||||
|
||||
@inject(ArduinoCliContribution)
|
||||
protected readonly cliContribution: ArduinoCliContribution;
|
||||
|
||||
@inject(ToolOutputServiceServer)
|
||||
protected readonly toolOutputService: ToolOutputServiceServer;
|
||||
|
||||
@ -27,19 +30,10 @@ export class ArduinoDaemon implements BackendApplicationContribution {
|
||||
|
||||
async onStart() {
|
||||
try {
|
||||
if (!ArduinoDaemon.DEBUG_CLI) {
|
||||
const build = join(__dirname, '..', '..', 'build');
|
||||
const executable = await new Promise<string>((resolve, reject) => {
|
||||
which(`arduino-cli${os.platform() === 'win32' ? '.exe' : ''}`, { path: `${process.env.PATH}${delimiter}${build}` }, (err, path) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(path);
|
||||
});
|
||||
});
|
||||
if (!this.cliContribution.debugCli) {
|
||||
const executable = await this.cli.getExecPath();
|
||||
this.logger.info(`>>> Starting 'arduino-cli' daemon... [${executable}]`);
|
||||
const daemon = exec(`${executable} --debug daemon`, (err, stdout, stderr) => {
|
||||
const daemon = exec(`${executable} daemon -v --log-level info --format json --log-format json`, (err, stdout, stderr) => {
|
||||
if (err || stderr) {
|
||||
console.log(err || new Error(stderr));
|
||||
return;
|
||||
@ -74,7 +68,7 @@ export class ArduinoDaemon implements BackendApplicationContribution {
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
this.isReady.resolve();
|
||||
if (!ArduinoDaemon.DEBUG_CLI) {
|
||||
if (!this.cliContribution.debugCli) {
|
||||
this.logger.info(`<<< The 'arduino-cli' daemon is up an running.`);
|
||||
} else {
|
||||
this.logger.info(`Assuming the 'arduino-cli' already runs in debug mode.`);
|
||||
|
@ -51,6 +51,9 @@ export class CompileReq extends jspb.Message {
|
||||
getExportfile(): string;
|
||||
setExportfile(value: string): void;
|
||||
|
||||
getJobs(): number;
|
||||
setJobs(value: number): void;
|
||||
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): CompileReq.AsObject;
|
||||
@ -77,6 +80,7 @@ export namespace CompileReq {
|
||||
quiet: boolean,
|
||||
vidpid: string,
|
||||
exportfile: string,
|
||||
jobs: number,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,8 @@ proto.cc.arduino.cli.commands.CompileReq.toObject = function(includeInstance, ms
|
||||
verbose: jspb.Message.getFieldWithDefault(msg, 10, false),
|
||||
quiet: jspb.Message.getFieldWithDefault(msg, 11, false),
|
||||
vidpid: jspb.Message.getFieldWithDefault(msg, 12, ""),
|
||||
exportfile: jspb.Message.getFieldWithDefault(msg, 13, "")
|
||||
exportfile: jspb.Message.getFieldWithDefault(msg, 13, ""),
|
||||
jobs: jspb.Message.getFieldWithDefault(msg, 14, 0)
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
@ -171,6 +172,10 @@ proto.cc.arduino.cli.commands.CompileReq.deserializeBinaryFromReader = function(
|
||||
var value = /** @type {string} */ (reader.readString());
|
||||
msg.setExportfile(value);
|
||||
break;
|
||||
case 14:
|
||||
var value = /** @type {number} */ (reader.readInt32());
|
||||
msg.setJobs(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
@ -292,6 +297,13 @@ proto.cc.arduino.cli.commands.CompileReq.serializeBinaryToWriter = function(mess
|
||||
f
|
||||
);
|
||||
}
|
||||
f = message.getJobs();
|
||||
if (f !== 0) {
|
||||
writer.writeInt32(
|
||||
14,
|
||||
f
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -527,6 +539,21 @@ proto.cc.arduino.cli.commands.CompileReq.prototype.setExportfile = function(valu
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* optional int32 jobs = 14;
|
||||
* @return {number}
|
||||
*/
|
||||
proto.cc.arduino.cli.commands.CompileReq.prototype.getJobs = function() {
|
||||
return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0));
|
||||
};
|
||||
|
||||
|
||||
/** @param {number} value */
|
||||
proto.cc.arduino.cli.commands.CompileReq.prototype.setJobs = function(value) {
|
||||
jspb.Message.setProto3IntField(this, 14, value);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generated by JsPbCodeGenerator.
|
||||
|
14
arduino-ide-extension/src/node/config-service-impl.ts
Normal file
14
arduino-ide-extension/src/node/config-service-impl.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { injectable, inject } from "inversify";
|
||||
import { ConfigService, Config } from "../common/protocol/config-service";
|
||||
import { ArduinoCli } from "./arduino-cli";
|
||||
|
||||
@injectable()
|
||||
export class ConfigServiceImpl implements ConfigService {
|
||||
|
||||
@inject(ArduinoCli)
|
||||
protected readonly cli: ArduinoCli;
|
||||
|
||||
async getConfiguration(): Promise<Config> {
|
||||
return this.cli.getDefaultConfig();
|
||||
}
|
||||
}
|
@ -1,5 +1,12 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import * as PQueue from 'p-queue';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { FileSystem } from '@theia/filesystem/lib/common';
|
||||
import { WorkspaceServiceExt } from '../browser/workspace-service-ext';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
import { ArduinoCoreClient } from './cli-protocol/commands/commands_grpc_pb';
|
||||
import {
|
||||
InitResp,
|
||||
@ -10,16 +17,10 @@ import {
|
||||
UpdateLibrariesIndexReq,
|
||||
UpdateLibrariesIndexResp
|
||||
} from './cli-protocol/commands/commands_pb';
|
||||
import { WorkspaceServiceExt } from '../browser/workspace-service-ext';
|
||||
import { FileSystem } from '@theia/filesystem/lib/common';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { CoreClientProvider, Client } from './core-client-provider';
|
||||
import * as PQueue from 'p-queue';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
import { ArduinoCli } from './arduino-cli';
|
||||
import { Instance } from './cli-protocol/commands/common_pb';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import { CoreClientProvider, Client } from './core-client-provider';
|
||||
import { FileUri } from '@theia/core/lib/node';
|
||||
|
||||
@injectable()
|
||||
export class CoreClientProviderImpl implements CoreClientProvider {
|
||||
@ -36,6 +37,9 @@ export class CoreClientProviderImpl implements CoreClientProvider {
|
||||
@inject(ToolOutputServiceServer)
|
||||
protected readonly toolOutputService: ToolOutputServiceServer;
|
||||
|
||||
@inject(ArduinoCli)
|
||||
protected readonly cli: ArduinoCli;
|
||||
|
||||
async getClient(workspaceRootOrResourceUri?: string): Promise<Client | undefined> {
|
||||
return this.clientRequestQueue.add(() => new Promise<Client | undefined>(async resolve => {
|
||||
const roots = await this.workspaceServiceExt.roots();
|
||||
@ -76,19 +80,26 @@ export class CoreClientProviderImpl implements CoreClientProvider {
|
||||
throw new Error(`Could not resolve filesystem path of URI: ${rootUri}.`);
|
||||
}
|
||||
|
||||
const defaultDownloadsDirPath = path.resolve(os.homedir(), 'Arduino-PoC', 'downloads');
|
||||
if (!fs.existsSync(defaultDownloadsDirPath)) {
|
||||
fs.mkdirpSync(defaultDownloadsDirPath);
|
||||
const { dataDirUri, sketchDirUri } = await this.cli.getDefaultConfig();
|
||||
const dataDirPath = FileUri.fsPath(dataDirUri);
|
||||
const sketchDirPath = FileUri.fsPath(sketchDirUri);
|
||||
|
||||
if (!fs.existsSync(dataDirPath)) {
|
||||
fs.mkdirSync(dataDirPath);
|
||||
}
|
||||
|
||||
const defaultDataDirPath = path.resolve(os.homedir(), 'Arduino-PoC', 'data')
|
||||
if (!fs.existsSync(defaultDataDirPath)) {
|
||||
fs.mkdirpSync(defaultDataDirPath);
|
||||
if (!fs.existsSync(sketchDirPath)) {
|
||||
fs.mkdirSync(sketchDirPath);
|
||||
}
|
||||
|
||||
config.setSketchbookdir(rootPath);
|
||||
config.setDatadir(defaultDataDirPath);
|
||||
config.setDownloadsdir(defaultDownloadsDirPath);
|
||||
const downloadDir = path.join(dataDirPath, 'staging');
|
||||
if (!fs.existsSync(downloadDir)) {
|
||||
fs.mkdirSync(downloadDir);
|
||||
}
|
||||
|
||||
config.setSketchbookdir(sketchDirPath);
|
||||
config.setDatadir(dataDirPath);
|
||||
config.setDownloadsdir(downloadDir);
|
||||
config.setBoardmanageradditionalurlsList(['https://downloads.arduino.cc/packages/package_index.json']);
|
||||
|
||||
const initReq = new InitReq();
|
||||
|
@ -8,7 +8,58 @@ export interface DaemonLog {
|
||||
|
||||
export namespace DaemonLog {
|
||||
|
||||
export type Level = 'info' | 'debug' | 'warning' | 'error';
|
||||
export interface Url {
|
||||
readonly Scheme: string;
|
||||
readonly Host: string;
|
||||
readonly Path: string;
|
||||
}
|
||||
|
||||
export namespace Url {
|
||||
|
||||
export function is(arg: any | undefined): arg is Url {
|
||||
return !!arg
|
||||
&& typeof arg.Scheme === 'string'
|
||||
&& typeof arg.Host === 'string'
|
||||
&& typeof arg.Path === 'string';
|
||||
}
|
||||
|
||||
export function toString(url: Url): string {
|
||||
const { Scheme, Host, Path } = url;
|
||||
return `${Scheme}://${Host}${Path}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface System {
|
||||
readonly os: string;
|
||||
// readonly Resource: Resource;
|
||||
}
|
||||
|
||||
export namespace System {
|
||||
export function toString(system: System): string {
|
||||
return `OS: ${system.os}`
|
||||
}
|
||||
}
|
||||
|
||||
export interface Tool {
|
||||
readonly version: string;
|
||||
readonly systems: System[];
|
||||
}
|
||||
|
||||
export namespace Tool {
|
||||
|
||||
export function is(arg: any | undefined): arg is Tool {
|
||||
return !!arg && typeof arg.version === 'string' && 'systems' in arg;
|
||||
}
|
||||
|
||||
export function toString(tool: Tool): string {
|
||||
const { version, systems } = tool;
|
||||
return `Version: ${version}${!!systems ? ` Systems: [${tool.systems.map(System.toString).join(', ')}]` : ''}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type Level = 'trace' | 'debug' | 'info' | 'warning' | 'error';
|
||||
|
||||
export function is(arg: any | undefined): arg is DaemonLog {
|
||||
return !!arg
|
||||
@ -20,61 +71,62 @@ export namespace DaemonLog {
|
||||
export function toLogLevel(log: DaemonLog): LogLevel {
|
||||
const { level } = log;
|
||||
switch (level) {
|
||||
case 'info': return LogLevel.INFO;
|
||||
case 'trace': return LogLevel.TRACE;
|
||||
case 'debug': return LogLevel.DEBUG;
|
||||
case 'error': return LogLevel.ERROR;
|
||||
case 'info': return LogLevel.INFO;
|
||||
case 'warning': return LogLevel.WARN;
|
||||
case 'error': return LogLevel.ERROR;
|
||||
default: return LogLevel.INFO;
|
||||
}
|
||||
}
|
||||
|
||||
export function log(logger: ILogger, toLog: string): void {
|
||||
const segments = toLog.split('time').filter(s => s.trim().length > 0);
|
||||
for (const segment of segments) {
|
||||
const maybeDaemonLog = parse(`time${segment}`.trim());
|
||||
for (const logMsg of maybeDaemonLog) {
|
||||
logger.log(toLogLevel(logMsg), logMsg.msg);
|
||||
}
|
||||
export function log(logger: ILogger, logMessages: string): void {
|
||||
const parsed = parse(logMessages);
|
||||
for (const log of parsed) {
|
||||
logger.log(toLogLevel(log), toMessage(log));
|
||||
}
|
||||
}
|
||||
|
||||
// Super naive.
|
||||
function parse(toLog: string): DaemonLog[] {
|
||||
const messages = toLog.split('\ntime=');
|
||||
const messages = toLog.trim().split('\n');
|
||||
const result: DaemonLog[] = [];
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
const msg = (i > 0 ? 'time=' : '') + messages[i];
|
||||
const rawSegments = msg.split(/(\s+)/)
|
||||
.map(segment => segment.replace(/['"]+/g, ''))
|
||||
.map(segment => segment.trim())
|
||||
.filter(segment => segment.length > 0);
|
||||
|
||||
const timeIndex = rawSegments.findIndex(segment => segment.startsWith('time='));
|
||||
const levelIndex = rawSegments.findIndex(segment => segment.startsWith('level='));
|
||||
const msgIndex = rawSegments.findIndex(segment => segment.startsWith('msg='));
|
||||
if (rawSegments.length > 2
|
||||
&& timeIndex !== -1
|
||||
&& levelIndex !== -1
|
||||
&& msgIndex !== -1) {
|
||||
result.push({
|
||||
time: rawSegments[timeIndex].split('=')[1],
|
||||
level: rawSegments[levelIndex].split('=')[1] as Level,
|
||||
msg: [rawSegments[msgIndex].split('=')[1], ...rawSegments.slice(msgIndex + 1)].join(' ')
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
const maybeDaemonLog = JSON.parse(messages[i]);
|
||||
if (DaemonLog.is(maybeDaemonLog)) {
|
||||
result.push(maybeDaemonLog);
|
||||
continue;
|
||||
}
|
||||
} catch { /* NOOP */ }
|
||||
result.push({
|
||||
time: new Date().toString(),
|
||||
level: 'info',
|
||||
msg: msg
|
||||
time: new Date().toString(),
|
||||
level: 'info',
|
||||
msg: messages[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
// Otherwise, log the string as is.
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toPrettyString(logMessage: string): string {
|
||||
const parsed = parse(logMessage);
|
||||
return parsed.map(msg => `[${msg.level.toUpperCase() || 'INFO'}] ${msg.msg}\n`).join('');
|
||||
export function toPrettyString(logMessages: string): string {
|
||||
const parsed = parse(logMessages);
|
||||
return parsed.map(toMessage).join('\n');
|
||||
}
|
||||
|
||||
function toMessage(log: DaemonLog): string {
|
||||
const details = Object.keys(log).filter(key => key !== 'msg' && key !== 'level' && key !== 'time').map(key => toDetails(log, key)).join(', ');
|
||||
return `[${log.level.toUpperCase()}] ${log.msg}${!!details ? ` [${details}]` : ''}`
|
||||
}
|
||||
|
||||
function toDetails(log: DaemonLog, key: string): string {
|
||||
let value = (log as any)[key];
|
||||
if (DaemonLog.Url.is(value)) {
|
||||
value = DaemonLog.Url.toString(value);
|
||||
} else if (DaemonLog.Tool.is(value)) {
|
||||
value = DaemonLog.Tool.toString(value);
|
||||
} else if (typeof value === 'object') {
|
||||
value = JSON.stringify(value).replace(/\"([^(\")"]+)\":/g, '$1:'); // Remove the quotes from the property keys.
|
||||
}
|
||||
return `${key.toLowerCase()}: ${value}`;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { injectable } from 'inversify';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { injectable, inject } from 'inversify';
|
||||
import { DefaultWorkspaceServer } from '@theia/workspace/lib/node/default-workspace-server';
|
||||
import { ConfigService } from '../common/protocol/config-service';
|
||||
|
||||
@injectable()
|
||||
export class DefaultWorkspaceServerExt extends DefaultWorkspaceServer {
|
||||
|
||||
@inject(ConfigService) protected readonly configService: ConfigService;
|
||||
|
||||
protected async getWorkspaceURIFromCli(): Promise<string | undefined> {
|
||||
return FileUri.create(path.join(os.homedir(), 'Arduino-PoC', 'Sketches')).toString();
|
||||
const config = await this.configService.getConfiguration();
|
||||
return config.sketchDirUri;
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "arduino-ide-browser",
|
||||
"name": "browser-app",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -30,7 +30,7 @@
|
||||
"theia": {
|
||||
"frontend": {
|
||||
"config": {
|
||||
"applicationName": "Arduino-PoC",
|
||||
"applicationName": "Arduino Editor",
|
||||
"defaultTheme": "arduino-theme",
|
||||
"preferences": {
|
||||
"editor.autoSave": "on"
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "arduino-ide-electron",
|
||||
"name": "electron-app",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -33,7 +33,7 @@
|
||||
"target": "electron",
|
||||
"frontend": {
|
||||
"config": {
|
||||
"applicationName": "Arduino-PoC",
|
||||
"applicationName": "Arduino Editor",
|
||||
"defaultTheme": "arduino-theme",
|
||||
"preferences": {
|
||||
"editor.autoSave": "on"
|
@ -14,7 +14,7 @@
|
||||
const workingCopy = 'working-copy';
|
||||
|
||||
/**
|
||||
* Relative path from the `__dirname` to the root where the `arduino-ide-extension` and the `arduino-ide-electron` folders are.
|
||||
* Relative path from the `__dirname` to the root where the `arduino-ide-extension` and the `electron-app` folders are.
|
||||
* This could come handy when moving the location of the `electron/packager`.
|
||||
*/
|
||||
const rootPath = join('..', '..');
|
||||
@ -42,18 +42,18 @@
|
||||
// Copy the following items into the `working-copy` folder. Make sure to reuse the `yarn.lock`. |
|
||||
//----------------------------------------------------------------------------------------------+
|
||||
mkdir('-p', path('..', workingCopy));
|
||||
for (const name of ['arduino-ide-extension', 'arduino-ide-electron', 'yarn.lock', 'package.json', 'lerna.json']) {
|
||||
for (const name of ['arduino-ide-extension', 'electron-app', 'yarn.lock', 'package.json', 'lerna.json']) {
|
||||
cp('-rf', path(rootPath, name), path('..', workingCopy));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------+
|
||||
// No need to build the `arduino-ide-browser` example. |
|
||||
// No need to build the `browser-app` example. |
|
||||
//-----------------------------------------------------+
|
||||
//@ts-ignore
|
||||
let pkg = require('../working-copy/package.json');
|
||||
const workspaces = pkg.workspaces;
|
||||
// We cannot remove the `arduino-ide-electron`. Otherwise, there is not way to collect the unused dependencies.
|
||||
const dependenciesToRemove = ['arduino-ide-browser'];
|
||||
// We cannot remove the `electron-app`. Otherwise, there is not way to collect the unused dependencies.
|
||||
const dependenciesToRemove = ['browser-app'];
|
||||
for (const dependencyToRemove of dependenciesToRemove) {
|
||||
const index = workspaces.indexOf(dependencyToRemove);
|
||||
if (index !== -1) {
|
||||
@ -70,13 +70,13 @@
|
||||
// Collect all unused dependencies by the backend. We have to remove them from the electron app.
|
||||
// The `bundle.js` already contains everything we need for the frontend.
|
||||
// We have to do it before changing the dependencies to `local-path`.
|
||||
const unusedDependencies = await utils.collectUnusedDependencies('../working-copy/arduino-ide-electron/');
|
||||
const unusedDependencies = await utils.collectUnusedDependencies('../working-copy/electron-app/');
|
||||
|
||||
//------------------------------------------------------------------------------------+
|
||||
// Merge the `working-copy/package.json` with `electron/build/template-package.json`. |
|
||||
//------------------------------------------------------------------------------------+
|
||||
// @ts-ignore
|
||||
pkg = require('../working-copy/arduino-ide-electron/package.json');
|
||||
pkg = require('../working-copy/electron-app/package.json');
|
||||
// @ts-ignore
|
||||
const template = require('../build/template-package.json');
|
||||
template.build.files = [ ...template.build.files, ...unusedDependencies.map(name => `!node_modules/${name}`) ];
|
||||
|
12
package.json
12
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "arduino-poc",
|
||||
"name": "arduino-editor",
|
||||
"version": "0.0.1",
|
||||
"description": "A PoC demonstrating an Arduino IDE built using Eclipse Theia",
|
||||
"description": "Arduino IDE built using Eclipse Theia",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/bcmi-labs/arduino-editor.git",
|
||||
"author": "Christian Weichel <christian.weichel@typefox.io>",
|
||||
@ -14,12 +14,12 @@
|
||||
"prepare": "lerna run prepare",
|
||||
"rebuild:browser": "theia rebuild:browser",
|
||||
"rebuild:electron": "theia rebuild:electron",
|
||||
"start": "cd arduino-ide-browser && yarn start",
|
||||
"start": "yarn --cwd ./browser-app start",
|
||||
"watch": "lerna run watch --parallel"
|
||||
},
|
||||
"workspaces": [
|
||||
"arduino-ide-electron",
|
||||
"arduino-ide-browser",
|
||||
"arduino-ide-extension"
|
||||
"arduino-ide-extension",
|
||||
"electron-app",
|
||||
"browser-app"
|
||||
]
|
||||
}
|
||||
|
@ -4473,7 +4473,7 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
|
||||
is-stream "^1.1.0"
|
||||
tar-stream "^1.5.2"
|
||||
|
||||
decompress-tarbz2@^4.0.0, decompress-tarbz2@^4.1.1:
|
||||
decompress-tarbz2@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
|
||||
integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
|
||||
@ -4484,7 +4484,7 @@ decompress-tarbz2@^4.0.0, decompress-tarbz2@^4.1.1:
|
||||
seek-bzip "^1.0.5"
|
||||
unbzip2-stream "^1.0.9"
|
||||
|
||||
decompress-targz@^4.0.0:
|
||||
decompress-targz@^4.0.0, decompress-targz@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
|
||||
integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
|
||||
@ -8098,7 +8098,7 @@ modify-values@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
|
||||
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
|
||||
|
||||
moment@^2.10.6, moment@^2.18.1, moment@^2.21.0:
|
||||
moment@^2.10.6, moment@^2.18.1, moment@^2.21.0, moment@^2.24.0:
|
||||
version "2.24.0"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
|
||||
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
|
||||
|
Loading…
x
Reference in New Issue
Block a user