mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-13 12:19:29 +00:00
ATL-302: Added built-in examples to the app.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
@@ -7,7 +7,7 @@ import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
|
||||
import { LanguageServerContribution } from '@theia/languages/lib/node';
|
||||
import { ArduinoLanguageServerContribution } from './language/arduino-language-server-contribution';
|
||||
import { LibraryService, LibraryServicePath } from '../common/protocol/library-service';
|
||||
import { LibraryServiceServerPath, LibraryServiceServer, LibraryServiceClient } from '../common/protocol/library-service';
|
||||
import { BoardsService, BoardsServicePath, BoardsServiceClient } from '../common/protocol/boards-service';
|
||||
import { LibraryServiceImpl } from './library-service-impl';
|
||||
import { BoardsServiceImpl } from './boards-service-impl';
|
||||
@@ -35,6 +35,8 @@ 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';
|
||||
import { ExamplesServiceImpl } from './examples-service-impl';
|
||||
import { ExamplesService, ExamplesServicePath } from '../common/protocol/examples-service';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
rebind(EnvVariablesServer).to(ArduinoEnvVariablesServer).inSingletonScope();
|
||||
@@ -66,25 +68,31 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
})
|
||||
).inSingletonScope();
|
||||
|
||||
// Shared examples service
|
||||
bind(ExamplesServiceImpl).toSelf().inSingletonScope();
|
||||
bind(ExamplesService).toService(ExamplesServiceImpl);
|
||||
bind(ConnectionHandler).toDynamicValue(context => new JsonRpcConnectionHandler(ExamplesServicePath, () => context.container.get(ExamplesService))).inSingletonScope();
|
||||
|
||||
// Language server
|
||||
bind(ArduinoLanguageServerContribution).toSelf().inSingletonScope();
|
||||
bind(LanguageServerContribution).toService(ArduinoLanguageServerContribution);
|
||||
|
||||
// Library service
|
||||
const libraryServiceConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
|
||||
bind(LibraryServiceImpl).toSelf().inSingletonScope();
|
||||
bind(LibraryService).toService(LibraryServiceImpl);
|
||||
bindBackendService(LibraryServicePath, LibraryService);
|
||||
});
|
||||
bind(ConnectionContainerModule).toConstantValue(libraryServiceConnectionModule);
|
||||
bind(LibraryServiceImpl).toSelf().inSingletonScope();
|
||||
bind(LibraryServiceServer).toService(LibraryServiceImpl);
|
||||
bind(ConnectionHandler).toDynamicValue(context =>
|
||||
new JsonRpcConnectionHandler<LibraryServiceClient>(LibraryServiceServerPath, client => {
|
||||
const server = context.container.get<LibraryServiceImpl>(LibraryServiceImpl);
|
||||
server.setClient(client);
|
||||
client.onDidCloseConnection(() => server.dispose());
|
||||
return server;
|
||||
})
|
||||
).inSingletonScope();
|
||||
|
||||
// Sketches service
|
||||
const sketchesServiceConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
|
||||
bind(SketchesServiceImpl).toSelf().inSingletonScope();
|
||||
bind(SketchesService).toService(SketchesServiceImpl);
|
||||
bindBackendService(SketchesServicePath, SketchesService);
|
||||
});
|
||||
bind(ConnectionContainerModule).toConstantValue(sketchesServiceConnectionModule);
|
||||
// Shred sketches service
|
||||
bind(SketchesServiceImpl).toSelf().inSingletonScope();
|
||||
bind(SketchesService).toService(SketchesServiceImpl);
|
||||
bind(ConnectionHandler).toDynamicValue(context => new JsonRpcConnectionHandler(SketchesServicePath, () => context.container.get(SketchesService))).inSingletonScope();
|
||||
|
||||
// Boards service
|
||||
const boardsServiceConnectionModule = ConnectionContainerModule.create(async ({ bind, bindBackendService }) => {
|
||||
@@ -190,6 +198,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
|
||||
// File-system extension for mapping paths to URIs
|
||||
bind(NodeFileSystemExt).toSelf().inSingletonScope();
|
||||
bind(FileSystemExt).toDynamicValue(context => context.container.get(NodeFileSystemExt));
|
||||
bind(FileSystemExt).toService(NodeFileSystemExt);
|
||||
bind(ConnectionHandler).toDynamicValue(context => new JsonRpcConnectionHandler(FileSystemExtPath, () => context.container.get(FileSystemExt))).inSingletonScope();
|
||||
});
|
||||
|
||||
@@ -112,8 +112,8 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
if (this.discoveryTimer !== undefined) {
|
||||
clearInterval(this.discoveryTimer);
|
||||
}
|
||||
this.logger.info('<<< Disposed boards service.');
|
||||
this.client = undefined;
|
||||
this.logger.info('<<< Disposed boards service.');
|
||||
}
|
||||
|
||||
async getAttachedBoards(): Promise<Board[]> {
|
||||
@@ -370,15 +370,15 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
}
|
||||
|
||||
async install(options: { item: BoardsPackage, version?: Installable.Version }): Promise<void> {
|
||||
const pkg = options.item;
|
||||
const version = !!options.version ? options.version : pkg.availableVersions[0];
|
||||
const item = options.item;
|
||||
const version = !!options.version ? options.version : item.availableVersions[0];
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return;
|
||||
}
|
||||
const { client, instance } = coreClient;
|
||||
|
||||
const [platform, architecture] = pkg.id.split(':');
|
||||
const [platform, architecture] = item.id.split(':');
|
||||
|
||||
const req = new PlatformInstallReq();
|
||||
req.setInstance(instance);
|
||||
@@ -386,7 +386,7 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
req.setPlatformPackage(platform);
|
||||
req.setVersion(version);
|
||||
|
||||
console.info('Starting board installation', pkg);
|
||||
console.info('>>> Starting boards package installation...', item);
|
||||
const resp = client.platformInstall(req);
|
||||
resp.on('data', (r: PlatformInstallResp) => {
|
||||
const prog = r.getProgress();
|
||||
@@ -399,34 +399,34 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
resp.on('error', reject);
|
||||
});
|
||||
if (this.client) {
|
||||
const packages = await this.search({});
|
||||
const updatedPackage = packages.find(({ id }) => id === pkg.id) || pkg;
|
||||
this.client.notifyBoardInstalled({ pkg: updatedPackage });
|
||||
const items = await this.search({});
|
||||
const updated = items.find(other => BoardsPackage.equals(other, item)) || item;
|
||||
this.client.notifyInstalled({ item: updated });
|
||||
}
|
||||
console.info('Board installation done', pkg);
|
||||
console.info('<<< Boards package installation done.', item);
|
||||
}
|
||||
|
||||
async uninstall(options: { item: BoardsPackage }): Promise<void> {
|
||||
const pkg = options.item;
|
||||
const item = options.item;
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return;
|
||||
}
|
||||
const { client, instance } = coreClient;
|
||||
|
||||
const [platform, architecture] = pkg.id.split(':');
|
||||
const [platform, architecture] = item.id.split(':');
|
||||
|
||||
const req = new PlatformUninstallReq();
|
||||
req.setInstance(instance);
|
||||
req.setArchitecture(architecture);
|
||||
req.setPlatformPackage(platform);
|
||||
|
||||
console.info('Starting board uninstallation', pkg);
|
||||
console.info('>>> Starting boards package uninstallation...', item);
|
||||
let logged = false;
|
||||
const resp = client.platformUninstall(req);
|
||||
resp.on('data', (_: PlatformUninstallResp) => {
|
||||
if (!logged) {
|
||||
this.toolOutputService.append({ tool: 'board uninstall', chunk: `uninstalling ${pkg.id}\n` });
|
||||
this.toolOutputService.append({ tool: 'board uninstall', chunk: `uninstalling ${item.id}\n` });
|
||||
logged = true;
|
||||
}
|
||||
})
|
||||
@@ -435,10 +435,10 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
resp.on('error', reject);
|
||||
});
|
||||
if (this.client) {
|
||||
// Here, unlike at `install` we send out the argument `pkg`. Otherwise, we would not know about the board FQBN.
|
||||
this.client.notifyBoardUninstalled({ pkg });
|
||||
// Here, unlike at `install` we send out the argument `item`. Otherwise, we would not know about the board FQBN.
|
||||
this.client.notifyUninstalled({ item });
|
||||
}
|
||||
console.info('Board uninstallation done', pkg);
|
||||
console.info('<<< Boards package uninstallation done.', item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,11 +15,16 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
|
||||
protected readonly toolOutputService: ToolOutputServiceServer;
|
||||
|
||||
protected readonly onIndexUpdatedEmitter = new Emitter<void>();
|
||||
protected readonly onClientReadyEmitter = new Emitter<void>();
|
||||
|
||||
get onIndexUpdated(): Event<void> {
|
||||
return this.onIndexUpdatedEmitter.event;
|
||||
}
|
||||
|
||||
get onClientReady(): Event<void> {
|
||||
return this.onClientReadyEmitter.event;
|
||||
}
|
||||
|
||||
close(client: CoreClientProvider.Client): void {
|
||||
client.client.close();
|
||||
}
|
||||
@@ -28,10 +33,12 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
|
||||
if (port && port === this._port) {
|
||||
// No need to create a new gRPC client, but we have to update the indexes.
|
||||
if (this._client) {
|
||||
this.updateIndexes(this._client);
|
||||
await this.updateIndexes(this._client);
|
||||
this.onClientReadyEmitter.fire();
|
||||
}
|
||||
} else {
|
||||
return super.reconcileClient(port);
|
||||
await super.reconcileClient(port);
|
||||
this.onClientReadyEmitter.fire();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
79
arduino-ide-extension/src/node/examples-service-impl.ts
Normal file
79
arduino-ide-extension/src/node/examples-service-impl.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { inject, injectable, postConstruct } from 'inversify';
|
||||
import { join, basename } from 'path';
|
||||
import * as fs from './fs-extra';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { Sketch } from '../common/protocol/sketches-service';
|
||||
import { SketchesServiceImpl } from './sketches-service-impl';
|
||||
import { ExamplesService, ExampleContainer } from '../common/protocol/examples-service';
|
||||
|
||||
@injectable()
|
||||
export class ExamplesServiceImpl implements ExamplesService {
|
||||
|
||||
@inject(SketchesServiceImpl)
|
||||
protected readonly sketchesService: SketchesServiceImpl;
|
||||
|
||||
protected _all: ExampleContainer | undefined;
|
||||
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
this.all();
|
||||
}
|
||||
|
||||
async all(): Promise<ExampleContainer> {
|
||||
if (this._all) {
|
||||
return this._all;
|
||||
}
|
||||
this._all = await this.load();
|
||||
return this._all;
|
||||
}
|
||||
|
||||
protected async load(path: string = join(__dirname, '..', '..', 'Examples')): Promise<ExampleContainer> {
|
||||
if (!await fs.exists(path)) {
|
||||
throw new Error('Examples are not available');
|
||||
}
|
||||
const stat = await fs.stat(path);
|
||||
if (!stat.isDirectory) {
|
||||
throw new Error(`${path} is not a directory.`);
|
||||
}
|
||||
const names = await fs.readdir(path);
|
||||
const sketches: Sketch[] = [];
|
||||
const children: ExampleContainer[] = [];
|
||||
for (const p of names.map(name => join(path, name))) {
|
||||
const stat = await fs.stat(p);
|
||||
if (stat.isDirectory()) {
|
||||
const sketch = await this.tryLoadSketch(p);
|
||||
if (sketch) {
|
||||
sketches.push(sketch);
|
||||
} else {
|
||||
const child = await this.load(p);
|
||||
children.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
const label = basename(path);
|
||||
return {
|
||||
label,
|
||||
children,
|
||||
sketches
|
||||
};
|
||||
}
|
||||
|
||||
protected async group(paths: string[]): Promise<Map<string, fs.Stats>> {
|
||||
const map = new Map<string, fs.Stats>();
|
||||
for (const path of paths) {
|
||||
const stat = await fs.stat(path);
|
||||
map.set(path, stat);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
protected async tryLoadSketch(path: string): Promise<Sketch | undefined> {
|
||||
try {
|
||||
const sketch = await this.sketchesService.loadSketch(FileUri.create(path).toString());
|
||||
return sketch;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import * as fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
|
||||
export const constants = fs.constants;
|
||||
export type Stats = fs.Stats;
|
||||
|
||||
export const existsSync = fs.existsSync;
|
||||
export const lstatSync = fs.lstatSync;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { injectable, inject } from 'inversify';
|
||||
import { Library, LibraryService } from '../common/protocol/library-service';
|
||||
import { injectable, inject, postConstruct } from 'inversify';
|
||||
import { LibraryPackage, LibraryService, LibraryServiceClient } from '../common/protocol/library-service';
|
||||
import { CoreClientProvider } from './core-client-provider';
|
||||
import {
|
||||
LibrarySearchReq,
|
||||
@@ -15,17 +15,37 @@ import {
|
||||
} from './cli-protocol/commands/lib_pb';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
import { Installable } from '../common/protocol/installable';
|
||||
import { ILogger, notEmpty } from '@theia/core';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
|
||||
@injectable()
|
||||
export class LibraryServiceImpl implements LibraryService {
|
||||
|
||||
@inject(ILogger)
|
||||
protected logger: ILogger;
|
||||
|
||||
@inject(CoreClientProvider)
|
||||
protected readonly coreClientProvider: CoreClientProvider;
|
||||
|
||||
@inject(ToolOutputServiceServer)
|
||||
protected readonly toolOutputService: ToolOutputServiceServer;
|
||||
|
||||
async search(options: { query?: string }): Promise<Library[]> {
|
||||
protected ready = new Deferred<void>();
|
||||
protected client: LibraryServiceClient | undefined;
|
||||
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
this.coreClientProvider.client().then(client => {
|
||||
if (client) {
|
||||
this.ready.resolve();
|
||||
} else {
|
||||
this.coreClientProvider.onClientReady(() => this.ready.resolve());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async search(options: { query?: string }): Promise<LibraryPackage[]> {
|
||||
await this.ready.promise;
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return [];
|
||||
@@ -71,9 +91,74 @@ export class LibraryServiceImpl implements LibraryService {
|
||||
return items;
|
||||
}
|
||||
|
||||
async install(options: { item: Library, version?: Installable.Version }): Promise<void> {
|
||||
const library = options.item;
|
||||
const version = !!options.version ? options.version : library.availableVersions[0];
|
||||
async list({ fqbn }: { fqbn?: string | undefined }): Promise<LibraryPackage[]> {
|
||||
await this.ready.promise;
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return [];
|
||||
}
|
||||
const { client, instance } = coreClient;
|
||||
|
||||
const req = new LibraryListReq();
|
||||
req.setInstance(instance);
|
||||
req.setAll(true);
|
||||
const resp = await new Promise<LibraryListResp>((resolve, reject) => client.libraryList(req, ((error, resp) => !!error ? reject(error) : resolve(resp))));
|
||||
const x = resp.getInstalledLibraryList().map(item => {
|
||||
const release = item.getRelease();
|
||||
const library = item.getLibrary();
|
||||
if (!release || !library) {
|
||||
return undefined;
|
||||
}
|
||||
// https://arduino.github.io/arduino-cli/latest/rpc/commands/#librarylocation
|
||||
// 0: In the libraries subdirectory of the Arduino IDE installation. (`ide_builtin`)
|
||||
// 1: In the libraries subdirectory of the user directory (sketchbook). (`user`)
|
||||
// 2: In the libraries subdirectory of a platform. (`platform_builtin`)
|
||||
// 3: When LibraryLocation is used in a context where a board is specified, this indicates the library is
|
||||
// in the libraries subdirectory of a platform referenced by the board's platform. (`referenced_platform_builtin`)
|
||||
// If 0, we ignore it.
|
||||
// If 1, we include always.
|
||||
// If 2, we include iff `fqbn` is specified and the platform matches.
|
||||
// if 3, TODO
|
||||
const location = library.getLocation();
|
||||
|
||||
if (location === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (location === 2) {
|
||||
if (!fqbn) {
|
||||
return undefined;
|
||||
}
|
||||
const architectures = library.getArchitecturesList();
|
||||
const [platform] = library.getContainerPlatform().split(':');
|
||||
if (!platform) {
|
||||
return undefined;
|
||||
}
|
||||
const [boardPlatform, boardArchitecture] = fqbn.split(':');
|
||||
if (boardPlatform !== platform || architectures.indexOf(boardArchitecture) === -1) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const installedVersion = library.getVersion();
|
||||
return toLibrary({
|
||||
name: library.getName(),
|
||||
installedVersion,
|
||||
installable: true,
|
||||
description: library.getSentence(),
|
||||
summary: library.getParagraph(),
|
||||
includes: release.getProvidesIncludesList(),
|
||||
moreInfoLink: library.getWebsite()
|
||||
}, release, [library.getVersion()]);
|
||||
}).filter(notEmpty);
|
||||
console.log(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
async install(options: { item: LibraryPackage, version?: Installable.Version }): Promise<void> {
|
||||
await this.ready.promise;
|
||||
const item = options.item;
|
||||
const version = !!options.version ? options.version : item.availableVersions[0];
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return;
|
||||
@@ -82,9 +167,10 @@ export class LibraryServiceImpl implements LibraryService {
|
||||
|
||||
const req = new LibraryInstallReq();
|
||||
req.setInstance(instance);
|
||||
req.setName(library.name);
|
||||
req.setName(item.name);
|
||||
req.setVersion(version);
|
||||
|
||||
console.info('>>> Starting library package installation...', item);
|
||||
const resp = client.libraryInstall(req);
|
||||
resp.on('data', (r: LibraryInstallResp) => {
|
||||
const prog = r.getProgress();
|
||||
@@ -96,10 +182,18 @@ export class LibraryServiceImpl implements LibraryService {
|
||||
resp.on('end', resolve);
|
||||
resp.on('error', reject);
|
||||
});
|
||||
|
||||
if (this.client) {
|
||||
const items = await this.search({});
|
||||
const updated = items.find(other => LibraryPackage.equals(other, item)) || item;
|
||||
this.client.notifyInstalled({ item: updated });
|
||||
}
|
||||
|
||||
console.info('<<< Library package installation done.', item);
|
||||
}
|
||||
|
||||
async uninstall(options: { item: Library }): Promise<void> {
|
||||
const library = options.item;
|
||||
async uninstall(options: { item: LibraryPackage }): Promise<void> {
|
||||
const item = options.item;
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return;
|
||||
@@ -108,14 +202,15 @@ export class LibraryServiceImpl implements LibraryService {
|
||||
|
||||
const req = new LibraryUninstallReq();
|
||||
req.setInstance(instance);
|
||||
req.setName(library.name);
|
||||
req.setVersion(library.installedVersion!);
|
||||
req.setName(item.name);
|
||||
req.setVersion(item.installedVersion!);
|
||||
|
||||
console.info('>>> Starting library package uninstallation...', item);
|
||||
let logged = false;
|
||||
const resp = client.libraryUninstall(req);
|
||||
resp.on('data', (_: LibraryUninstallResp) => {
|
||||
if (!logged) {
|
||||
this.toolOutputService.append({ tool: 'library', chunk: `uninstalling ${library.name}:${library.installedVersion}%\n` });
|
||||
this.toolOutputService.append({ tool: 'library', chunk: `uninstalling ${item.name}:${item.installedVersion}%\n` });
|
||||
logged = true;
|
||||
}
|
||||
});
|
||||
@@ -123,11 +218,25 @@ export class LibraryServiceImpl implements LibraryService {
|
||||
resp.on('end', resolve);
|
||||
resp.on('error', reject);
|
||||
});
|
||||
if (this.client) {
|
||||
this.client.notifyUninstalled({ item });
|
||||
}
|
||||
console.info('<<< Library package uninstallation done.', item);
|
||||
}
|
||||
|
||||
setClient(client: LibraryServiceClient | undefined): void {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.logger.info('>>> Disposing library service...');
|
||||
this.client = undefined;
|
||||
this.logger.info('<<< Disposed library service.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function toLibrary(tpl: Partial<Library>, release: LibraryRelease, availableVersions: string[]): Library {
|
||||
function toLibrary(tpl: Partial<LibraryPackage>, release: LibraryRelease, availableVersions: string[]): LibraryPackage {
|
||||
return {
|
||||
name: '',
|
||||
installable: false,
|
||||
@@ -135,6 +244,7 @@ function toLibrary(tpl: Partial<Library>, release: LibraryRelease, availableVers
|
||||
|
||||
author: release.getAuthor(),
|
||||
availableVersions,
|
||||
includes: release.getProvidesIncludesList(),
|
||||
description: release.getSentence(),
|
||||
moreInfoLink: release.getWebsite(),
|
||||
summary: release.getParagraph()
|
||||
|
||||
@@ -19,6 +19,8 @@ const MAX_FILESYSTEM_DEPTH = 40;
|
||||
|
||||
const WIN32_DRIVE_REGEXP = /^[a-zA-Z]:\\/;
|
||||
|
||||
const prefix = '.arduinoProIDE-unsaved';
|
||||
|
||||
// TODO: `fs`: use async API
|
||||
@injectable()
|
||||
export class SketchesServiceImpl implements SketchesService, BackendApplicationContribution {
|
||||
@@ -205,6 +207,22 @@ export class SketchesServiceImpl implements SketchesService, BackendApplicationC
|
||||
}
|
||||
}
|
||||
|
||||
async cloneExample(uri: string): Promise<Sketch> {
|
||||
const sketch = await this.loadSketch(uri);
|
||||
const parentPath = await new Promise<string>((resolve, reject) => {
|
||||
this.temp.mkdir({ prefix }, (err, dirPath) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(dirPath);
|
||||
})
|
||||
});
|
||||
const destinationUri = FileUri.create(path.join(parentPath, sketch.name)).toString();
|
||||
const copiedSketchUri = await this.copy(sketch, { destinationUri });
|
||||
return this.loadSketch(copiedSketchUri);
|
||||
}
|
||||
|
||||
protected async simpleLocalWalk(
|
||||
root: string,
|
||||
maxDepth: number,
|
||||
@@ -258,15 +276,15 @@ export class SketchesServiceImpl implements SketchesService, BackendApplicationC
|
||||
async createNewSketch(): Promise<Sketch> {
|
||||
const monthNames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
|
||||
const today = new Date();
|
||||
const parent = await new Promise<string>((resolve, reject) => {
|
||||
this.temp.mkdir({ prefix: '.arduinoProIDE-unsaved' }, (err, dirPath) => {
|
||||
const parentPath = await new Promise<string>((resolve, reject) => {
|
||||
this.temp.mkdir({ prefix }, (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);
|
||||
@@ -286,7 +304,7 @@ export class SketchesServiceImpl implements SketchesService, BackendApplicationC
|
||||
throw new Error('Cannot create a unique sketch name');
|
||||
}
|
||||
|
||||
const sketchDir = path.join(parent, sketchName)
|
||||
const sketchDir = path.join(parentPath, sketchName)
|
||||
const sketchFile = path.join(sketchDir, `${sketchName}.ino`);
|
||||
await fs.mkdirp(sketchDir);
|
||||
await fs.writeFile(sketchFile, `void setup() {
|
||||
@@ -346,7 +364,7 @@ void loop() {
|
||||
temp = firstToLowerCase(temp);
|
||||
}
|
||||
}
|
||||
return sketchPath.indexOf('.arduinoProIDE-unsaved') !== -1 && sketchPath.startsWith(temp);
|
||||
return sketchPath.indexOf(prefix) !== -1 && sketchPath.startsWith(temp);
|
||||
}
|
||||
|
||||
async copy(sketch: Sketch, { destinationUri }: { destinationUri: string }): Promise<string> {
|
||||
|
||||
Reference in New Issue
Block a user