/// <summary> /// Creates a new Python REPL window which is independent from the /// default Python REPL windows. /// /// This window will not persist across VS sessions. /// </summary> /// <param name="id">An ID which can be used to retrieve the window again and can survive across VS sessions. /// /// The ID cannot include the | character.</param> /// <param name="title">The title of the window to be displayed</param> /// <param name="interpreter">The interpreter to be used. This implies the language version and provides the path to the Python interpreter to be used.</param> /// <param name="startupFile">The file to be executed on the startup of the REPL. Can be null, which will result in an interactive REPL.</param> /// <param name="workingDir">The working directory of the REPL process</param> /// <param name="project">The IVsHierarchy representing the Python project.</param> public IReplWindow CreatePythonRepl(string id, string title, IPythonInterpreterFactory interpreter, string workingDir, Dictionary <string, string> envVars = null, IVsHierarchy project = null) { Utilities.ArgumentNotNull("interpreter", interpreter); Utilities.ArgumentNotNull("id", id); Utilities.ArgumentNotNull("title", title); // The previous format of repl ID would produce new windows for // distinct working directories and/or env vars. To emulate this, // we now put all of these values into the user ID part, even though // they must still be manually provided after the evaluator is // created. var realId = string.Format( "{0};{1};{2}", id, workingDir ?? "", envVars == null ? "" : string.Join(";", envVars.Select(kvp => kvp.Key + "=" + kvp.Value)) ); string replId = PythonReplEvaluatorProvider.GetConfigurableReplId(realId); #if DEV14_OR_LATER var replProvider = ComponentModel.GetService <InteractiveWindowProvider>(); var vsWindow = #else var replProvider = ComponentModel.GetService <IReplWindowProvider>(); var window = #endif replProvider.FindReplWindow(replId) ?? replProvider.CreateReplWindow( this.GetPythonContentType(), title, typeof(PythonLanguageInfo).GUID, replId ); #if DEV14_OR_LATER var window = vsWindow.InteractiveWindow; #endif var commandProvider = project as IPythonProject2; if (commandProvider != null) { commandProvider.AddActionOnClose((object)window, BasePythonReplEvaluator.CloseReplWindow); } var evaluator = window.Evaluator as BasePythonReplEvaluator; var options = (evaluator != null) ? evaluator.CurrentOptions as ConfigurablePythonReplOptions : null; if (options == null) { throw new NotSupportedException("Cannot modify options of " + window.Evaluator.GetType().FullName); } options.InterpreterFactory = interpreter; options.Project = project as PythonProjectNode; options._workingDir = workingDir; options._envVars = new Dictionary <string, string>(envVars); evaluator.Reset(quiet: true) .HandleAllExceptions(SR.ProductName, GetType()) .DoNotWait(); return(window); }
private async Task <bool> RunInRepl(IPythonProject2 project, CommandStartInfo startInfo) { var executeIn = string.IsNullOrEmpty(startInfo.ExecuteIn) ? CreatePythonCommandItem.ExecuteInRepl : startInfo.ExecuteIn; bool resetRepl = executeIn.StartsWith("R", StringComparison.InvariantCulture); var replTitle = executeIn.Substring(4).TrimStart(' ', ':'); if (string.IsNullOrEmpty(replTitle)) { replTitle = SR.GetString(SR.CustomCommandReplTitle, DisplayLabelWithoutAccessKeys); } else { var match = _customCommandLabelRegex.Match(replTitle); if (match.Success) { replTitle = LoadResourceFromAssembly( match.Groups["assembly"].Value, match.Groups["namespace"].Value, match.Groups["key"].Value ); } } replTitle = PerformSubstitutions(project, replTitle); var replWindowId = PythonReplEvaluatorProvider.GetConfigurableReplId(ReplId + executeIn.Substring(4)); var model = _project.Site.GetComponentModel(); var replProvider = model.GetService <IReplWindowProvider>(); if (replProvider == null) { return(false); } var replWindow = replProvider.FindReplWindow(replWindowId); bool created = replWindow == null; if (created) { replWindow = replProvider.CreateReplWindow( _project.Site.GetPythonContentType(), replTitle, typeof(PythonLanguageInfo).GUID, replWindowId ); } var replToolWindow = replWindow as ToolWindowPane; var replFrame = (replToolWindow != null) ? replToolWindow.Frame as IVsWindowFrame : null; var pyEvaluator = replWindow.Evaluator as PythonReplEvaluator; var options = (pyEvaluator != null) ? pyEvaluator.CurrentOptions as ConfigurablePythonReplOptions : null; if (options == null) { if (created && replFrame != null) { // We created the window, but it isn't valid, so we'll close // it again immediately. replFrame.CloseFrame((uint)__FRAMECLOSE.FRAMECLOSE_NoSave); } return(false); } if (pyEvaluator.IsExecuting) { throw new InvalidOperationException(SR.GetString(SR.ErrorCommandAlreadyRunning)); } options.InterpreterFactory = project.GetInterpreterFactory(); options.Project = project as PythonProjectNode; options._workingDir = startInfo.WorkingDirectory; options._envVars = startInfo.EnvironmentVariables; project.AddActionOnClose((object)replWindow, BasePythonReplEvaluator.CloseReplWindow); var pane = replWindow as ToolWindowPane; var frame = pane != null ? pane.Frame as IVsWindowFrame : null; if (frame != null) { ErrorHandler.ThrowOnFailure(frame.Show()); } var result = await pyEvaluator.Reset(quiet : true); if (result.IsSuccessful) { try { var filename = startInfo.Filename; var arguments = startInfo.Arguments; if (startInfo.IsScript) { pyEvaluator.Window.WriteLine(string.Format("Executing {0} {1}", Path.GetFileName(filename), arguments)); Debug.WriteLine("Executing {0} {1}", filename, arguments); result = await pyEvaluator.ExecuteFile(filename, arguments); } else if (startInfo.IsModule) { pyEvaluator.Window.WriteLine(string.Format("Executing -m {0} {1}", filename, arguments)); Debug.WriteLine("Executing -m {0} {1}", filename, arguments); result = await pyEvaluator.ExecuteModule(filename, arguments); } else if (startInfo.IsCode) { Debug.WriteLine("Executing -c \"{0}\"", filename, arguments); result = await pyEvaluator.ExecuteText(filename); } else { pyEvaluator.Window.WriteLine(string.Format("Executing {0} {1}", Path.GetFileName(filename), arguments)); Debug.WriteLine("Executing {0} {1}", filename, arguments); result = await pyEvaluator.ExecuteProcess(filename, arguments); } if (resetRepl) { // We really close the backend, rather than resetting. pyEvaluator.Close(); } } catch (Exception ex) { ActivityLog.LogError(SR.ProductName, SR.GetString(SR.ErrorRunningCustomCommand, _label, ex)); var outWindow = OutputWindowRedirector.GetGeneral(project.Site); if (outWindow != null) { outWindow.WriteErrorLine(SR.GetString(SR.ErrorRunningCustomCommand, _label, ex)); outWindow.Show(); } } return(true); } return(false); }