Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"onCommand:python.selectAndDebugTestMethod",
"onCommand:python.runFailedTests",
"onCommand:python.execSelectionInTerminal",
"onCommand:python.execSelectionInDjangoShell",
"onCommand:jupyter.runSelectionLine",
"onCommand:jupyter.execCurrentCell",
"onCommand:jupyter.execCurrentCellAndAdvance",
Expand Down Expand Up @@ -174,6 +175,11 @@
"title": "Run Selection in Python Terminal",
"category": "Python"
},
{
"command": "python.execSelectionInDjangoShell",
"title": "Run Selection in Django Shell",
"category": "Python"
},
{
"command": "jupyter.runSelectionLine",
"title": "Run Selection/Line",
Expand Down Expand Up @@ -230,6 +236,11 @@
"group": "Python",
"when": "editorHasSelection && editorLangId == python"
},
{
"command": "python.execSelectionInDjangoShell",
"group": "Python",
"when": "editorHasSelection && editorLangId == python && python.isDjangoProject"
},
{
"when": "resourceLangId == python",
"command": "python.execInTerminal",
Expand Down
1 change: 1 addition & 0 deletions src/client/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export namespace Commands {
export const Set_Interpreter = 'python.setInterpreter';
export const Exec_In_Terminal = 'python.execInTerminal';
export const Exec_Selection_In_Terminal = 'python.execSelectionInTerminal';
export const Exec_Selection_In_Django_Shell = 'python.execSelectionInDjangoShell';
export const Tests_View_UI = 'python.viewTestUI';
export const Tests_Picker_UI = 'python.selectTestToRun';
export const Tests_Picker_UI_Debug = 'python.selectTestToDebug';
Expand Down
36 changes: 35 additions & 1 deletion src/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { activateFormatOnSaveProvider } from './providers/formatOnSaveProvider';
import { WorkspaceSymbols } from './workspaceSymbols/main';
import { BlockFormatProviders } from './typeFormatters/blockFormatProvider';
import * as os from 'os';
import * as fs from 'fs';


const PYTHON: vscode.DocumentFilter = { language: 'python', scheme: 'file' };
Expand All @@ -36,6 +37,7 @@ let jupMain: jup.Jupyter;

export function activate(context: vscode.ExtensionContext) {
let pythonSettings = settings.PythonSettings.getInstance();
let pythonExt = new PythonExt()
const hasPySparkInCompletionPath = pythonSettings.autoComplete.extraPaths.some(p => p.toLowerCase().indexOf('spark') >= 0);
telemetryHelper.sendTelemetryEvent(telemetryContracts.EVENT_LOAD, {
CodeComplete_Has_ExtraPaths: pythonSettings.autoComplete.extraPaths.length > 0 ? 'true' : 'false',
Expand Down Expand Up @@ -119,4 +121,36 @@ export function activate(context: vscode.ExtensionContext) {

// this method is called when your extension is deactivated
export function deactivate() {
}
}

class PythonExt {

private _isDjangoProject: ContextKey;

constructor() {
this._isDjangoProject = new ContextKey('python.isDjangoProject');
this._ensureState();
}

private _ensureState(): void {
// context: python.isDjangoProject
this._isDjangoProject.set(fs.existsSync(vscode.workspace.rootPath.concat("/manage.py")));
}
}

class ContextKey {
private _name: string;
private _lastValue: boolean;

constructor(name:string) {
this._name = name;
}

public set(value:boolean): void {
if (this._lastValue === value) {
return;
}
this._lastValue = value;
vscode.commands.executeCommand('setContext', this._name, this._lastValue);
}
}
109 changes: 95 additions & 14 deletions src/client/providers/execInTerminalProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function activateExecInTerminalProvider(): vscode.Disposable[] {
const disposables: vscode.Disposable[] = [];
disposables.push(vscode.commands.registerCommand(Commands.Exec_In_Terminal, execInTerminal));
disposables.push(vscode.commands.registerCommand(Commands.Exec_Selection_In_Terminal, execSelectionInTerminal));
disposables.push(vscode.commands.registerCommand(Commands.Exec_Selection_In_Django_Shell, execSelectionInDjangoShell));
disposables.push(vscode.window.onDidCloseTerminal((closedTermina: vscode.Terminal) => {
if (terminal === closedTermina) {
terminal = null;
Expand All @@ -19,9 +20,16 @@ export function activateExecInTerminalProvider(): vscode.Disposable[] {
}

function execInTerminal(fileUri?: vscode.Uri) {
const terminalShellSettings = vscode.workspace.getConfiguration('terminal.integrated.shell');
const IS_POWERSHELL = /powershell/.test(terminalShellSettings.get<string>('windows'));

let pythonSettings = settings.PythonSettings.getInstance();
const currentPythonPath = pythonSettings.pythonPath;
let filePath: string;

let currentPythonPath = pythonSettings.pythonPath;
if (currentPythonPath.indexOf(' ') > 0 ) {
currentPythonPath = `"${currentPythonPath}"`
}

if (fileUri === undefined || typeof fileUri.fsPath !== 'string') {
const activeEditor = vscode.window.activeTextEditor;
Expand All @@ -48,6 +56,7 @@ function execInTerminal(fileUri?: vscode.Uri) {
if (filePath.indexOf(' ') > 0) {
filePath = `"${filePath}"`;
}

terminal = terminal ? terminal : vscode.window.createTerminal(`Python`);
if (pythonSettings.terminal && pythonSettings.terminal.executeInFileDir) {
const fileDirPath = path.dirname(filePath);
Expand All @@ -57,18 +66,31 @@ function execInTerminal(fileUri?: vscode.Uri) {
}
const launchArgs = settings.PythonSettings.getInstance().terminal.launchArgs;
const launchArgsString = launchArgs.length > 0 ? " ".concat(launchArgs.join(" ")) : "";
const command = `${currentPythonPath}${launchArgsString} ${filePath}`
if (IS_WINDOWS) {
const cmd = `"${currentPythonPath}"${launchArgsString} ${filePath}`;
terminal.sendText(cmd.replace(/\\/g, "/"));
const commandWin = command.replace(/\\/g, "/");
if (IS_POWERSHELL) {
terminal.sendText(`& ${commandWin}`);
}
else {
terminal.sendText(commandWin);
}
}
else {
terminal.sendText(`${currentPythonPath}${launchArgsString} ${filePath}`);
terminal.sendText(command);
}
terminal.show();
}

function execSelectionInTerminal() {
const currentPythonPath = settings.PythonSettings.getInstance().pythonPath;
const terminalShellSettings = vscode.workspace.getConfiguration('terminal.integrated.shell');
const IS_POWERSHELL = /powershell/.test(terminalShellSettings.get<string>('windows'));

let currentPythonPath = settings.PythonSettings.getInstance().pythonPath;
if (currentPythonPath.indexOf(' ') > 0 ) {
currentPythonPath = `"${currentPythonPath}"`
}

const activeEditor = vscode.window.activeTextEditor;
if (!activeEditor) {
return;
Expand All @@ -79,22 +101,81 @@ function execSelectionInTerminal() {
return;
}
const code = vscode.window.activeTextEditor.document.getText(new vscode.Range(selection.start, selection.end));
terminal = terminal ? terminal : vscode.window.createTerminal(`Python`);
const launchArgs = settings.PythonSettings.getInstance().terminal.launchArgs;
const launchArgsString = launchArgs.length > 0 ? " ".concat(launchArgs.join(" ")) : "";
const command = `${currentPythonPath}${launchArgsString}`
if (!terminal) {
terminal = vscode.window.createTerminal(`Python`);
if (IS_WINDOWS) {
const commandWin = command.replace(/\\/g, "/");
if (IS_POWERSHELL) {
terminal.sendText(`& ${commandWin}`);
}
else {
terminal.sendText(commandWin);
}
}
else {
terminal.sendText(command);
}
}
const unix_code = code.replace(/\r\n/g, "\n")
if (IS_WINDOWS) {
// Multi line commands don't work the same way on windows terminals as it does on other OS
// So just start the Python REPL, then send the commands
if (currentPythonPath.indexOf(' ') > 0) {
terminal.sendText(`"${currentPythonPath}"${launchArgsString}`);
terminal.sendText(unix_code.replace(/\n/g, "\r\n"));
}
else
{
terminal.sendText(unix_code)
}
terminal.show();
}

function execSelectionInDjangoShell() {
const terminalShellSettings = vscode.workspace.getConfiguration('terminal.integrated.shell');
const IS_POWERSHELL = /powershell/.test(terminalShellSettings.get<string>('windows'));

let currentPythonPath = settings.PythonSettings.getInstance().pythonPath;
if (currentPythonPath.indexOf(' ') > 0 ) {
currentPythonPath = `"${currentPythonPath}"`
}

const activeEditor = vscode.window.activeTextEditor;
if (!activeEditor) {
return;
}

const workspaceRoot = vscode.workspace.rootPath;
const djangoShellCmd = `"${workspaceRoot}/manage.py" shell`
const selection = vscode.window.activeTextEditor.selection;
if (selection.isEmpty) {
return;
}
const code = vscode.window.activeTextEditor.document.getText(new vscode.Range(selection.start, selection.end));
const launchArgs = settings.PythonSettings.getInstance().terminal.launchArgs;
const launchArgsString = launchArgs.length > 0 ? " ".concat(launchArgs.join(" ")) : "";
const command = `${currentPythonPath}${launchArgsString} ${djangoShellCmd}`
if (!terminal) {
terminal = vscode.window.createTerminal(`Django Shell`);
if (IS_WINDOWS) {
const commandWin = command.replace(/\\/g, "/");
if (IS_POWERSHELL) {
terminal.sendText(`& ${commandWin}`);
}
else {
terminal.sendText(commandWin);
}
}
else {
terminal.sendText(`${currentPythonPath}${launchArgsString}`);
terminal.sendText(command);
}
terminal.sendText(code);
}
else {
terminal.sendText(`${currentPythonPath}${launchArgsString} -c "${code}"`);
const unix_code = code.replace(/\r\n/g, "\n")
if (IS_WINDOWS) {
terminal.sendText(unix_code.replace(/\n/g, "\r\n"));
}
else
{
terminal.sendText(unix_code)
}
terminal.show();
}