Skip to content

Commit 7992bec

Browse files
committed
2 parents 156fe97 + 0a7d7ce commit 7992bec

File tree

6 files changed

+134
-21
lines changed

6 files changed

+134
-21
lines changed

PSReadLine/Cmdlets.cs

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ public enum ViModeStyle
5252
Prompt,
5353
Cursor
5454
}
55+
56+
public enum ViMode
57+
{
58+
Insert,
59+
Command
60+
}
5561
#endregion vi
5662

5763
public enum HistorySaveStyle
@@ -590,15 +596,46 @@ protected override void EndProcessing()
590596
}
591597
}
592598

593-
[Cmdlet("Set", "PSReadlineKeyHandler", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=528810")]
594-
public class SetPSReadlineKeyHandlerCommand : PSCmdlet, IDynamicParameters
599+
public class ChangePSReadlineKeyHandlerCommandBase : PSCmdlet
595600
{
596601
[Parameter(Position = 0, Mandatory = true)]
597602
[Alias("Key")]
598603
[ValidateNotNullOrEmpty]
599604
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
600605
public string[] Chord { get; set; }
601606

607+
[Parameter]
608+
public ViMode ViMode { get; set; }
609+
610+
[ExcludeFromCodeCoverage]
611+
protected IDisposable UseRequestedDispatchTables()
612+
{
613+
bool inViMode = PSConsoleReadLine.GetOptions().EditMode == EditMode.Vi;
614+
bool viModeParamPresent = MyInvocation.BoundParameters.ContainsKey("ViMode");
615+
616+
if (inViMode || viModeParamPresent)
617+
{
618+
if (!inViMode)
619+
{
620+
// "-ViMode" must have been specified explicitly. Well, okay... we can
621+
// modify the Vi tables... but isn't that an odd thing to do from
622+
// not-vi mode?
623+
WriteWarning(PSReadLineResources.NotInViMode);
624+
}
625+
626+
if (ViMode == ViMode.Command)
627+
return PSConsoleReadLine.UseViCommandModeTables();
628+
else // default if -ViMode not specified, invalid, or "Insert"
629+
return PSConsoleReadLine.UseViInsertModeTables();
630+
}
631+
632+
return null;
633+
}
634+
}
635+
636+
[Cmdlet("Set", "PSReadlineKeyHandler", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=528810")]
637+
public class SetPSReadlineKeyHandlerCommand : ChangePSReadlineKeyHandlerCommandBase, IDynamicParameters
638+
{
602639
[Parameter(Position = 1, Mandatory = true, ParameterSetName = "ScriptBlock")]
603640
[ValidateNotNull]
604641
public ScriptBlock ScriptBlock { get; set; }
@@ -616,18 +653,21 @@ public class SetPSReadlineKeyHandlerCommand : PSCmdlet, IDynamicParameters
616653
[ExcludeFromCodeCoverage]
617654
protected override void EndProcessing()
618655
{
619-
if (ParameterSetName.Equals(FunctionParameterSet))
620-
{
621-
var function = (string)_dynamicParameters.Value[FunctionParameter].Value;
622-
var keyHandler = (Action<ConsoleKeyInfo?, object>)
623-
Delegate.CreateDelegate(typeof (Action<ConsoleKeyInfo?, object>),
624-
typeof (PSConsoleReadLine).GetMethod(function));
625-
BriefDescription = function;
626-
PSConsoleReadLine.SetKeyHandler(Chord, keyHandler, BriefDescription, Description);
627-
}
628-
else
656+
using (UseRequestedDispatchTables())
629657
{
630-
PSConsoleReadLine.SetKeyHandler(Chord, ScriptBlock, BriefDescription, Description);
658+
if (ParameterSetName.Equals(FunctionParameterSet))
659+
{
660+
var function = (string)_dynamicParameters.Value[FunctionParameter].Value;
661+
var keyHandler = (Action<ConsoleKeyInfo?, object>)
662+
Delegate.CreateDelegate(typeof (Action<ConsoleKeyInfo?, object>),
663+
typeof (PSConsoleReadLine).GetMethod(function));
664+
BriefDescription = function;
665+
PSConsoleReadLine.SetKeyHandler(Chord, keyHandler, BriefDescription, Description);
666+
}
667+
else
668+
{
669+
PSConsoleReadLine.SetKeyHandler(Chord, ScriptBlock, BriefDescription, Description);
670+
}
631671
}
632672
}
633673

@@ -713,18 +753,15 @@ protected override void EndProcessing()
713753
}
714754

715755
[Cmdlet("Remove", "PSReadlineKeyHandler", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=528809")]
716-
public class RemoveKeyHandlerCommand : PSCmdlet
756+
public class RemoveKeyHandlerCommand : ChangePSReadlineKeyHandlerCommandBase
717757
{
718-
[Parameter(Position = 0, Mandatory = true)]
719-
[Alias("Key")]
720-
[ValidateNotNullOrEmpty]
721-
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
722-
public string[] Chord { get; set; }
723-
724758
[ExcludeFromCodeCoverage]
725759
protected override void EndProcessing()
726760
{
727-
PSConsoleReadLine.RemoveKeyHandler(Chord);
761+
using (UseRequestedDispatchTables())
762+
{
763+
PSConsoleReadLine.RemoveKeyHandler(Chord);
764+
}
728765
}
729766
}
730767

PSReadLine/Disposable.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
3+
namespace Microsoft.PowerShell
4+
{
5+
internal sealed class Disposable : IDisposable
6+
{
7+
private Action m_onDispose;
8+
9+
public Disposable(Action onDispose)
10+
{
11+
if (onDispose == null)
12+
throw new ArgumentNullException("onDispose");
13+
14+
m_onDispose = onDispose;
15+
}
16+
17+
public void Dispose()
18+
{
19+
if (m_onDispose != null)
20+
{
21+
m_onDispose();
22+
m_onDispose = null;
23+
}
24+
}
25+
}
26+
}
27+

PSReadLine/PSReadLine.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
<Compile Include="ConsoleBufferBuilder.cs" />
5858
<Compile Include="ConsoleKeyChordConverter.cs" />
5959
<Compile Include="ConsoleLib.cs" />
60+
<Compile Include="Disposable.cs" />
6061
<Compile Include="History.cs" />
6162
<Compile Include="HistoryQueue.cs" />
6263
<Compile Include="KeyBindings.cs" />

PSReadLine/PSReadLineResources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

PSReadLine/PSReadLineResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,4 +717,7 @@ If there are other parse errors, unresolved commands, or incorrect parameters, s
717717
<data name="ViJoinLinesDescription" xml:space="preserve">
718718
<value>Joins the current multi-line edit mode line with the next.</value>
719719
</data>
720+
<data name="NotInViMode" xml:space="preserve">
721+
<value>The -ViMode parameter was used, but the current EditMode is not Vi.</value>
722+
</data>
720723
</root>

PSReadLine/ReadLine.vi.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,42 @@ public static void ViInsertMode(ConsoleKeyInfo? key = null, object arg = null)
511511
_singleton.ViIndicateInsertMode();
512512
}
513513

514+
/// <summary>
515+
/// Temporarily swap in Vi-Command dispatch tables. Used for setting handlers.
516+
/// </summary>
517+
internal static IDisposable UseViCommandModeTables()
518+
{
519+
var oldDispatchTable = _singleton._dispatchTable;
520+
var oldChordDispatchTable = _singleton._chordDispatchTable;
521+
522+
_singleton._dispatchTable = _viCmdKeyMap;
523+
_singleton._chordDispatchTable = _viCmdChordTable;
524+
525+
return new Disposable( () =>
526+
{
527+
_singleton._dispatchTable = oldDispatchTable;
528+
_singleton._chordDispatchTable = oldChordDispatchTable;
529+
} );
530+
}
531+
532+
/// <summary>
533+
/// Temporarily swap in Vi-Insert dispatch tables. Used for setting handlers.
534+
/// </summary>
535+
internal static IDisposable UseViInsertModeTables()
536+
{
537+
var oldDispatchTable = _singleton._dispatchTable;
538+
var oldChordDispatchTable = _singleton._chordDispatchTable;
539+
540+
_singleton._dispatchTable = _viInsKeyMap;
541+
_singleton._chordDispatchTable = _viInsChordTable;
542+
543+
return new Disposable( () =>
544+
{
545+
_singleton._dispatchTable = oldDispatchTable;
546+
_singleton._chordDispatchTable = oldChordDispatchTable;
547+
} );
548+
}
549+
514550
private void ViIndicateCommandMode()
515551
{
516552
if (_options.ViModeIndicator == ViModeStyle.Cursor)

0 commit comments

Comments
 (0)