diff --git a/package.json b/package.json index 510d902..268aa55 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,22 @@ "command": "globalCommandExplorer.delete", "title": "Delete" }, + { + "command": "workSpaceCommandExecuter.watch", + "title": "Watch", + "icon": { + "light": "resources/light/watch.svg", + "dark": "resources/dark/watch.svg" + } + }, + { + "command": "globalCommandExecuter.watch", + "title": "Watch", + "icon": { + "light": "resources/light/watch.svg", + "dark": "resources/dark/watch.svg" + } + }, { "command": "workSpaceCommandExecuter.execute", "title": "Execute", @@ -206,15 +222,25 @@ } ], "view/item/context": [ + { + "command": "workSpaceCommandExecuter.watch", + "when": "view == workSpaceCommandExplorer && viewItem == file", + "group": "inline@0" + }, + { + "command": "globalCommandExecuter.watch", + "when": "view == globalCommandExplorer && viewItem == file", + "group": "inline@0" + }, { "command": "workSpaceCommandExecuter.execute", "when": "view == workSpaceCommandExplorer && viewItem == file", - "group": "inline" + "group": "inline@1" }, { "command": "globalCommandExecuter.execute", "when": "view == globalCommandExplorer && viewItem == file", - "group": "inline" + "group": "inline@1" }, { "command": "workSpaceCommandExplorer.delete", diff --git a/resources/dark/watch.svg b/resources/dark/watch.svg new file mode 100644 index 0000000..4608c4e --- /dev/null +++ b/resources/dark/watch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/light/watch.svg b/resources/light/watch.svg new file mode 100644 index 0000000..a906a6b --- /dev/null +++ b/resources/light/watch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/commandExecuter.ts b/src/commandExecuter.ts index d7c7ebf..cfcf5f2 100644 --- a/src/commandExecuter.ts +++ b/src/commandExecuter.ts @@ -7,27 +7,31 @@ export class CommandExecuter { constructor(viewId: string, context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand(`${viewId}.execute`, (element: Entry) => this.executeCommand(element))); + context.subscriptions.push(vscode.commands.registerCommand(`${viewId}.watch`, (element: Entry) => this.watchCommandTime(element))); } - private executeCommand(element: Entry){ + private async executeCommand(element: Entry, needsWatchTime: boolean = false) { const command: Command = JSON.parse(fs.readFileSync(element.uri.fsPath, 'utf8')); this.ensureTerminalExists(); - if(vscode.window.terminals.length === 1){ + if (vscode.window.terminals.length === 1) { const terminal = vscode.window.terminals[0]; terminal.show(); console.log(`execute $ ${command.script}`); terminal.sendText(command.script ? command.script : ''); + if (needsWatchTime) { this.startWatch(element, command) } + await this.progressBar(command); } else { - this.selectTerminal().then(terminal => { - if (terminal) { - terminal.show(); - console.log(`execute $ ${command.script}`); - terminal.sendText(command.script ? command.script : ''); - } else { - console.error('Selected Terminal is not exist'); - vscode.window.showErrorMessage('Sorry, Unexpected error has occurred.'); - } - }); + let terminal = await this.selectTerminal() + if (terminal) { + terminal.show(); + console.log(`execute $ ${command.script}`); + terminal.sendText(command.script ? command.script : ''); + if (needsWatchTime) { this.startWatch(element, command) } + await this.progressBar(command); + } else { + console.error('Selected Terminal is not exist'); + vscode.window.showErrorMessage('Sorry, Unexpected error has occurred.'); + } } } @@ -46,11 +50,72 @@ export class CommandExecuter { return item ? item.terminal : undefined; }); } - + private ensureTerminalExists(): void { if (vscode.window.terminals.length === 0) { vscode.window.createTerminal('Command List'); } } + + private async watchCommandTime(element: Entry) { + const value = await vscode.window.showInformationMessage( + "[BETA] Stopwatch.⏱ Do you want to measure time? If recorded, a progress bar will appear next time.", + "Start", + "Cancel" + ); + if (value === 'Start') { + this.executeCommand(element, true); + } + } + + private startWatch = async (element: Entry, command: Command) => { + let start = new Date(); + const value = await vscode.window.showInformationMessage( + "[BETA] Stopwatch.⏱ Record the execution time", + "Completed. Record time", + "Cancel" + ); + if (value === 'Completed. Record time') { + let end = new Date(); + let time = (end.getTime() - start.getTime()) / 1000; + console.log(time); + command.time = time; + await fs.writeFileSync(element.uri.fsPath, this.stringToUnit8Array(JSON.stringify(command))); + await vscode.window.showInformationMessage( + "Congratulations👏 The progress bar will appear next time🥳", + ); + } + } + + private stringToUnit8Array = (s: string): Uint8Array => { + return Uint8Array.from(Buffer.from(s)); + } + private progressBar = async (command?: Command) => { + if (command?.time == null || command.time <= 0) return; + const time = command.time; + + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: "", + cancellable: false + }, async (progress) => { + const refreshTime = 100; // ms + const loopCount = time * 1000 / refreshTime; + for(var index=0; index => { + return new Promise(resolve => { + setTimeout(()=> { + resolve(time); + }, time); + }); + }; + } \ No newline at end of file diff --git a/src/commandExplorer.ts b/src/commandExplorer.ts index 06cf929..55082b7 100644 --- a/src/commandExplorer.ts +++ b/src/commandExplorer.ts @@ -235,7 +235,8 @@ export class FileSystemProvider implements vscode.TreeDataProvider, vscod if (label == null) return; const command: Command = { script: script, - label: label + label: label, + time: file.time }; const fileName = command.label ? command.label : command.script ? command.script : 'No Name'