Skip to content

Commit 7b7dccb

Browse files
committed
Resolve #88: Run file through context menu of file explorer
1 parent 3571b9d commit 7b7dccb

File tree

6 files changed

+85
-50
lines changed

6 files changed

+85
-50
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
### 0.8.0 (2017-10-25)
2+
* [#88](https://github.com/formulahendry/vscode-code-runner/issues/88): Run file through context menu of file explorer
3+
14
### 0.7.4 (2017-10-20)
25
* [#191](https://github.com/formulahendry/vscode-code-runner/issues/191): Stop running code when VS Code is closed
36

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ If you like this extension, you could donate via **[PayPal](https://www.paypal.m
1313
## Features
1414

1515
* Run code file of current active Text Editor
16+
* Run code file through context menu of file explorer
1617
* Run selected code snippet in Text Editor
1718
* Run custom command
1819
* Stop code running
@@ -23,8 +24,16 @@ If you like this extension, you could donate via **[PayPal](https://www.paypal.m
2324

2425
## Usages
2526

26-
* Open code file or select code snippet in Text Editor, then use shortcut `Ctrl+Alt+N`, or press `F1` and then select/type `Run Code`, or right click the Text Editor and then click `Run Code` in editor context menu, or click `Run Code` button in editor title menu, the code will run and the output will be shown in the Output Window.
27-
* To stop the running code, use shortcut `Ctrl+Alt+M`, or press `F1` and then select/type `Stop Code Run`, or right click the Output Channel and then click `Stop Code Run` in context menu
27+
* To run code:
28+
* use shortcut `Ctrl+Alt+N`
29+
* or press `F1` and then select/type `Run Code`,
30+
* or right click the Text Editor and then click `Run Code` in editor context menu
31+
* or click `Run Code` button in editor title menu
32+
* or click `Run Code` button in context menu of file explorer
33+
* To stop the running code:
34+
* use shortcut `Ctrl+Alt+M`
35+
* or press `F1` and then select/type `Stop Code Run`
36+
* or right click the Output Channel and then click `Stop Code Run` in context menu
2837

2938
![Usage](images/usage.gif)
3039

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "code-runner",
33
"displayName": "Code Runner",
44
"description": "Run C, C++, Java, JS, PHP, Python, Perl, Ruby, Go, Lua, Groovy, PowerShell, CMD, BASH, F#, C#, VBScript, TypeScript, CoffeeScript, Scala, Swift, Julia, Crystal, OCaml, R, AppleScript, Elixir, VB.NET, Clojure, Haxe, Objective-C, Rust, Racket, AutoHotkey, AutoIt, Kotlin, Dart, Pascal, Haskell, Nim, D",
5-
"version": "0.7.4",
5+
"version": "0.8.0",
66
"publisher": "formulahendry",
77
"icon": "images/logo.png",
88
"engines": {
@@ -94,6 +94,13 @@
9494
"command": "code-runner.run",
9595
"group": "navigation"
9696
}
97+
],
98+
"explorer/context": [
99+
{
100+
"when": "!explorerResourceIsFolder",
101+
"command": "code-runner.run",
102+
"group": "navigation"
103+
}
97104
]
98105
},
99106
"configuration": {

src/appInsightsClient.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ export class AppInsightsClient {
1414
this._enableAppInsights = config.get<boolean>("enableAppInsights");
1515
}
1616

17-
public sendEvent(eventName: string): void {
17+
public sendEvent(eventName: string, properties?: { [key: string]: string; }): void {
1818
if (this._enableAppInsights) {
1919
for (const i in compilers) {
2020
if (eventName.indexOf(compilers[i] + " ") >= 0) {
2121
eventName = compilers[i];
2222
break;
2323
}
2424
}
25-
this._client.trackEvent(eventName === "" ? "bat" : eventName);
25+
this._client.trackEvent(eventName === "" ? "bat" : eventName, properties);
2626
}
2727
}
2828
}

src/codeManager.ts

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use strict";
22
import * as fs from "fs";
33
import * as os from "os";
4-
import { dirname, join } from "path";
4+
import { dirname, extname, join } from "path";
55
import * as vscode from "vscode";
66
import { AppInsightsClient } from "./appInsightsClient";
77

@@ -16,6 +16,8 @@ export class CodeManager implements vscode.Disposable {
1616
private _isTmpFile: boolean;
1717
private _languageId: string;
1818
private _cwd: string;
19+
private _runFromExplorer: boolean;
20+
private _document: vscode.TextDocument;
1921
private _workspaceFolder: string;
2022
private _config: vscode.WorkspaceConfiguration;
2123
private _appInsightsClient: AppInsightsClient;
@@ -30,29 +32,36 @@ export class CodeManager implements vscode.Disposable {
3032
this._terminal = null;
3133
}
3234

33-
public run(languageId: string = null): void {
35+
public async run(languageId: string = null, fileUri: vscode.Uri = null) {
3436
if (this._isRunning) {
3537
vscode.window.showInformationMessage("Code is already running!");
3638
return;
3739
}
3840

39-
const editor = vscode.window.activeTextEditor;
40-
if (!editor) {
41-
vscode.window.showInformationMessage("No code found or selected.");
42-
return;
41+
if (fileUri) {
42+
this._runFromExplorer = true;
43+
this._document = await vscode.workspace.openTextDocument(fileUri);
44+
} else {
45+
const editor = vscode.window.activeTextEditor;
46+
if (editor) {
47+
this._document = editor.document;
48+
} else {
49+
vscode.window.showInformationMessage("No code found or selected.");
50+
return;
51+
}
4352
}
4453

45-
this.initialize(editor);
54+
this.initialize();
4655

47-
const fileExtension = this.getFileExtension(editor);
56+
const fileExtension = extname(this._document.fileName);
4857
const executor = this.getExecutor(languageId, fileExtension);
4958
// undefined or null
5059
if (executor == null) {
5160
vscode.window.showInformationMessage("Code language not supported or defined.");
5261
return;
5362
}
5463

55-
this.getCodeFileAndExecute(editor, fileExtension, executor);
64+
this.getCodeFileAndExecute(fileExtension, executor);
5665
}
5766

5867
public runCustomCommand(): void {
@@ -62,13 +71,17 @@ export class CodeManager implements vscode.Disposable {
6271
}
6372

6473
const editor = vscode.window.activeTextEditor;
65-
this.initialize(editor);
74+
if (editor) {
75+
this._document = editor.document;
76+
}
77+
78+
this.initialize();
6679

6780
const executor = this._config.get<string>("customCommand");
6881

69-
if (editor) {
70-
const fileExtension = this.getFileExtension(editor);
71-
this.getCodeFileAndExecute(editor, fileExtension, executor, false);
82+
if (this._document) {
83+
const fileExtension = extname(this._document.fileName);
84+
this.getCodeFileAndExecute(fileExtension, executor, false);
7285
} else {
7386
this.executeCommand(executor, false);
7487
}
@@ -102,16 +115,16 @@ export class CodeManager implements vscode.Disposable {
102115
}
103116
}
104117

105-
private initialize(editor: vscode.TextEditor): void {
118+
private initialize(): void {
106119
this._config = this.getConfiguration();
107120
this._cwd = this._config.get<string>("cwd");
108121
if (this._cwd) {
109122
return;
110123
}
111-
this._workspaceFolder = this.getWorkspaceFolder(editor);
124+
this._workspaceFolder = this.getWorkspaceFolder();
112125
if ((this._config.get<boolean>("fileDirectoryAsCwd") || !this._workspaceFolder)
113-
&& editor && !editor.document.isUntitled) {
114-
this._cwd = dirname(editor.document.fileName);
126+
&& this._document && !this._document.isUntitled) {
127+
this._cwd = dirname(this._document.fileName);
115128
} else {
116129
this._cwd = this._workspaceFolder;
117130
}
@@ -122,18 +135,17 @@ export class CodeManager implements vscode.Disposable {
122135
}
123136

124137
private getConfiguration(): vscode.WorkspaceConfiguration {
125-
const editor = vscode.window.activeTextEditor;
126-
if (editor && editor.document) {
127-
return vscode.workspace.getConfiguration("code-runner", editor.document.uri);
138+
if (this._document) {
139+
return vscode.workspace.getConfiguration("code-runner", this._document.uri);
128140
} else {
129141
return vscode.workspace.getConfiguration("code-runner");
130142
}
131143
}
132144

133-
private getWorkspaceFolder(editor: vscode.TextEditor): string {
145+
private getWorkspaceFolder(): string {
134146
if (vscode.workspace.workspaceFolders) {
135-
if (editor && editor.document) {
136-
const workspaceFolder = vscode.workspace.getWorkspaceFolder(editor.document.uri);
147+
if (this._document) {
148+
const workspaceFolder = vscode.workspace.getWorkspaceFolder(this._document.uri);
137149
if (workspaceFolder) {
138150
return workspaceFolder.uri.fsPath;
139151
}
@@ -144,13 +156,17 @@ export class CodeManager implements vscode.Disposable {
144156
}
145157
}
146158

147-
private getCodeFileAndExecute(editor: vscode.TextEditor, fileExtension: string, executor: string, appendFile: boolean = true): any {
148-
const selection = editor.selection;
159+
private getCodeFileAndExecute(fileExtension: string, executor: string, appendFile: boolean = true): any {
160+
let selection;
161+
const activeTextEditor = vscode.window.activeTextEditor;
162+
if (activeTextEditor) {
163+
selection = activeTextEditor.selection;
164+
}
149165
const ignoreSelection = this._config.get<boolean>("ignoreSelection");
150166

151-
if ((selection.isEmpty || ignoreSelection) && !editor.document.isUntitled) {
167+
if ((this._runFromExplorer || !selection || selection.isEmpty || ignoreSelection) && !this._document.isUntitled) {
152168
this._isTmpFile = false;
153-
this._codeFile = editor.document.fileName;
169+
this._codeFile = this._document.fileName;
154170

155171
if (this._config.get<boolean>("saveAllFilesBeforeRun")) {
156172
return vscode.workspace.saveAll().then(() => {
@@ -159,12 +175,13 @@ export class CodeManager implements vscode.Disposable {
159175
}
160176

161177
if (this._config.get<boolean>("saveFileBeforeRun")) {
162-
return editor.document.save().then(() => {
178+
return this._document.save().then(() => {
163179
this.executeCommand(executor, appendFile);
164180
});
165181
}
166182
} else {
167-
let text = (selection.isEmpty || ignoreSelection) ? editor.document.getText() : editor.document.getText(selection);
183+
let text = (this._runFromExplorer || !selection || selection.isEmpty || ignoreSelection) ?
184+
this._document.getText() : this._document.getText(selection);
168185

169186
if (this._languageId === "php") {
170187
text = text.trim();
@@ -174,7 +191,7 @@ export class CodeManager implements vscode.Disposable {
174191
}
175192

176193
this._isTmpFile = true;
177-
const folder = editor.document.isUntitled ? this._cwd : dirname(editor.document.fileName);
194+
const folder = this._document.isUntitled ? this._cwd : dirname(this._document.fileName);
178195
this.createRandomFile(text, folder, fileExtension);
179196
}
180197

@@ -205,7 +222,7 @@ export class CodeManager implements vscode.Disposable {
205222
}
206223

207224
private getExecutor(languageId: string, fileExtension: string): string {
208-
this._languageId = languageId === null ? vscode.window.activeTextEditor.document.languageId : languageId;
225+
this._languageId = languageId === null ? this._document.languageId : languageId;
209226
const executorMap = this._config.get<any>("executorMap");
210227
let executor = executorMap[this._languageId];
211228
// executor is undefined or null
@@ -224,16 +241,6 @@ export class CodeManager implements vscode.Disposable {
224241
return executor;
225242
}
226243

227-
private getFileExtension(editor: vscode.TextEditor): string {
228-
const fileName = editor.document.fileName;
229-
const index = fileName.lastIndexOf(".");
230-
if (index !== -1) {
231-
return fileName.substr(index);
232-
} else {
233-
return "";
234-
}
235-
}
236-
237244
private executeCommand(executor: string, appendFile: boolean = true) {
238245
if (this._config.get<boolean>("runInTerminal")) {
239246
this.executeCommandInTerminal(executor, appendFile);
@@ -376,7 +383,7 @@ export class CodeManager implements vscode.Disposable {
376383
}
377384
this._terminal.show(this._config.get<boolean>("preserveFocus"));
378385
executor = this.changeExecutorFromCmdToPs(executor);
379-
this._appInsightsClient.sendEvent(executor);
386+
this.sendRunEvent(executor, true);
380387
let command = this.getFinalCommandToRunCodeFile(executor, appendFile);
381388
command = this.changeFilePathForBashOnWindows(command);
382389
if (this._config.get<boolean>("clearPreviousOutput") && !isNewTerminal) {
@@ -402,7 +409,7 @@ export class CodeManager implements vscode.Disposable {
402409
if (showExecutionMessage) {
403410
this._outputChannel.appendLine("[Running] " + command);
404411
}
405-
this._appInsightsClient.sendEvent(executor);
412+
this.sendRunEvent(executor, false);
406413
const startTime = new Date();
407414
this._process = exec(command, { cwd: this._cwd });
408415

@@ -428,4 +435,13 @@ export class CodeManager implements vscode.Disposable {
428435
}
429436
});
430437
}
438+
439+
private sendRunEvent(executor: string, runFromTerminal: boolean) {
440+
const properties = {
441+
runFromTerminal: runFromTerminal.toString(),
442+
runFromExplorer: this._runFromExplorer.toString(),
443+
isTmpFile: this._isTmpFile.toString(),
444+
};
445+
this._appInsightsClient.sendEvent(executor, properties);
446+
}
431447
}

src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ export function activate(context: vscode.ExtensionContext) {
1010
codeManager.onDidCloseTerminal();
1111
});
1212

13-
const run = vscode.commands.registerCommand("code-runner.run", () => {
14-
codeManager.run();
13+
const run = vscode.commands.registerCommand("code-runner.run", (fileUri: vscode.Uri) => {
14+
codeManager.run(null, fileUri);
1515
});
1616

1717
const runCustomCommand = vscode.commands.registerCommand("code-runner.runCustomCommand", () => {

0 commit comments

Comments
 (0)