mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-24 11:46:32 +00:00
fixed fuzzy. added proper boost.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
fdc5814e66
commit
8aa08cbf6e
@ -42,34 +42,36 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
|
||||
const { fqbn } = selectedBoard;
|
||||
if (fqbn) {
|
||||
const { configOptions, programmers, selectedProgrammer } = await this.boardsDataStore.getData(fqbn);
|
||||
const boardsConfigMenuPath = [...ArduinoMenus.TOOLS, '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<string, Disposable & { label: string }>()
|
||||
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 }));
|
||||
if (configOptions.length) {
|
||||
const boardsConfigMenuPath = [...ArduinoMenus.TOOLS, '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<string, Disposable & { label: string }>()
|
||||
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));
|
||||
})
|
||||
]);
|
||||
}
|
||||
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, 'z02_programmers'];
|
||||
const label = selectedProgrammer ? `Programmer: ${selectedProgrammer.name}` : 'Programmer'
|
||||
const label = selectedProgrammer ? `Programmer: "${selectedProgrammer.name}"` : 'Programmer'
|
||||
this.menuRegistry.registerSubmenu(programmersMenuPath, label);
|
||||
for (const programmer of programmers) {
|
||||
const { id, name } = programmer;
|
||||
|
@ -8,6 +8,12 @@ import { RecursiveRequired } from '../../common/types';
|
||||
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 {
|
||||
@ -168,13 +174,28 @@ export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApp
|
||||
const coresFilter = !!cores && cores.length
|
||||
? ((toFilter: { packageName: string }) => cores.some(core => core === toFilter.packageName))
|
||||
: () => true;
|
||||
const fuzzyFilter = !!query
|
||||
? ((toFilter: Board) => !!monaco.filters.matchesFuzzy(query, toFilter.name, true))
|
||||
: () => true
|
||||
return boards
|
||||
.filter(coresFilter)
|
||||
.filter(fuzzyFilter)
|
||||
.sort(Board.compare)
|
||||
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).sort((left, right) => compareEntries(left, right, normalizedQuery)).map(({ board }) => board);
|
||||
}
|
||||
|
||||
get boardsConfig(): BoardsConfig.Config {
|
||||
|
@ -219,7 +219,7 @@ ${value}
|
||||
}
|
||||
|
||||
protected async run(commandId: string): Promise<any> {
|
||||
const editor = await this.current();
|
||||
const editor = await this.current(); // TODO: this should be the active monaco editor and not Theia editor. e.g: Output
|
||||
if (editor) {
|
||||
const action = editor.getControl().getAction(commandId);
|
||||
if (action) {
|
||||
|
367
arduino-ide-extension/src/browser/theia/monaco/comparers.ts
Normal file
367
arduino-ide-extension/src/browser/theia/monaco/comparers.ts
Normal file
@ -0,0 +1,367 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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<T> {
|
||||
|
||||
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<string> : ([] as Array<string>);
|
||||
|
||||
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
|
||||
else if (elementAPrefixMatch && elementBPrefixMatch) {
|
||||
if (elementAName.length < elementBName.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (elementAName.length > elementBName.length) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -276,6 +276,7 @@ export interface Programmer {
|
||||
readonly id: string;
|
||||
}
|
||||
export namespace Programmer {
|
||||
|
||||
export function equals(left: Programmer | undefined, right: Programmer | undefined): boolean {
|
||||
if (!left) {
|
||||
return !right;
|
||||
@ -285,6 +286,15 @@ export namespace Programmer {
|
||||
}
|
||||
return left.id === right.id && left.name === right.name && left.platform === right.platform;
|
||||
}
|
||||
|
||||
export function toString({ id, platform }: Programmer): string {
|
||||
const [vendor,] = platform.split('@');
|
||||
if (!vendor) {
|
||||
throw new Error(`Could not extract vendor from platform: '${platform}'.`);
|
||||
}
|
||||
return `${vendor}:${id}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace Board {
|
||||
@ -357,5 +367,4 @@ export namespace Board {
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { inject, injectable, postConstruct } from 'inversify';
|
||||
import { FileSystem } from '@theia/filesystem/lib/common/filesystem';
|
||||
import { CoreService, CoreServiceClient } from '../common/protocol/core-service';
|
||||
import { CompileReq, CompileResp } from './cli-protocol/commands/compile_pb';
|
||||
import { BoardsService } from '../common/protocol/boards-service';
|
||||
import { BoardsService, Programmer } from '../common/protocol/boards-service';
|
||||
import { CoreClientProvider } from './core-client-provider';
|
||||
import * as path from 'path';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
@ -62,7 +62,7 @@ export class CoreServiceImpl implements CoreService {
|
||||
compilerReq.setVerbose(true);
|
||||
compilerReq.setQuiet(false);
|
||||
if (options.programmer) {
|
||||
compilerReq.setProgrammer(options.programmer.id);
|
||||
compilerReq.setProgrammer(Programmer.toString(options.programmer));
|
||||
}
|
||||
|
||||
const result = client.compile(compilerReq);
|
||||
@ -108,7 +108,7 @@ export class CoreServiceImpl implements CoreService {
|
||||
uploadReq.setFqbn(fqbn);
|
||||
uploadReq.setPort(options.port);
|
||||
if (options.programmer) {
|
||||
uploadReq.setProgrammer(options.programmer.id);
|
||||
uploadReq.setProgrammer(Programmer.toString(options.programmer));
|
||||
}
|
||||
const result = client.upload(uploadReq);
|
||||
|
||||
|
@ -72,7 +72,7 @@ export class SketchesServiceImpl implements SketchesService, BackendApplicationC
|
||||
&& fs.lstatSync(filePath).isFile()) {
|
||||
const uri = FileUri.create(filePath).toString();
|
||||
if (fileName === basename + '.ino') {
|
||||
uris.unshift(uri);
|
||||
uris.unshift(uri); // The sketch file is the first.
|
||||
} else {
|
||||
uris.push(uri);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user