Skip to content

Commit

Permalink
Add a -Chord parameter to Get-PSReadLineKeyHandler (#1298)
Browse files Browse the repository at this point in the history
  • Loading branch information
theaquamarine authored Mar 31, 2020
1 parent 8b778c6 commit fcb2c9d
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 6 deletions.
25 changes: 21 additions & 4 deletions PSReadLine/Cmdlets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -805,26 +805,32 @@ public object GetDynamicParameters()
}
}

[Cmdlet("Get", "PSReadLineKeyHandler", HelpUri = "https://go.microsoft.com/fwlink/?LinkId=528807")]
[Cmdlet("Get", "PSReadLineKeyHandler", DefaultParameterSetName = "FullListing",
HelpUri = "https://go.microsoft.com/fwlink/?LinkId=528807")]
[OutputType(typeof(KeyHandler))]
public class GetKeyHandlerCommand : PSCmdlet
{
[Parameter]
[Parameter(ParameterSetName = "FullListing")]
public SwitchParameter Bound
{
get => _bound.GetValueOrDefault();
set => _bound = value;
}
private SwitchParameter? _bound;

[Parameter]
[Parameter(ParameterSetName = "FullListing")]
public SwitchParameter Unbound
{
get => _unbound.GetValueOrDefault();
set => _unbound = value;
}
private SwitchParameter? _unbound;

[Parameter(ParameterSetName = "SpecificBindings", Position = 0, Mandatory = true)]
[ValidateNotNullOrEmpty]
[Alias("Key")]
public string[] Chord { get; set; }

[ExcludeFromCodeCoverage]
protected override void EndProcessing()
{
Expand All @@ -845,7 +851,18 @@ protected override void EndProcessing()
bound = false;
unbound = _unbound.Value.IsPresent;
}
var groups = PSConsoleReadLine.GetKeyHandlers(bound, unbound).GroupBy(k => k.Group).OrderBy(g => g.Key);

IEnumerable<PowerShell.KeyHandler> handlers;
if (ParameterSetName.Equals("FullListing", StringComparison.OrdinalIgnoreCase))
{
handlers = PSConsoleReadLine.GetKeyHandlers(bound, unbound);
}
else
{
handlers = PSConsoleReadLine.GetKeyHandlers(Chord);
}
var groups = handlers.GroupBy(k => k.Group).OrderBy(g => g.Key);

foreach (var bindings in groups)
{
WriteObject(bindings.OrderBy(k => k.Function), true);
Expand Down
83 changes: 83 additions & 0 deletions PSReadLine/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,5 +399,88 @@ public static void RemoveKeyHandler(string[] key)
}
}
}

/// <summary>
/// Return key handlers bound to specified chords.
/// </summary>
/// <returns></returns>
public static IEnumerable<PowerShell.KeyHandler> GetKeyHandlers(string[] Chord)
{
var boundFunctions = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

if (Chord == null) yield break;

foreach (string Key in Chord)
{
ConsoleKeyInfo[] consoleKeyChord = ConsoleKeyChordConverter.Convert(Key);
PSKeyInfo firstKey = PSKeyInfo.FromConsoleKeyInfo(consoleKeyChord[0]);

if (_singleton._dispatchTable.TryGetValue(firstKey, out KeyHandler entry))
{
if (consoleKeyChord.Length == 1)
{
yield return new PowerShell.KeyHandler
{
Key = firstKey.KeyStr,
Function = entry.BriefDescription,
Description = entry.LongDescription,
Group = GetDisplayGrouping(entry.BriefDescription),
};
}
else
{
PSKeyInfo secondKey = PSKeyInfo.FromConsoleKeyInfo(consoleKeyChord[1]);
if (_singleton._chordDispatchTable.TryGetValue(firstKey, out var secondDispatchTable) &&
secondDispatchTable.TryGetValue(secondKey, out entry))
{
yield return new PowerShell.KeyHandler
{
Key = firstKey.KeyStr + "," + secondKey.KeyStr,
Function = entry.BriefDescription,
Description = entry.LongDescription,
Group = GetDisplayGrouping(entry.BriefDescription),
};
}
}
}

// If in Vi mode, also check Vi's command mode list.
if (PSConsoleReadLine.GetOptions().EditMode == EditMode.Vi)
{
if (_viCmdKeyMap.TryGetValue(firstKey, out entry))
{
if (consoleKeyChord.Length == 1)
{
if (entry.BriefDescription == "Ignore") continue;
yield return new PowerShell.KeyHandler
{
Key = '<' + firstKey.KeyStr + '>',
Function = entry.BriefDescription,
Description = entry.LongDescription,
Group = GetDisplayGrouping(entry.BriefDescription),
};
}
else
{
PSKeyInfo secondKey = PSKeyInfo.FromConsoleKeyInfo(consoleKeyChord[1]);
if (_viCmdChordTable.TryGetValue(firstKey, out var secondDispatchTable) &&
secondDispatchTable.TryGetValue(secondKey, out entry))
{
if (entry.BriefDescription == "Ignore") continue;
yield return new PowerShell.KeyHandler
{
Key = '<' + firstKey.KeyStr + "," + secondKey.KeyStr + '>',
Function = entry.BriefDescription,
Description = entry.LongDescription,
Group = GetDisplayGrouping(entry.BriefDescription),
};
}
}
}
}
}
yield break;

}
}
}
20 changes: 18 additions & 2 deletions docs/Get-PSReadLineKeyHandler.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Include functions that are bound.

```yaml
Type: switch
Parameter Sets: (All)
Parameter Sets: Set 1
Aliases:

Required: False
Expand All @@ -53,7 +53,7 @@ Include functions that are unbound.
```yaml
Type: switch
Parameter Sets: (All)
Parameter Sets: Set 1
Aliases:

Required: False
Expand All @@ -63,6 +63,22 @@ Accept pipeline input: false
Accept wildcard characters: False
```
### -Chord
Return only functions bound to specific keys or sequences.
```yaml
Type: String[]
Parameter Sets: Set 2
Aliases: Key

Required: True
Position: 0
Default value:
Accept pipeline input: false
Accept wildcard characters: False
```
## INPUTS
### None
Expand Down
14 changes: 14 additions & 0 deletions test/OptionsTest.VI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ public void ViGetKeyHandlers()
Assert.False(string.IsNullOrWhiteSpace(handler.Function));
Assert.False(string.IsNullOrWhiteSpace(handler.Description));
}

var handlers = PSConsoleReadLine.GetKeyHandlers(Chord: new string[] { "home" });
Assert.NotEmpty(handlers);
foreach (var handler in handlers)
{
Assert.Contains("Home", handler.Key);
}

handlers = PSConsoleReadLine.GetKeyHandlers(Chord: new string[] { "d,0" });
Assert.NotEmpty(handlers);
foreach (var handler in handlers)
{
Assert.Equal("<d,0>", handler.Key);
}
}
}
}
25 changes: 25 additions & 0 deletions test/OptionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public void ContinuationPrompt()
[SkippableFact]
public void GetKeyHandlers()
{
System.Collections.Generic.IEnumerable<Microsoft.PowerShell.KeyHandler> handlers;

foreach (var keymode in new[] {KeyMode.Cmd, KeyMode.Emacs})
{
TestSetup(keymode);
Expand All @@ -75,6 +77,29 @@ public void GetKeyHandlers()
Assert.False(string.IsNullOrWhiteSpace(handler.Function));
Assert.False(string.IsNullOrWhiteSpace(handler.Description));
}

handlers = PSConsoleReadLine.GetKeyHandlers(Chord: new string[] { "home" });
Assert.NotEmpty(handlers);
foreach (var handler in handlers)
{
Assert.Equal("Home", handler.Key);
}
}

TestSetup(KeyMode.Emacs);

handlers = PSConsoleReadLine.GetKeyHandlers(Chord: new string[] { "ctrl+x" });
Assert.NotEmpty(handlers);
foreach (var handler in handlers)
{
Assert.Equal("Ctrl+x", handler.Key);
}

handlers = PSConsoleReadLine.GetKeyHandlers(Chord: new string[] { "ctrl+x,ctrl+e" });
Assert.NotEmpty(handlers);
foreach (var handler in handlers)
{
Assert.Equal("Ctrl+x,Ctrl+e", handler.Key);
}
}

Expand Down

0 comments on commit fcb2c9d

Please sign in to comment.