Skip to content
Merged
120 changes: 86 additions & 34 deletions src/Microsoft.PowerShell.Linux.Host/main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ Prints this text.
}
// TODO: check for input on stdin

ConsoleColor InitialForegroundColor = Console.ForegroundColor;
ConsoleColor InitialBackgroundColor = Console.BackgroundColor;

// Create the listener and run it
Listener listener = new Listener(initialScript, loadProfiles);

Expand All @@ -118,6 +121,9 @@ Prints this text.
listener.Run();
}

Console.ForegroundColor = InitialForegroundColor;
Console.BackgroundColor = InitialBackgroundColor;

// Exit with the desired exit code that was set by the exit command.
// The exit code is set in the host by the MyHost.SetShouldExit() method.
System.Environment.Exit(listener.ExitCode);
Expand All @@ -129,7 +135,7 @@ internal class Listener
/// <summary>
/// Used to read user input.
/// </summary>
internal ConsoleReadLine consoleReadLine = new ConsoleReadLine();
internal ConsoleReadLine consoleReadLine;

/// <summary>
/// Holds a reference to the runspace for this interpeter.
Expand Down Expand Up @@ -213,6 +219,7 @@ public Listener(string initialScript, bool loadProfiles)
InitialSessionState iss = InitialSessionState.CreateDefault2();
this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost, iss);
this.myRunSpace.Open();
this.consoleReadLine = new ConsoleReadLine(this.myHost.Runspace, this.myHost.UI);

if (this.myRunSpace.Debugger != null)
{
Expand All @@ -222,7 +229,6 @@ public Listener(string initialScript, bool loadProfiles)
// feature. In order to debug Workflow script functions the debugger
// DebugMode must include the DebugModes.LocalScript flag.
this.myRunSpace.Debugger.SetDebugMode(DebugModes.LocalScript);

}

if (loadProfiles)
Expand Down Expand Up @@ -360,14 +366,8 @@ private void ExecuteHelper(string cmd, object input)
{
this.currentPowerShell.Runspace = this.myRunSpace;

if (incompleteLine)
{
this.currentPowerShell.AddScript(partialLine + cmd);
}
else
{
this.currentPowerShell.AddScript(cmd);
}
string fullCommand = incompleteLine ? (partialLine + cmd) : cmd;
this.currentPowerShell.AddScript(fullCommand);
incompleteLine = false;

// Add the default outputter to the end of the pipe and then call the
Expand All @@ -394,11 +394,7 @@ private void ExecuteHelper(string cmd, object input)
catch (IncompleteParseException)
{
incompleteLine = true;
cmd = cmd.Trim();
partialLine += cmd;

partialLine += System.Environment.NewLine;

partialLine = $"{partialLine}{cmd}{System.Environment.NewLine}";
}

finally
Expand Down Expand Up @@ -526,7 +522,6 @@ private void HandleControlC(object sender, ConsoleCancelEventArgs e)
this.currentPowerShell.Stop();
}
}

e.Cancel = true;
}
catch (Exception exception)
Expand All @@ -544,7 +539,8 @@ internal void Run()
{
// Set up the control-C handler.
Console.CancelKeyPress += new ConsoleCancelEventHandler(this.HandleControlC);
//Console.TreatControlCAsInput = false;

string initialCommand = String.Empty;

// Read commands and run them until the ShouldExit flag is set by
// the user calling "exit".
Expand All @@ -564,9 +560,26 @@ internal void Run()
prompt = "PS> ";
}

this.myHost.UI.Write(ConsoleColor.White, Console.BackgroundColor, prompt);
string cmd = consoleReadLine.Read(this.myHost.Runspace, false);
this.Execute(cmd);
this.myHost.UI.Write(prompt);

ConsoleReadLine.ReadResult result = consoleReadLine.Read(false, initialCommand);

switch(result.state)
{
case ConsoleReadLine.ReadResult.State.Abort:
incompleteLine = false;
partialLine = string.Empty;
initialCommand = String.Empty;
break;
case ConsoleReadLine.ReadResult.State.Redraw:
initialCommand = result.command;
break;
case ConsoleReadLine.ReadResult.State.Complete:
default:
this.Execute(result.command);
initialCommand = String.Empty;
break;
}
}
}

Expand All @@ -582,20 +595,39 @@ private void HandleDebuggerStopEvent(object sender, DebuggerStopEventArgs args)

WriteDebuggerStopMessages(args);

string initialCommand = String.Empty;

// loop to process Debugger commands.
while (resumeAction == null)
{
Console.Write("[DBG] PS >> ");
string command = consoleReadLine.Read(this.myHost.Runspace, true);
Console.WriteLine();
string prompt = incompleteLine ? ">> " : "[DBG] PS >> ";
this.myHost.UI.Write(prompt);

ConsoleReadLine.ReadResult result = consoleReadLine.Read(true, initialCommand);

switch(result.state)
{
case ConsoleReadLine.ReadResult.State.Abort:
incompleteLine = false;
partialLine = string.Empty;
initialCommand = String.Empty;
continue;
case ConsoleReadLine.ReadResult.State.Redraw:
initialCommand = result.command;
continue;
case ConsoleReadLine.ReadResult.State.Complete:
default:
initialCommand = String.Empty;
break;
}

// Stream output from command processing to console.
var output = new PSDataCollection<PSObject>();
output.DataAdded += (dSender, dArgs) =>
{
foreach (var item in output.ReadAll())
{
Console.WriteLine(item);
this.myHost.UI.WriteLine(item.ToString());
}
};

Expand All @@ -606,10 +638,30 @@ private void HandleDebuggerStopEvent(object sender, DebuggerStopEventArgs args)
// command or script. The returned DebuggerCommandResults object will indicate
// whether the command was evaluated by the debugger and if the debugger should
// be released with a specific resume action.

PSCommand psCommand = new PSCommand();
psCommand.AddScript(command).AddCommand("Out-String").AddParameter("Stream", true);
DebuggerCommandResults results = debugger.ProcessCommand(psCommand, output);
if (results.ResumeAction != null)

string fullCommand = incompleteLine ? (partialLine + result.command) : result.command;
psCommand.AddScript(fullCommand).AddCommand("Out-String").AddParameter("Stream", true);
incompleteLine = false;

DebuggerCommandResults results = null;
try
{
results = debugger.ProcessCommand(psCommand, output);
}
catch (IncompleteParseException)
{
incompleteLine = true;
partialLine = $"{partialLine}{result.command}{System.Environment.NewLine}";
}

if (!incompleteLine)
{
partialLine = string.Empty;
}

if (!incompleteLine && results.ResumeAction != null)
{
resumeAction = results.ResumeAction;
}
Expand All @@ -632,30 +684,30 @@ private void WriteDebuggerStopMessages(DebuggerStopEventArgs args)
// 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;
}

// Breakpoint stop information. Writes all breakpoints that
// 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.
// This writes the InvocationInfo position message if
// 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;
Expand Down
30 changes: 28 additions & 2 deletions src/Microsoft.PowerShell.Linux.Host/rawui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,40 @@ public override Size WindowSize
set { Console.SetWindowSize(value.Width, value.Height); }
}

/// <summary>
/// Cached Window Title, for systems that needs it
/// </summary>
private string title = String.Empty;

/// <summary>
/// Gets or sets the title of the displayed window. The example
/// maps the Console.Title property to the value of this property.
/// </summary>
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;
}
}

/// <summary>
Expand Down
Loading