/// <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);
        }
Пример #2
0
        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);
        }