diff --git a/src/Microsoft.PowerShell.Linux.Host/readline.cs b/src/Microsoft.PowerShell.Linux.Host/readline.cs index 75d7ee5a81..72edebee10 100644 --- a/src/Microsoft.PowerShell.Linux.Host/readline.cs +++ b/src/Microsoft.PowerShell.Linux.Host/readline.cs @@ -2,6 +2,7 @@ namespace Microsoft.PowerShell.Linux.Host { using System; using System.Collections.ObjectModel; + using System.IO; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Text; @@ -79,6 +80,11 @@ namespace Microsoft.PowerShell.Linux.Host /// private ConsoleColor defaultColor = ConsoleColor.White; + /// + /// To keep track of whether we have hit "enter" key since last arrow up/down key + /// + private bool newHistory = false; + /// /// Initializes a new instance of the ConsoleReadLine class. /// @@ -244,17 +250,18 @@ namespace Microsoft.PowerShell.Linux.Host string tabResult = cmdCompleteOpt.CompletionMatches[tabCompletionPos].CompletionText; + // To match behavior on Windows + bool moveLeftOneSpace = false; + if (cmdCompleteOpt.CompletionMatches[tabCompletionPos].ResultType == CompletionResultType.ProviderContainer) + { + tabResult = GetReplacementTextForDirectory(tabResult, ref moveLeftOneSpace); + } + tabCompletionPos++; //if there is a command for the user before the uncompleted option if (!String.IsNullOrEmpty(tabResult)) { - //handle file path slashes - if (tabResult.Contains(".\\")) - { - tabResult = tabResult.Replace(".\\", ""); - } - var replaceIndex = cmdCompleteOpt.ReplacementIndex; string replaceBuffer = this.buffer.ToString(); @@ -275,10 +282,48 @@ namespace Microsoft.PowerShell.Linux.Host BufferFromString(tabResult); this.Render(); + + if (moveLeftOneSpace) + { + MoveLeft(); + } } } //end of OnTab() + /// + /// Helper function to add trailing slash to directories + /// + private static string GetReplacementTextForDirectory(string replacementText, ref bool moveLeftOneSpace) + { + string separator = Path.DirectorySeparatorChar.ToString(); + const string singleQuote = "'"; + const string doubleQuote = "\""; + + if (!replacementText.EndsWith(separator, StringComparison.Ordinal)) + { + if (replacementText.EndsWith(separator + singleQuote, StringComparison.Ordinal) + || replacementText.EndsWith(separator + doubleQuote, StringComparison.Ordinal)) + { + moveLeftOneSpace = true; + return replacementText; + } + else if (replacementText.EndsWith(singleQuote, StringComparison.Ordinal) + || replacementText.EndsWith(doubleQuote, StringComparison.Ordinal)) + { + var len = replacementText.Length; + char quoteChar = replacementText[len - 1]; + replacementText = replacementText.Substring(0, len - 1) + separator + quoteChar; + moveLeftOneSpace = true; + } + else + { + replacementText = replacementText + separator; + } + } + return replacementText; + } + /// /// Set buffer to a string rather than inserting char by char /// @@ -311,100 +356,77 @@ namespace Microsoft.PowerShell.Linux.Host } /// - /// The up arrow was pressed to retrieve history + /// The down arrow was pressed to retrieve history /// - private void OnDownArrow() { - - if (historyResult == null) - { - return; - } - - if (historyIndex == historyResult.Count) + private void OnDownArrow() + { + if (this.newHistory) { + GetHistory(); OnEscape(); + historyIndex = historyResult.Count; } - - historyIndex++; - - try + else { + if ( historyResult == null) + { + return; + } + + historyIndex++; + + if (historyIndex >= historyResult.Count) + { + OnEscape(); + historyIndex = historyResult.Count; + return; + } + + BufferFromString(historyResult[historyIndex].Members["CommandLine"].Value.ToString()); + this.Render(); + } + + this.newHistory = false; + } + + /// + /// Changes the history queue when the up arrow is pressed + /// + private void OnUpArrow() + { + if (this.newHistory) + { + GetHistory(); + historyIndex = historyResult.Count - 1; + + BufferFromString(historyResult[historyIndex].Members["CommandLine"].Value.ToString()); + this.Render(); + } + else + { + if ( historyResult == null || historyIndex == 0) + { + return; + } + + historyIndex--; + BufferFromString(historyResult[historyIndex].Members["CommandLine"].Value.ToString()); this.Render(); } - catch - { - return; - } + this.newHistory = false; } /// - /// Changes the history queue when the down arrow is pressed + /// Helper function to get command history /// - private void OnUpArrow() + private void GetHistory() { - - try{ - if ((previousKeyPress.Key != ConsoleKey.DownArrow && previousKeyPress.Key != ConsoleKey.UpArrow) || previousKeyPress.Key == ConsoleKey.Enter) - { - //first time getting the history - using (Pipeline pipeline = this.powershell.Runspace.CreatePipeline("Get-History")) - { - historyResult = pipeline.Invoke(); - } - - try - { - historyIndex = historyResult.Count -1; - BufferFromString(historyResult[historyIndex].Members["CommandLine"].Value.ToString()); - this.Render(); - historyIndex--; - } - - catch - { - return; - } - - } - - else - { - if (historyIndex > historyResult.Count) //we hit the blank prompt using the down arrow - { - historyIndex = historyResult.Count -1; - } - - if ( historyIndex < 0 ) - { - historyIndex = 0; - } - - try - { - BufferFromString(historyResult[historyIndex].Members["CommandLine"].Value.ToString()); - this.Render(); - - if ( historyIndex == 0 ) - { - return; - } - - else - { - historyIndex--; - } - } - - catch - { - return; - } - } + using (Pipeline pipeline = this.powershell.Runspace.CreatePipeline("Get-History")) + { + historyResult = pipeline.Invoke(); } - - catch { return;} } /// @@ -526,6 +548,7 @@ namespace Microsoft.PowerShell.Linux.Host /// A newline character. private string OnEnter() { + this.newHistory = true; Console.Out.WriteLine(); return this.buffer.ToString(); } diff --git a/src/monad b/src/monad index 3aec819b82..365bd20cf4 160000 --- a/src/monad +++ b/src/monad @@ -1 +1 @@ -Subproject commit 3aec819b82f53b84824b69702975242d6568ca0d +Subproject commit 365bd20cf400f5c8dd2ff9d8894e16a046248d0f