From aab00e2ee1af65c4d90d99046e7dc4287c209ca6 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 22 Mar 2016 14:01:59 -0700 Subject: [PATCH] Fixes UI-related bugs, and migrate Console.Write to myHost.UI.Write --- src/Microsoft.PowerShell.Linux.Host/main.cs | 23 +++++------ src/Microsoft.PowerShell.Linux.Host/rawui.cs | 30 +++++++++++++- .../readline.cs | 41 ++++++++++++------- src/Microsoft.PowerShell.Linux.Host/ui.cs | 10 ++++- 4 files changed, 73 insertions(+), 31 deletions(-) diff --git a/src/Microsoft.PowerShell.Linux.Host/main.cs b/src/Microsoft.PowerShell.Linux.Host/main.cs index 19abe349b2..b4847dc60a 100644 --- a/src/Microsoft.PowerShell.Linux.Host/main.cs +++ b/src/Microsoft.PowerShell.Linux.Host/main.cs @@ -533,7 +533,6 @@ OPTIONS { // Set up the control-C handler. Console.CancelKeyPress += new ConsoleCancelEventHandler(this.HandleControlC); - //Console.TreatControlCAsInput = false; string initialCommand = String.Empty; @@ -557,7 +556,7 @@ OPTIONS this.myHost.UI.Write(ConsoleColor.White, Console.BackgroundColor, prompt); - ConsoleReadLine.ReadResult result = consoleReadLine.Read(this.myHost.Runspace, false, initialCommand); + ConsoleReadLine.ReadResult result = consoleReadLine.Read(this.myHost.Runspace, this.myHost.UI, false, initialCommand); switch(result.state) { @@ -596,9 +595,9 @@ OPTIONS while (resumeAction == null) { string prompt = incompleteLine ? ">> " : "[DBG] PS >> "; - Console.Write(prompt); + this.myHost.UI.Write(prompt); - ConsoleReadLine.ReadResult result = consoleReadLine.Read(this.myHost.Runspace, true, initialCommand); + ConsoleReadLine.ReadResult result = consoleReadLine.Read(this.myHost.Runspace, this.myHost.UI, true, initialCommand); switch(result.state) { @@ -622,7 +621,7 @@ OPTIONS { foreach (var item in output.ReadAll()) { - Console.WriteLine(item); + this.myHost.UI.WriteLine(item.ToString()); } }; @@ -679,8 +678,8 @@ OPTIONS // Show help message only once. if (!_showHelpMessage) { - Console.WriteLine("Entering debug mode. Type 'h' to get help."); - Console.WriteLine(); + this.myHost.UI.WriteLine("Entering debug mode. Type 'h' to get help."); + this.myHost.UI.WriteLine(); _showHelpMessage = true; } @@ -688,12 +687,12 @@ OPTIONS // pertain to this debugger execution stop point. if (args.Breakpoints.Count > 0) { - Console.WriteLine("Debugger hit breakpoint on:"); + this.myHost.UI.WriteLine("Debugger hit breakpoint on:"); foreach (var breakPoint in args.Breakpoints) { - Console.WriteLine(breakPoint.ToString()); + this.myHost.UI.WriteLine(breakPoint.ToString()); } - Console.WriteLine(); + this.myHost.UI.WriteLine(); } // Script position stop information. @@ -701,8 +700,8 @@ OPTIONS // there is one. if (args.InvocationInfo != null) { - Console.WriteLine(args.InvocationInfo.PositionMessage); - Console.WriteLine(); + this.myHost.UI.WriteLine(args.InvocationInfo.PositionMessage); + this.myHost.UI.WriteLine(); } Console.ForegroundColor = saveFGColor; diff --git a/src/Microsoft.PowerShell.Linux.Host/rawui.cs b/src/Microsoft.PowerShell.Linux.Host/rawui.cs index 48a83b508a..9b359a2daa 100644 --- a/src/Microsoft.PowerShell.Linux.Host/rawui.cs +++ b/src/Microsoft.PowerShell.Linux.Host/rawui.cs @@ -122,14 +122,40 @@ namespace Microsoft.PowerShell.Linux.Host set { Console.SetWindowSize(value.Width, value.Height); } } + /// + /// Cached Window Title, for systems that needs it + /// + private string title = String.Empty; + /// /// Gets or sets the title of the displayed window. The example /// maps the Console.Title property to the value of this property. /// public override string WindowTitle { - get { return Console.Title; } - set { Console.Title = value; } + get + { + // In Unix/Linux systems, Console.Title current results in a not-implemented + // exception. In that case, we return a cached copy of title that was set earlier. + // Obviously, this will not work if: 1) Title was never set in PowerShell, or 2) + // one sets the windows's title outside of PowerShell. + string result; + try + { + result = Console.Title; + } + catch (PlatformNotSupportedException) + { + return title; + } + return result; + } + + set + { + Console.Title = value; + title = value; + } } /// diff --git a/src/Microsoft.PowerShell.Linux.Host/readline.cs b/src/Microsoft.PowerShell.Linux.Host/readline.cs index 1b60a901f4..b8695f2b65 100644 --- a/src/Microsoft.PowerShell.Linux.Host/readline.cs +++ b/src/Microsoft.PowerShell.Linux.Host/readline.cs @@ -4,6 +4,7 @@ namespace Microsoft.PowerShell.Linux.Host using System.Collections.ObjectModel; using System.IO; using System.Management.Automation; + using System.Management.Automation.Host; using System.Management.Automation.Runspaces; using System.Text; @@ -19,6 +20,11 @@ namespace Microsoft.PowerShell.Linux.Host /// private PowerShell powershell = PowerShell.Create(); + /// + /// Host's UserInterface + /// + private PSHostUserInterface ui; + /// /// The buffer used to edit. /// @@ -78,7 +84,7 @@ namespace Microsoft.PowerShell.Linux.Host /// We do not pick different colors for every token, those tokens /// use this default. /// - private ConsoleColor defaultColor = ConsoleColor.White; + private ConsoleColor defaultColor = Console.ForegroundColor; /// /// To keep track of whether we have hit "enter" key since last arrow up/down key @@ -147,9 +153,10 @@ namespace Microsoft.PowerShell.Linux.Host /// Read a line of text, colorizing while typing. /// /// The command line read - public ReadResult Read(Runspace runspace, bool nested, string initialValue) + public ReadResult Read(Runspace runspace, PSHostUserInterface hostUI, bool nested, string initialValue) { this.powershell.Runspace = runspace; + this.ui = hostUI; this.Initialize(); bool commandComplete = false; bool abort = false; @@ -603,15 +610,15 @@ namespace Microsoft.PowerShell.Linux.Host { OnEscape(); ConsoleColor saveFGColor = Console.ForegroundColor; - Console.Out.Write("("); + ui.Write("("); Console.ForegroundColor = ConsoleColor.Red; - Console.Out.Write("{0}", failed); + ui.Write(String.Format("{0}", failed)); Console.ForegroundColor = saveFGColor; - Console.Out.Write("reverse-i-search)'{0}", searchString.ToString()); + ui.Write(String.Format("reverse-i-search)'{0}", searchString.ToString())); this.current = this.cursor.GetPosition(); - Console.Out.Write("': "); + ui.Write("': "); Console.ForegroundColor = ConsoleColor.Green; - Console.Out.Write("{0}", searchResult); + ui.Write(String.Format("{0}", searchResult)); Console.ForegroundColor = saveFGColor; this.rendered = this.cursor.GetPosition(); this.cursor.Place(this.current); @@ -848,7 +855,7 @@ namespace Microsoft.PowerShell.Linux.Host private string OnEnter() { this.newHistory = true; - Console.Out.WriteLine(); + ui.WriteLine(); return this.buffer.ToString(); } @@ -946,10 +953,12 @@ namespace Microsoft.PowerShell.Linux.Host if (tokens.Count > 0) { + ConsoleColor saveFGColor = Console.ForegroundColor; + // Print leading blanks if (tokens[0].Start != 0) { - Console.Out.Write(new string(' ', tokens[0].Start)); + ui.Write(new string(' ', tokens[0].Start)); } // Place the cursor at the start of the first token to render. The @@ -964,7 +973,7 @@ namespace Microsoft.PowerShell.Linux.Host // use the actual text from our input because the content sometimes // excludes part of the token, e.g. the quote characters of a string. Console.ForegroundColor = this.tokenColors[(int)tokens[i].Type]; - Console.Out.Write(text.Substring(tokens[i].Start, tokens[i].Length)); + ui.Write(text.Substring(tokens[i].Start, tokens[i].Length)); // Whitespace doesn't show up in the array of tokens. Write it out here. if (i != (tokens.Count - 1)) @@ -972,7 +981,7 @@ namespace Microsoft.PowerShell.Linux.Host Console.ForegroundColor = this.defaultColor; for (int j = (tokens[i].Start + tokens[i].Length); j < tokens[i + 1].Start; ++j) { - Console.Out.Write(text[j]); + ui.Write(text[j].ToString()); } } } @@ -982,8 +991,10 @@ namespace Microsoft.PowerShell.Linux.Host Console.ForegroundColor = this.defaultColor; for (int j = tokens[i - 1].Start + tokens[i - 1].Length; j < text.Length; ++j) { - Console.Out.Write(text[j]); + ui.Write(text[j].ToString()); } + + Console.ForegroundColor = saveFGColor; } else { @@ -991,13 +1002,13 @@ namespace Microsoft.PowerShell.Linux.Host // happens most frequently when the first token is incomplete, like a string // literal missing a closing quote. this.cursor.Reset(); - Console.Out.Write(text); + ui.Write(text); } // If characters were deleted, we must write over previously written characters if (text.Length < this.rendered) { - Console.Out.Write(new string(' ', this.rendered - text.Length)); + ui.Write(new string(' ', this.rendered - text.Length)); } this.rendered = text.Length; @@ -1011,7 +1022,7 @@ namespace Microsoft.PowerShell.Linux.Host { ConsoleColor saveFGColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; - Console.Out.WriteLine("^C"); + ui.WriteLine("^C"); Console.ForegroundColor = saveFGColor; } diff --git a/src/Microsoft.PowerShell.Linux.Host/ui.cs b/src/Microsoft.PowerShell.Linux.Host/ui.cs index 4d105d6556..04aed71c5c 100644 --- a/src/Microsoft.PowerShell.Linux.Host/ui.cs +++ b/src/Microsoft.PowerShell.Linux.Host/ui.cs @@ -349,10 +349,13 @@ ReadNext: ConsoleColor backgroundColor, string value) { + ConsoleColor oldFg = Console.ForegroundColor; + ConsoleColor oldBg = Console.BackgroundColor; Console.ForegroundColor = foregroundColor; Console.BackgroundColor = backgroundColor; Console.Write(value); - Console.ResetColor(); + Console.ForegroundColor = oldFg; + Console.BackgroundColor = oldBg; } @@ -368,10 +371,13 @@ ReadNext: ConsoleColor backgroundColor, string value) { + ConsoleColor oldFg = Console.ForegroundColor; + ConsoleColor oldBg = Console.BackgroundColor; Console.ForegroundColor = foregroundColor; Console.BackgroundColor = backgroundColor; Console.WriteLine(value); - Console.ResetColor(); + Console.ForegroundColor = oldFg; + Console.BackgroundColor = oldBg; } ///