From 766d1c19d43f878ce5f202d177ed31ff3732ec38 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Thu, 6 Aug 2020 17:39:02 -0700 Subject: [PATCH 1/6] Add paging support to Get-Help --- .../System.Management.Automation.csproj | 1 + .../help/HelpCommands.cs | 140 +++++++++++++++++- 2 files changed, 136 insertions(+), 5 deletions(-) diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 187d3d7611e..bf5543607b8 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -29,6 +29,7 @@ + diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index 852db86c267..71afc9922ea 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -14,6 +14,8 @@ using System.Management.Automation.Internal; using System.Management.Automation.Runspaces; using System.Runtime.InteropServices; +using System.Text; +using Microsoft.PowerShell; #if !UNIX using Microsoft.Win32; #endif @@ -115,15 +117,21 @@ public SwitchParameter Detailed [Parameter(ParameterSetName = "AllUsersView")] public SwitchParameter Full { + private get => _full; + set { - if (value.ToBool()) + _full = value.ToBool(); + + if (_full) { _viewTokenToAdd = HelpView.FullView; } } } + private bool _full; + /// /// Changes the view of HelpObject returned. /// @@ -141,15 +149,24 @@ public SwitchParameter Full [Parameter(ParameterSetName = "Examples", Mandatory = true)] public SwitchParameter Examples { + private get + { + return _examples; + } + set { - if (value.ToBool()) + _examples = value.ToBool(); + + if (_examples) { _viewTokenToAdd = HelpView.ExamplesView; } } } + private bool _examples; + /// /// Parameter name. /// @@ -202,6 +219,20 @@ public SwitchParameter Online private bool _showOnlineHelp; + /// + /// This parameter,if true, will direct get-help cmdlet to + /// display the help content using Microsoft.PowerShell.Pager on alternate screen buffer. + /// + [Parameter] + public SwitchParameter Paged + { + get; + set; + } + + private Pager pager; + private string multiItemPagerBuffer; + #if !UNIX private GraphicalHostReflectionWrapper graphicalHostReflectionWrapper; private bool showWindow; @@ -336,6 +367,16 @@ protected override void ProcessRecord() { throw PSTraceSource.NewInvalidOperationException(HelpErrors.MultipleOnlineTopicsNotSupported, "Online"); } + else if (Paged && countOfHelpInfos > 1) + { + if (pager is null) + { + pager = new Pager(); + } + + pager.Write(multiItemPagerBuffer); + + } // show errors only if there is no wildcard search or VerboseHelpErrors is true. if (((countOfHelpInfos == 0) && (!WildcardPattern.ContainsWildcardCharacters(helpRequest.Target))) @@ -496,7 +537,7 @@ private void GetAndWriteParameterInfo(HelpInfo helpInfo) { foreach (PSObject pInfo in pInfos) { - WriteObject(pInfo); + WriteObjectOrWritePaged(pInfo, bufferOutputWhenPaged: false); } } } @@ -597,7 +638,7 @@ private void WriteObjectsOrShowOnlineHelp(HelpInfo helpInfo, bool showFullHelp) { PSObject objectToReturn = TransformView(helpInfo.FullHelp); objectToReturn.IsHelpObject = true; - WriteObject(objectToReturn); + WriteObjectOrWritePaged(objectToReturn, bufferOutputWhenPaged: false); } } else @@ -612,12 +653,101 @@ private void WriteObjectsOrShowOnlineHelp(HelpInfo helpInfo, bool showFullHelp) } } - WriteObject(helpInfo.ShortHelp); + WriteObjectOrWritePaged(helpInfo.ShortHelp, bufferOutputWhenPaged: true); } } } } + private void WriteObjectOrWritePaged(object sendToPipeline, bool bufferOutputWhenPaged) + { + if (Paged) + { + if (pager is null) + { + pager = new Pager(); + } + + var helpText = GetHelpOutput(); + + if (bufferOutputWhenPaged) + { + multiItemPagerBuffer = helpText; + } + else + { + pager.Write(helpText); + } + } + else + { + WriteObject(sendToPipeline); + } + } + + private string GetHelpOutput() + { + string helpContentAsString = null; + + using (var ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace)) + { + ps.AddCommand(@"Microsoft.PowerShell.Core\Get-Help"); + + StringBuilder sb = new StringBuilder(); + + if (!string.IsNullOrEmpty(this.Name)) + { + ps.AddParameter(nameof(this.Name), this.Name); + } + + if (this.Category is not null) + { + ps.AddParameter(nameof(this.Category), this.Category); + } + + if (this.Component is not null) + { + ps.AddParameter(nameof(this.Component), this.Component); + } + + if (this.Functionality is not null) + { + ps.AddParameter(nameof(this.Functionality), this.Functionality); + } + + if (!string.IsNullOrEmpty(this.Path)) + { + ps.AddParameter(nameof(this.Path), this.Path); + } + + if (this.Role is not null) + { + ps.AddParameter(nameof(this.Role), this.Role); + } + + if (this.Examples) + { + ps.AddParameter(nameof(this.Examples), this.Examples); + } + + if (this.Full) + { + ps.AddParameter(nameof(this.Full), this.Full); + } + + if (this.Parameter is not null) + { + ps.AddParameter(nameof(this.Parameter), this.Parameter); + } + + ps.AddCommand(@"Microsoft.PowerShell.Utility\Out-String"); + + helpContentAsString = ps.Invoke().FirstOrDefault(); + } + + return helpContentAsString; + } + /// /// Opens the Uri. System's default application will be used /// to show the uri. From 467e137772a12ad42dd13675eb0868cef3912801 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Fri, 7 Aug 2020 11:39:11 -0700 Subject: [PATCH 2/6] Address feedback from Ilya --- .../help/HelpCommands.cs | 122 ++++++++---------- 1 file changed, 56 insertions(+), 66 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index 71afc9922ea..b490100f712 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -230,8 +230,11 @@ public SwitchParameter Paged set; } - private Pager pager; - private string multiItemPagerBuffer; + private Microsoft.PowerShell.Pager Pager => _pager ??= new Microsoft.PowerShell.Pager(); + + private Pager _pager; + + private string _multiItemPagerBuffer; #if !UNIX private GraphicalHostReflectionWrapper graphicalHostReflectionWrapper; @@ -369,13 +372,7 @@ protected override void ProcessRecord() } else if (Paged && countOfHelpInfos > 1) { - if (pager is null) - { - pager = new Pager(); - } - - pager.Write(multiItemPagerBuffer); - + Pager.Write(_multiItemPagerBuffer); } // show errors only if there is no wildcard search or VerboseHelpErrors is true. @@ -537,7 +534,7 @@ private void GetAndWriteParameterInfo(HelpInfo helpInfo) { foreach (PSObject pInfo in pInfos) { - WriteObjectOrWritePaged(pInfo, bufferOutputWhenPaged: false); + WriteObjectPaged(pInfo, bufferOutputWhenPaged: false); } } } @@ -638,7 +635,7 @@ private void WriteObjectsOrShowOnlineHelp(HelpInfo helpInfo, bool showFullHelp) { PSObject objectToReturn = TransformView(helpInfo.FullHelp); objectToReturn.IsHelpObject = true; - WriteObjectOrWritePaged(objectToReturn, bufferOutputWhenPaged: false); + WriteObjectPaged(objectToReturn, bufferOutputWhenPaged: false); } } else @@ -653,30 +650,28 @@ private void WriteObjectsOrShowOnlineHelp(HelpInfo helpInfo, bool showFullHelp) } } - WriteObjectOrWritePaged(helpInfo.ShortHelp, bufferOutputWhenPaged: true); + WriteObjectPaged(helpInfo.ShortHelp, bufferOutputWhenPaged: true); } } } } - private void WriteObjectOrWritePaged(object sendToPipeline, bool bufferOutputWhenPaged) + private void WriteObjectPaged(object sendToPipeline, bool bufferOutputWhenPaged) { if (Paged) { - if (pager is null) - { - pager = new Pager(); - } - var helpText = GetHelpOutput(); if (bufferOutputWhenPaged) { - multiItemPagerBuffer = helpText; + // The output from GetHelpOutput has all the item in the output. + // We just need to store it and then write to Pager later. + // No need to append them. + _multiItemPagerBuffer = helpText; } else { - pager.Write(helpText); + Pager.Write(helpText); } } else @@ -687,65 +682,60 @@ private void WriteObjectOrWritePaged(object sendToPipeline, bool bufferOutputWhe private string GetHelpOutput() { - string helpContentAsString = null; - - using (var ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace)) - { - ps.AddCommand(@"Microsoft.PowerShell.Core\Get-Help"); - - StringBuilder sb = new StringBuilder(); + using PowerShell ps = PowerShell.Create(RunspaceMode.CurrentRunspace); - if (!string.IsNullOrEmpty(this.Name)) - { - ps.AddParameter(nameof(this.Name), this.Name); - } + ps.AddCommand(@"Microsoft.PowerShell.Core\Get-Help"); - if (this.Category is not null) - { - ps.AddParameter(nameof(this.Category), this.Category); - } + StringBuilder sb = new StringBuilder(); - if (this.Component is not null) - { - ps.AddParameter(nameof(this.Component), this.Component); - } + if (!string.IsNullOrEmpty(this.Name)) + { + ps.AddParameter(nameof(this.Name), this.Name); + } - if (this.Functionality is not null) - { - ps.AddParameter(nameof(this.Functionality), this.Functionality); - } + if (this.Category is not null) + { + ps.AddParameter(nameof(this.Category), this.Category); + } - if (!string.IsNullOrEmpty(this.Path)) - { - ps.AddParameter(nameof(this.Path), this.Path); - } + if (this.Component is not null) + { + ps.AddParameter(nameof(this.Component), this.Component); + } - if (this.Role is not null) - { - ps.AddParameter(nameof(this.Role), this.Role); - } + if (this.Functionality is not null) + { + ps.AddParameter(nameof(this.Functionality), this.Functionality); + } - if (this.Examples) - { - ps.AddParameter(nameof(this.Examples), this.Examples); - } + if (!string.IsNullOrEmpty(this.Path)) + { + ps.AddParameter(nameof(this.Path), this.Path); + } - if (this.Full) - { - ps.AddParameter(nameof(this.Full), this.Full); - } + if (this.Role is not null) + { + ps.AddParameter(nameof(this.Role), this.Role); + } - if (this.Parameter is not null) - { - ps.AddParameter(nameof(this.Parameter), this.Parameter); - } + if (this.Examples) + { + ps.AddParameter(nameof(this.Examples), this.Examples); + } - ps.AddCommand(@"Microsoft.PowerShell.Utility\Out-String"); + if (this.Full) + { + ps.AddParameter(nameof(this.Full), this.Full); + } - helpContentAsString = ps.Invoke().FirstOrDefault(); + if (this.Parameter is not null) + { + ps.AddParameter(nameof(this.Parameter), this.Parameter); } - return helpContentAsString; + ps.AddCommand(@"Microsoft.PowerShell.Utility\Out-String"); + + return ps.Invoke().FirstOrDefault(); } /// From be0ca5a54fee5cec8d4f932c8635d296d69aba78 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Fri, 7 Aug 2020 15:13:07 -0700 Subject: [PATCH 3/6] Use new syntax for using --- src/System.Management.Automation/help/HelpCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index b490100f712..d8f04b4316c 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -682,7 +682,7 @@ private void WriteObjectPaged(object sendToPipeline, bool bufferOutputWhenPaged) private string GetHelpOutput() { - using PowerShell ps = PowerShell.Create(RunspaceMode.CurrentRunspace); + using System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace); ps.AddCommand(@"Microsoft.PowerShell.Core\Get-Help"); From 23f305bcd9d4d044e3025d4149faa691e328631c Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Fri, 7 Aug 2020 15:13:27 -0700 Subject: [PATCH 4/6] Update wix --- assets/files.wxs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/files.wxs b/assets/files.wxs index cc24064ddb8..5d7b42ca97e 100644 --- a/assets/files.wxs +++ b/assets/files.wxs @@ -3108,6 +3108,9 @@ + + + @@ -4110,6 +4113,7 @@ + From 3c401033085dfe8ff810acdf6efcdd240dc708da Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 11 Aug 2020 07:11:41 -0700 Subject: [PATCH 5/6] Update comment as per CR feedback Co-authored-by: James Truher [MSFT] --- src/System.Management.Automation/help/HelpCommands.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index d8f04b4316c..aebfc226f70 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -220,7 +220,7 @@ public SwitchParameter Online private bool _showOnlineHelp; /// - /// This parameter,if true, will direct get-help cmdlet to + /// This parameter, if true, will direct get-help cmdlet to /// display the help content using Microsoft.PowerShell.Pager on alternate screen buffer. /// [Parameter] @@ -1008,4 +1008,3 @@ Uri result in } } } - From 09f33a86c1e1be05fe136b6965562a94b6480c71 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 11 Aug 2020 10:44:42 -0700 Subject: [PATCH 6/6] Remove unused string builder --- src/System.Management.Automation/help/HelpCommands.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index d8f04b4316c..d7ca667d2fb 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -686,8 +686,6 @@ private string GetHelpOutput() ps.AddCommand(@"Microsoft.PowerShell.Core\Get-Help"); - StringBuilder sb = new StringBuilder(); - if (!string.IsNullOrEmpty(this.Name)) { ps.AddParameter(nameof(this.Name), this.Name);