Skip to content

Commit 7a37aa2

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommitted
ATL-78: Implemented include library.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
1 parent 56ff866 commit 7a37aa2

File tree

8 files changed

+200
-120
lines changed

8 files changed

+200
-120
lines changed

arduino-ide-extension/scripts/download-cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
(() => {
1212

13-
const DEFAULT_VERSION = '0.13.0-rc1'; // require('moment')().format('YYYYMMDD');
13+
const DEFAULT_VERSION = '0.13.0-rc2'; // require('moment')().format('YYYYMMDD');
1414

1515
const path = require('path');
1616
const shell = require('shelljs');

arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ import { ExamplesServicePath, ExamplesService } from '../common/protocol/example
122122
import { BuiltInExamples, LibraryExamples } from './contributions/examples';
123123
import { LibraryServiceProvider } from './library/library-service-provider';
124124
import { IncludeLibrary } from './contributions/include-library';
125-
import { IncludeLibraryMenuUpdater } from './library/include-library-menu-updater';
126125

127126
const ElementQueries = require('css-element-queries/src/ElementQueries');
128127

@@ -158,7 +157,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
158157
// Library service
159158
bind(LibraryServiceProvider).toSelf().inSingletonScope();
160159
bind(LibraryServiceServer).toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, LibraryServiceServerPath)).inSingletonScope();
161-
bind(FrontendApplicationContribution).to(IncludeLibraryMenuUpdater).inSingletonScope();
162160

163161
// Library list widget
164162
bind(LibraryListWidget).toSelf();

arduino-ide-extension/src/browser/contributions/examples.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as PQueue from 'p-queue';
12
import { inject, injectable, postConstruct } from 'inversify';
23
import { MenuPath, SubMenuOptions } from '@theia/core/lib/common/menu';
34
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';

arduino-ide-extension/src/browser/contributions/include-library.ts

Lines changed: 129 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,49 @@
1-
import { /*inject,*/ injectable } from 'inversify';
2-
// import { remote } from 'electron';
3-
// import { ArduinoMenus } from '../menu/arduino-menus';
1+
import * as PQueue from 'p-queue';
2+
import { inject, injectable } from 'inversify';
3+
import URI from '@theia/core/lib/common/uri';
4+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
5+
import { EditorManager } from '@theia/editor/lib/browser';
6+
import { MenuModelRegistry, MenuPath } from '@theia/core/lib/common/menu';
7+
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
8+
import { ArduinoMenus } from '../menu/arduino-menus';
9+
import { LibraryPackage, LibraryLocation } from '../../common/protocol';
10+
import { MainMenuManager } from '../../common/main-menu-manager';
11+
import { LibraryListWidget } from '../library/library-list-widget';
12+
import { LibraryServiceProvider } from '../library/library-service-provider';
13+
import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl';
414
import { SketchContribution, Command, CommandRegistry } from './contribution';
5-
import { LibraryPackage } from '../../common/protocol';
6-
// import { SaveAsSketch } from './save-as-sketch';
7-
// import { EditorManager } from '@theia/editor/lib/browser';
8-
// import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
915

1016
@injectable()
1117
export class IncludeLibrary extends SketchContribution {
1218

19+
@inject(CommandRegistry)
20+
protected readonly commandRegistry: CommandRegistry;
21+
22+
@inject(MenuModelRegistry)
23+
protected readonly menuRegistry: MenuModelRegistry;
24+
25+
@inject(MainMenuManager)
26+
protected readonly mainMenuManager: MainMenuManager;
27+
28+
@inject(EditorManager)
29+
protected readonly editorManager: EditorManager;
30+
31+
@inject(LibraryServiceProvider)
32+
protected readonly libraryServiceProvider: LibraryServiceProvider;
33+
34+
@inject(BoardsServiceClientImpl)
35+
protected readonly boardsServiceClient: BoardsServiceClientImpl;
36+
37+
protected readonly queue = new PQueue({ autoStart: true, concurrency: 1 });
38+
protected readonly toDispose = new DisposableCollection();
39+
40+
onStart(): void {
41+
this.updateMenuActions();
42+
this.boardsServiceClient.onBoardsConfigChanged(() => this.updateMenuActions())
43+
this.libraryServiceProvider.onLibraryPackageInstalled(() => this.updateMenuActions());
44+
this.libraryServiceProvider.onLibraryPackageUninstalled(() => this.updateMenuActions());
45+
}
46+
1347
registerCommands(registry: CommandRegistry): void {
1448
registry.registerCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY, {
1549
execute: async arg => {
@@ -20,9 +54,95 @@ export class IncludeLibrary extends SketchContribution {
2054
});
2155
}
2256

57+
protected async updateMenuActions(): Promise<void> {
58+
return this.queue.add(async () => {
59+
this.toDispose.dispose();
60+
this.mainMenuManager.update();
61+
const libraries: LibraryPackage[] = []
62+
const fqbn = this.boardsServiceClient.boardsConfig.selectedBoard?.fqbn;
63+
// Do not show board specific examples, when no board is selected.
64+
if (fqbn) {
65+
libraries.push(...await this.libraryServiceProvider.list({ fqbn }));
66+
}
67+
68+
// `Include Library` submenu
69+
const includeLibMenuPath = [...ArduinoMenus.SKETCH__UTILS_GROUP, '0_include'];
70+
this.menuRegistry.registerSubmenu(includeLibMenuPath, 'Include Library', { order: '1' });
71+
// `Manage Libraries...` group.
72+
this.menuRegistry.registerMenuAction([...includeLibMenuPath, '0_manage'], {
73+
commandId: `${LibraryListWidget.WIDGET_ID}:toggle`,
74+
label: 'Manage Libraries...'
75+
});
76+
this.toDispose.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction({ commandId: `${LibraryListWidget.WIDGET_ID}:toggle` })));
77+
78+
// `Add .ZIP Library...`
79+
// TODO: implement it
80+
81+
// `Arduino libraries`
82+
const packageMenuPath = [...includeLibMenuPath, '2_arduino'];
83+
const userMenuPath = [...includeLibMenuPath, '3_contributed'];
84+
for (const library of libraries) {
85+
this.toDispose.push(this.registerLibrary(library, library.location === LibraryLocation.USER ? userMenuPath : packageMenuPath));
86+
}
87+
88+
this.mainMenuManager.update();
89+
});
90+
}
91+
92+
protected registerLibrary(library: LibraryPackage, menuPath: MenuPath): Disposable {
93+
const commandId = `arduino-include-library--${library.name}:${library.author}`;
94+
const command = { id: commandId };
95+
const handler = { execute: () => this.commandRegistry.executeCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY.id, library) };
96+
const menuAction = { commandId, label: library.name };
97+
this.menuRegistry.registerMenuAction(menuPath, menuAction);
98+
return new DisposableCollection(
99+
this.commandRegistry.registerCommand(command, handler),
100+
Disposable.create(() => this.menuRegistry.unregisterMenuAction(menuAction)),
101+
);
102+
}
103+
23104
protected async includeLibrary(library: LibraryPackage): Promise<void> {
24-
// Always include to the main sketch file unless a c, cpp, or h file is the active one.
25-
console.log('INCLUDE', library);
105+
const sketch = await this.sketchServiceClient.currentSketch();
106+
if (!sketch) {
107+
return;
108+
}
109+
// If the current editor is one of the additional files from the sketch, we use that.
110+
// Otherwise, we pick the editor of the main sketch file.
111+
let codeEditor: monaco.editor.IStandaloneCodeEditor | undefined;
112+
const editor = this.editorManager.currentEditor?.editor;
113+
if (editor instanceof MonacoEditor) {
114+
if (sketch.additionalFileUris.some(uri => uri === editor.uri.toString())) {
115+
codeEditor = editor.getControl();
116+
}
117+
}
118+
119+
if (!codeEditor) {
120+
const widget = await this.editorManager.open(new URI(sketch.mainFileUri));
121+
if (widget.editor instanceof MonacoEditor) {
122+
codeEditor = widget.editor.getControl();
123+
}
124+
}
125+
126+
if (!codeEditor) {
127+
return;
128+
}
129+
130+
const textModel = codeEditor.getModel();
131+
if (!textModel) {
132+
return;
133+
}
134+
const cursorState = codeEditor.getSelections() || [];
135+
const eol = textModel.getEOL();
136+
const includes = library.includes.slice();
137+
includes.push(''); // For the trailing new line.
138+
const text = includes.map(include => include ? `#include <${include}>` : eol).join(eol);
139+
textModel.pushStackElement(); // Start a fresh operation.
140+
textModel.pushEditOperations(cursorState, [{
141+
range: new monaco.Range(1, 1, 1, 1),
142+
text,
143+
forceMoveMarkers: true
144+
}], () => cursorState);
145+
textModel.pushStackElement(); // Make it undoable.
26146
}
27147

28148
}

arduino-ide-extension/src/browser/library/include-library-menu-updater.ts

Lines changed: 0 additions & 94 deletions
This file was deleted.

arduino-ide-extension/src/node/cli-protocol/commands/lib_pb.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,11 @@ export class Library extends jspb.Message {
726726
setExamplesList(value: Array<string>): Library;
727727
addExamples(value: string, index?: number): string;
728728

729+
clearProvidesIncludesList(): void;
730+
getProvidesIncludesList(): Array<string>;
731+
setProvidesIncludesList(value: Array<string>): Library;
732+
addProvidesIncludes(value: string, index?: number): string;
733+
729734

730735
serializeBinary(): Uint8Array;
731736
toObject(includeInstance?: boolean): Library.AsObject;
@@ -764,6 +769,7 @@ export namespace Library {
764769
location: LibraryLocation,
765770
layout: LibraryLayout,
766771
examplesList: Array<string>,
772+
providesIncludesList: Array<string>,
767773
}
768774
}
769775

arduino-ide-extension/src/node/cli-protocol/commands/lib_pb.js

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4762,7 +4762,7 @@ proto.cc.arduino.cli.commands.InstalledLibrary.prototype.hasRelease = function()
47624762
* @private {!Array<number>}
47634763
* @const
47644764
*/
4765-
proto.cc.arduino.cli.commands.Library.repeatedFields_ = [8,9,26];
4765+
proto.cc.arduino.cli.commands.Library.repeatedFields_ = [8,9,26,27];
47664766

47674767

47684768

@@ -4818,7 +4818,8 @@ proto.cc.arduino.cli.commands.Library.toObject = function(includeInstance, msg)
48184818
propertiesMap: (f = msg.getPropertiesMap()) ? f.toObject(includeInstance, undefined) : [],
48194819
location: jspb.Message.getFieldWithDefault(msg, 24, 0),
48204820
layout: jspb.Message.getFieldWithDefault(msg, 25, 0),
4821-
examplesList: (f = jspb.Message.getRepeatedField(msg, 26)) == null ? undefined : f
4821+
examplesList: (f = jspb.Message.getRepeatedField(msg, 26)) == null ? undefined : f,
4822+
providesIncludesList: (f = jspb.Message.getRepeatedField(msg, 27)) == null ? undefined : f
48224823
};
48234824

48244825
if (includeInstance) {
@@ -4953,6 +4954,10 @@ proto.cc.arduino.cli.commands.Library.deserializeBinaryFromReader = function(msg
49534954
var value = /** @type {string} */ (reader.readString());
49544955
msg.addExamples(value);
49554956
break;
4957+
case 27:
4958+
var value = /** @type {string} */ (reader.readString());
4959+
msg.addProvidesIncludes(value);
4960+
break;
49564961
default:
49574962
reader.skipField();
49584963
break;
@@ -5147,6 +5152,13 @@ proto.cc.arduino.cli.commands.Library.serializeBinaryToWriter = function(message
51475152
f
51485153
);
51495154
}
5155+
f = message.getProvidesIncludesList();
5156+
if (f.length > 0) {
5157+
writer.writeRepeatedString(
5158+
27,
5159+
f
5160+
);
5161+
}
51505162
};
51515163

51525164

@@ -5643,6 +5655,43 @@ proto.cc.arduino.cli.commands.Library.prototype.clearExamplesList = function() {
56435655
};
56445656

56455657

5658+
/**
5659+
* repeated string provides_includes = 27;
5660+
* @return {!Array<string>}
5661+
*/
5662+
proto.cc.arduino.cli.commands.Library.prototype.getProvidesIncludesList = function() {
5663+
return /** @type {!Array<string>} */ (jspb.Message.getRepeatedField(this, 27));
5664+
};
5665+
5666+
5667+
/**
5668+
* @param {!Array<string>} value
5669+
* @return {!proto.cc.arduino.cli.commands.Library} returns this
5670+
*/
5671+
proto.cc.arduino.cli.commands.Library.prototype.setProvidesIncludesList = function(value) {
5672+
return jspb.Message.setField(this, 27, value || []);
5673+
};
5674+
5675+
5676+
/**
5677+
* @param {string} value
5678+
* @param {number=} opt_index
5679+
* @return {!proto.cc.arduino.cli.commands.Library} returns this
5680+
*/
5681+
proto.cc.arduino.cli.commands.Library.prototype.addProvidesIncludes = function(value, opt_index) {
5682+
return jspb.Message.addToRepeatedField(this, 27, value, opt_index);
5683+
};
5684+
5685+
5686+
/**
5687+
* Clears the list making it empty but non-null.
5688+
* @return {!proto.cc.arduino.cli.commands.Library} returns this
5689+
*/
5690+
proto.cc.arduino.cli.commands.Library.prototype.clearProvidesIncludesList = function() {
5691+
return this.setProvidesIncludesList([]);
5692+
};
5693+
5694+
56465695
/**
56475696
* @enum {number}
56485697
*/

0 commit comments

Comments
 (0)