Adding support for Ctrl-K, Ctrl-Y, and Ctrl-L

This commit is contained in:
George Fleming
2016-03-23 14:11:04 -07:00
parent 2deb871ab2
commit e713af87bb
2 changed files with 121 additions and 46 deletions
+33 -19
View File
@@ -535,6 +535,8 @@ OPTIONS
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".
while (!this.ShouldExit && this.myHost.Runspace != null)
@@ -555,19 +557,24 @@ OPTIONS
this.myHost.UI.Write(ConsoleColor.White, Console.BackgroundColor, prompt);
bool abort;
string cmd = consoleReadLine.Read(this.myHost.Runspace, false, out abort);
if (string.IsNullOrEmpty(cmd))
ConsoleReadLine.ReadResult result = consoleReadLine.Read(this.myHost.Runspace, false, initialCommand);
switch(result.state)
{
if (abort)
{
case ConsoleReadLine.ReadResult.State.Abort:
incompleteLine = false;
partialLine = string.Empty;
}
continue;
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;
}
this.Execute(cmd);
}
}
@@ -583,23 +590,30 @@ OPTIONS
WriteDebuggerStopMessages(args);
string initialCommand = String.Empty;
// loop to process Debugger commands.
while (resumeAction == null)
{
string prompt = incompleteLine ? ">> " : "[DBG] PS >> ";
Console.Write(prompt);
bool abort;
string command = consoleReadLine.Read(this.myHost.Runspace, true, out abort);
if (string.IsNullOrEmpty(command))
ConsoleReadLine.ReadResult result = consoleReadLine.Read(this.myHost.Runspace, true, initialCommand);
switch(result.state)
{
if (abort)
{
case ConsoleReadLine.ReadResult.State.Abort:
incompleteLine = false;
partialLine = string.Empty;
}
continue;
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.
@@ -622,7 +636,7 @@ OPTIONS
PSCommand psCommand = new PSCommand();
string fullCommand = incompleteLine ? (partialLine + command) : command;
string fullCommand = incompleteLine ? (partialLine + result.command) : result.command;
psCommand.AddScript(fullCommand).AddCommand("Out-String").AddParameter("Stream", true);
incompleteLine = false;
@@ -634,7 +648,7 @@ OPTIONS
catch (IncompleteParseException)
{
incompleteLine = true;
partialLine = $"{partialLine}{command}{System.Environment.NewLine}";
partialLine = $"{partialLine}{result.command}{System.Environment.NewLine}";
}
if (!incompleteLine)
+88 -27
View File
@@ -90,6 +90,29 @@ namespace Microsoft.PowerShell.Linux.Host
/// </summary>
private string preTabBuffer;
/// <summary>
/// kill buffer used by Ctrl-K and Ctrl-Y
/// </summary>
private string killBuffer = String.Empty;
/// <summary>
/// What Read() outputs
/// </summary>
public class ReadResult
{
public ReadResult(State s, string cmd)
{
this.command = cmd;
this.state = s;
Console.TreatControlCAsInput = true;
}
public enum State {Complete, Abort, Redraw}
public string command;
public State state;
}
/// <summary>
/// Initializes a new instance of the ConsoleReadLine class.
/// </summary>
@@ -124,13 +147,20 @@ namespace Microsoft.PowerShell.Linux.Host
/// Read a line of text, colorizing while typing.
/// </summary>
/// <returns>The command line read</returns>
public string Read(Runspace runspace, bool nested, out bool abort)
public ReadResult Read(Runspace runspace, bool nested, string initialValue)
{
this.powershell.Runspace = runspace;
this.Initialize();
bool commandComplete = false;
abort = false;
// Console.WriteLine("Default value of TreatCtrlCAsInput: {0}", Console.TreatControlCAsInput);
bool abort = false;
bool redraw = false;
if (!String.IsNullOrEmpty(initialValue))
{
this.BufferFromString(initialValue);
this.Render();
}
Console.TreatControlCAsInput = false;
while (true)
@@ -140,12 +170,7 @@ namespace Microsoft.PowerShell.Linux.Host
// Basic Emacs-style readline implementation
if (key.Modifiers.HasFlag(ConsoleModifiers.Control))
{
commandComplete = ProcessControlKey(key, nested, ref abort);
if (abort)
{
Console.TreatControlCAsInput = true;
return String.Empty;
}
commandComplete = ProcessControlKey(key, nested, ref abort, ref redraw);
}
else if (key.Modifiers.HasFlag(ConsoleModifiers.Alt))
{
@@ -159,10 +184,19 @@ namespace Microsoft.PowerShell.Linux.Host
previousKeyPress = key;
if (abort)
{
return new ReadResult(ReadResult.State.Abort, String.Empty);
}
if (redraw)
{
return new ReadResult(ReadResult.State.Redraw, this.buffer.ToString());
}
if (commandComplete)
{
Console.TreatControlCAsInput = true;
return this.OnEnter();
return new ReadResult(ReadResult.State.Complete, this.OnEnter());
}
}
}
@@ -170,7 +204,7 @@ namespace Microsoft.PowerShell.Linux.Host
/// <summary>
/// Process Control-Key combo
/// </summary>
private bool ProcessControlKey(ConsoleKeyInfo key, bool nested, ref bool abort)
private bool ProcessControlKey(ConsoleKeyInfo key, bool nested, ref bool abort, ref bool redraw)
{
switch (key.Key)
{
@@ -180,12 +214,12 @@ namespace Microsoft.PowerShell.Linux.Host
case ConsoleKey.E:
this.OnEnd();
break;
// TODO: save buffer, yank with Ctrl-Y
/*
case ConsoleKey.K:
this.OnEscape();
break;
*/
case ConsoleKey.K:
this.OnKill();
break;
case ConsoleKey.Y:
this.OnYank();
break;
case ConsoleKey.D:
this.OnDelete();
break;
@@ -206,15 +240,12 @@ namespace Microsoft.PowerShell.Linux.Host
this.OnDownArrow(nested);
break;
case ConsoleKey.J:
this.OnEnter();
break;
// TODO: save and restore buffer
/*
case ConsoleKey.L:
this.BufferFromString("clear");
previousKeyPress = key;
return this.OnEnter();
*/
previousKeyPress = key;
return true;
case ConsoleKey.L:
Console.Clear();
redraw = true;
return false;
case ConsoleKey.C:
this.Abort();
abort = true;
@@ -688,6 +719,36 @@ namespace Microsoft.PowerShell.Linux.Host
}
}
/// <summary>
/// Ctrl-K was entered.
/// </summary>
private void OnKill()
{
if (this.buffer.Length > 0 && this.current < this.buffer.Length)
{
this.killBuffer = this.buffer.ToString().Substring(this.current);
this.buffer.Remove(this.current, killBuffer.Length);
this.Render();
}
else
{
this.killBuffer = String.Empty;
}
}
/// <summary>
/// Ctrl-Y was entered.
/// </summary>
private void OnYank()
{
if (!String.IsNullOrEmpty(killBuffer))
{
this.buffer.Insert(this.current, killBuffer);
this.current += killBuffer.Length;
this.Render();
}
}
/// <summary>
/// The Backspace key was entered.
/// </summary>