diff --git a/package.json b/package.json index a97d952f..9f2c694a 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "onCommand:arduino.rebuildIntelliSenseConfig", "onCommand:arduino.selectProgrammer", "onCommand:arduino.selectSerialPort", + "onCommand:arduino.selectSketch", "onCommand:arduino.changeBaudRate", "onCommand:arduino.openSerialMonitor", "onCommand:arduino.sendMessageToSerialPort", @@ -115,6 +116,10 @@ "command": "arduino.selectProgrammer", "title": "Arduino: Select Programmer" }, + { + "command": "arduino.selectSketch", + "title": "Arduino: Select Sketch" + }, { "command": "arduino.selectSerialPort", "title": "Arduino: Select Serial Port" diff --git a/src/deviceContext.ts b/src/deviceContext.ts index 16451a81..0cfaa358 100644 --- a/src/deviceContext.ts +++ b/src/deviceContext.ts @@ -112,7 +112,7 @@ export class DeviceContext implements IDeviceContext, vscode.Disposable { this._watcher.onDidDelete(() => this.loadContext()); this._vscodeWatcher.onDidDelete(() => this.loadContext()); this._sketchStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, constants.statusBarPriority.SKETCH); - this._sketchStatusBar.command = "arduino.setSketchFile"; + this._sketchStatusBar.command = "arduino.selectSketch"; this._sketchStatusBar.tooltip = "Sketch File"; } } diff --git a/src/extension.ts b/src/extension.ts index 6ae7b0df..b4f6f456 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -156,24 +156,40 @@ export async function activate(context: vscode.ExtensionContext) { return { board: arduinoContextModule.default.boardManager.currentBoard.name }; }); - registerArduinoCommand("arduino.setSketchFile", async () => { + registerArduinoCommand("arduino.selectSketch", async () => { const sketchFileName = deviceContext.sketch; - const newSketchFileName = await vscode.window.showInputBox({ - placeHolder: sketchFileName, - validateInput: (value) => { - if (value && /\.((ino)|(cpp)|c)$/.test(value.trim())) { - return null; - } else { - return "Invalid sketch file name. Should be *.ino/*.cpp/*.c"; - } - }, - }); + + // Include any ino, cpp, or c files under the workspace folder + const includePattern = "**/*.{ino,cpp,c}"; + + // The sketchbook folder may contain hardware & library folders, any sketches under these paths + // should be excluded + const sketchbookPath = arduinoContextModule.default.arduinoApp.settings.sketchbookPath; + const excludePatterns = [ + path.relative(ArduinoWorkspace.rootPath, sketchbookPath + "/hardware/**"), + path.relative(ArduinoWorkspace.rootPath, sketchbookPath + "/libraries/**")]; + + // If an output path is specified, it should be excluded as well + if (deviceContext.output) { + const outputPath = path.relative(ArduinoWorkspace.rootPath, + path.resolve(ArduinoWorkspace.rootPath, deviceContext.output)); + excludePatterns.push(`${outputPath}/**`); + } + const excludePattern = `{${excludePatterns.map((p) => p.replace("\\", "/")).join(",")}}`; + + const fileUris = await vscode.workspace.findFiles(includePattern, excludePattern); + const newSketchFileName = await vscode.window.showQuickPick(fileUris.map((fileUri) => + ({ + label: path.relative(ArduinoWorkspace.rootPath, fileUri.fsPath), + description: fileUri.fsPath, + })), + { placeHolder: sketchFileName, matchOnDescription: true }); if (!newSketchFileName) { return; } - deviceContext.sketch = newSketchFileName; + deviceContext.sketch = newSketchFileName.label; deviceContext.showStatusBar(); }); diff --git a/test/extension.test.ts b/test/extension.test.ts index fb746313..6c91b0e9 100644 --- a/test/extension.test.ts +++ b/test/extension.test.ts @@ -54,7 +54,7 @@ suite("Arduino: Extension Tests", () => { "arduino.showExampleExplorer", "arduino.loadPackages", "arduino.installBoard", - "arduino.setSketchFile", + "arduino.selectSketch", "arduino.cliUpload", "arduino.cliUploadUsingProgrammer", ];