diff --git a/README.md b/README.md index 0ef7d602c..56f3de290 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![logo][] PowerShell ==================== -PowerShell is a task automation and configuration management platform. +PowerShell is an automation and configuration management platform. It consists of a cross-platform command-line shell and associated scripting language. [logo]: assets/Powershell_64.png diff --git a/demos/rest.ps1 b/demos/rest.ps1 deleted file mode 100644 index a7b8c799f..000000000 --- a/demos/rest.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -# Get all repositories from the GitHub API, sort by most pull requests, most stars, most forks, etc. - -# Get repo info (json) from the github api -# Convert json to PS object -# Set the private status to false -# Convert back to json -# Push the new json back to the github api \ No newline at end of file diff --git a/docs/learning-powershell/README.md b/docs/learning-powershell/README.md index c51f47621..0a5c7b254 100644 --- a/docs/learning-powershell/README.md +++ b/docs/learning-powershell/README.md @@ -103,6 +103,7 @@ Recommended Training and Reading - [Learn PowerShell Video Library][powershell.com-learn-powershell] from PowerShell.com - [PowerShell Quick Reference Guides][quick-reference] by PowerShellMagazine.com - [PowerShell 5 How-To Videos][script-guy-how-to] by Ed Wilson +- [PowerShell TechNet Resources][https://technet.microsoft.com/en-us/scriptcenter/dd742419.aspx] from ScriptCenter Commercial Resources diff --git a/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs b/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs index eb108b41e..a6248e8be 100644 --- a/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs +++ b/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs @@ -6,9 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -#if UNIX -using System.Reflection; -#endif using System.Runtime.InteropServices; using Microsoft.PowerShell.Internal; @@ -56,6 +53,7 @@ namespace Microsoft.PowerShell Stack tokens = null; ConsoleModifiers modifiers = 0; ConsoleKey key = 0; + char keyChar = '\u0000'; bool valid = !String.IsNullOrEmpty(sequence); @@ -81,6 +79,9 @@ namespace Microsoft.PowerShell // key should be first token to be popped if (key == 0) { + // the keyChar is this token + keyChar = token[0]; + // Enum.TryParse accepts arbitrary integers. We shouldn't, // but single digits need to map to the correct key, e.g. // ConsoleKey.D1 @@ -152,8 +153,6 @@ namespace Microsoft.PowerShell throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, PSReadLineResources.InvalidSequence, sequence)); } - char keyChar = GetCharFromConsoleKey(key, modifiers); - return new ConsoleKeyInfo(keyChar, key, shift: ((modifiers & ConsoleModifiers.Shift) != 0), alt: ((modifiers & ConsoleModifiers.Alt) != 0), @@ -164,6 +163,27 @@ namespace Microsoft.PowerShell { bool valid = false; +#if UNIX + bool isShift; + bool isCtrl; + key = GetKeyFromCharValue(literal, out isShift, out isCtrl); + + // Failure to get a key for the char just means that the key is not + // special (in the ConsoleKey enum), so we return a default key. + // Thus this never fails. + valid = true; + failReason = null; + + if (isShift) + { + modifiers |= ConsoleModifiers.Shift; + } + if (isCtrl) + { + modifiers |= ConsoleModifiers.Control; + } + // alt is not possible to get +#else // shift state will be in MSB short virtualKey = NativeMethods.VkKeyScan(literal); int hresult = Marshal.GetLastWin32Error(); @@ -206,30 +226,89 @@ namespace Microsoft.PowerShell Exception e = Marshal.GetExceptionForHR(hresult); failReason = e.Message; } +#endif return valid; } +#if UNIX + // this is borrowed from the CoreFX internal System.IO.StdInReader class + // https://github.com/dotnet/corefx/blob/5b2ae6aa485773cd5569f56f446698633c9ad945/src/System.Console/src/System/IO/StdInReader.cs#L222 + private static ConsoleKey GetKeyFromCharValue(char x, out bool isShift, out bool isCtrl) + { + isShift = false; + isCtrl = false; + + switch (x) + { + case '\b': + return ConsoleKey.Backspace; + + case '\t': + return ConsoleKey.Tab; + + case '\n': + return ConsoleKey.Enter; + + case (char)(0x1B): + return ConsoleKey.Escape; + + case '*': + return ConsoleKey.Multiply; + + case '+': + return ConsoleKey.Add; + + case '-': + return ConsoleKey.Subtract; + + case '/': + return ConsoleKey.Divide; + + case (char)(0x7F): + return ConsoleKey.Delete; + + case ' ': + return ConsoleKey.Spacebar; + + default: + // 1. Ctrl A to Ctrl Z. + if (x >= 1 && x <= 26) + { + isCtrl = true; + return ConsoleKey.A + x - 1; + } + + // 2. Numbers from 0 to 9. + if (x >= '0' && x <= '9') + { + return ConsoleKey.D0 + x - '0'; + } + + //3. A to Z + if (x >= 'A' && x <= 'Z') + { + isShift = true; + return ConsoleKey.A + (x - 'A'); + } + + // 4. a to z. + if (x >= 'a' && x <= 'z') + { + return ConsoleKey.A + (x - 'a'); + } + + break; + } + + return default(ConsoleKey); + } +#else internal static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modifiers) { // default for unprintables and unhandled char keyChar = '\u0000'; -#if UNIX - Type keyType = typeof (Keys); - FieldInfo[] keyFields = keyType.GetFields(); - - foreach (FieldInfo field in keyFields) - { - if (field.FieldType == typeof(ConsoleKeyInfo)) - { - ConsoleKeyInfo info = (ConsoleKeyInfo)field.GetValue(null); - if (info.Key == key && info.Modifiers == modifiers) - { - return info.KeyChar; - } - } - } -#else + // emulate GetKeyboardState bitmap - set high order bit for relevant modifier virtual keys var state = new byte[256]; state[NativeMethods.VK_SHIFT] = (byte)(((modifiers & ConsoleModifiers.Shift) != 0) ? 0x80 : 0); @@ -252,8 +331,8 @@ namespace Microsoft.PowerShell { keyChar = chars[0]; } -#endif return keyChar; } +#endif } } diff --git a/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs b/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs index 17ef3de2a..f9d1b7cc7 100644 --- a/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs +++ b/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs @@ -387,25 +387,12 @@ namespace Microsoft.PowerShell.Internal } #if UNIX - if (sb.Length > 0) - sb.Append("+"); - // TODO: find better way to map these characters to something more friendly - if ((key.Key >= ConsoleKey.D0 && key.Key <= ConsoleKey.D9) - || (key.Key >= ConsoleKey.Oem1 && key.Key <= ConsoleKey.Oem8)) - { - sb.Append(key.KeyChar); - } - else - { - if (key.Modifiers.HasFlag(ConsoleModifiers.Shift)) - { - sb.Append("Shift+"); - } - sb.Append(key.Key); - } + char c = key.KeyChar; #else + // Windows cannot use KeyChar as some chords (like Ctrl+[) show up as control characters. char c = ConsoleKeyChordConverter.GetCharFromConsoleKey(key.Key, (mods & ConsoleModifiers.Shift) != 0 ? ConsoleModifiers.Shift : 0); +#endif if (char.IsControl(c) || char.IsWhiteSpace(c)) { if (key.Modifiers.HasFlag(ConsoleModifiers.Shift)) @@ -424,7 +411,6 @@ namespace Microsoft.PowerShell.Internal sb.Append("+"); sb.Append(c); } -#endif return sb.ToString(); } } diff --git a/src/Microsoft.PowerShell.PSReadLine/KeyBindings.cs b/src/Microsoft.PowerShell.PSReadLine/KeyBindings.cs index f4843b3c4..d527dd1bd 100644 --- a/src/Microsoft.PowerShell.PSReadLine/KeyBindings.cs +++ b/src/Microsoft.PowerShell.PSReadLine/KeyBindings.cs @@ -93,9 +93,13 @@ namespace Microsoft.PowerShell { // Because a comparison of two ConsoleKeyInfo objects is a comparison of the // combination of the ConsoleKey and Modifiers, we must combine their hashes. - // This is based on Tuple.GetHashCode - int h1 = obj.Key.GetHashCode(); + // Note that if the ConsoleKey is default, we must fall back to the KeyChar, + // otherwise every non-special key will compare as the same. + int h1 = obj.Key == default(ConsoleKey) + ? obj.KeyChar.GetHashCode() + : obj.Key.GetHashCode(); int h2 = obj.Modifiers.GetHashCode(); + // This is based on Tuple.GetHashCode return unchecked(((h1 << 5) + h1) ^ h2); } } diff --git a/src/Microsoft.PowerShell.PackageManagement/Cmdlets/CmdletWithSearchAndSource.cs b/src/Microsoft.PowerShell.PackageManagement/Cmdlets/CmdletWithSearchAndSource.cs index 260542f61..50b48e6f4 100644 --- a/src/Microsoft.PowerShell.PackageManagement/Cmdlets/CmdletWithSearchAndSource.cs +++ b/src/Microsoft.PowerShell.PackageManagement/Cmdlets/CmdletWithSearchAndSource.cs @@ -42,7 +42,11 @@ namespace Microsoft.PowerShell.PackageManagement.Cmdlets { public abstract class CmdletWithSearchAndSource : CmdletWithSearch { internal readonly OrderedDictionary> _resultsPerName = new OrderedDictionary>(); protected List _providersNotFindingAnything = new List(); +#if CORECLR + internal static readonly string[] ProviderFilters = new[] { "Packagemanagement", "Provider", "PSEdition_PowerShellCore" }; +#else internal static readonly string[] ProviderFilters = new[] { "Packagemanagement", "Provider" }; +#endif protected const string Bootstrap = "Bootstrap"; protected const string PowerShellGet = "PowerShellGet"; internal static readonly string[] RequiredProviders = new[] { Bootstrap, PowerShellGet }; diff --git a/src/System.Management.Automation/project.json b/src/System.Management.Automation/project.json index 1efa7a605..bf8b88afb 100644 --- a/src/System.Management.Automation/project.json +++ b/src/System.Management.Automation/project.json @@ -21,7 +21,7 @@ }, "dependencies": { - "Microsoft.Management.Infrastructure": "1.0.0-alpha-01" + "Microsoft.Management.Infrastructure": "1.0.0-alpha02" }, "frameworks": { diff --git a/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 b/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 index aa0842b8a..d882c79e5 100644 --- a/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 +++ b/test/powershell/Modules/PSReadLine/PSReadLine.Tests.ps1 @@ -20,7 +20,7 @@ Describe "PSReadLine" -tags "CI" { It "Should use Windows Bindings on Windows" -skip:(-not $IsWindows) { (Get-PSReadLineOption).EditMode | Should Be Windows - (Get-PSReadlineKeyHandler | where { $_.Key -eq "Ctrl+A" }).Function | Should Be SelectAll + (Get-PSReadlineKeyHandler | where { $_.Key -eq "Ctrl+a" }).Function | Should Be SelectAll } It "Should set the edit mode" { @@ -31,6 +31,17 @@ Describe "PSReadLine" -tags "CI" { (Get-PSReadlineKeyHandler | where { $_.Key -eq "Ctrl+A" }).Function | Should Be BeginningOfLine } + It "Should allow custom bindings for plain keys" { + Set-PSReadlineKeyHandler -Key '"' -Function SelfInsert + (Get-PSReadLineKeyHandler | where { $_.Key -eq '"' }).Function | Should Be SelfInsert + } + + It "Should report Capitalized bindings correctly" { + Set-PSReadlineOption -EditMode Emacs + (Get-PSReadLineKeyHandler | where { $_.Key -ceq "Alt+b" }).Function | Should Be BackwardWord + (Get-PSReadLineKeyHandler | where { $_.Key -ceq "Alt+B" }).Function | Should Be SelectBackwardWord + } + AfterAll { Remove-Module PSReadLine