-
Notifications
You must be signed in to change notification settings - Fork 234
Change Get-Help behavior to return local help when no online help available #721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good but I have a few ideas to make it a bit more readable :)
IEnumerable<object> isCommand = await editorSession.PowerShellContext.ExecuteCommand<object>(psCommand); | ||
if (isCommand != null && isCommand.Count() > 0){ | ||
psCommand = new PSCommand(); | ||
psCommand.AddCommand("Get-Help"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to chain this:
psCommand.AddCommand("Get-Help")
.AddArgument(helpParams)
.AddCommand("Select-Object")
.AddArgument("RelatedLinks")
etc...
PSCommand psCommand = new PSCommand(); | ||
// Check if it's an actual command first. This returns near instant. Get-Help takes a good 5 seconds to return when not a command. | ||
psCommand.AddCommand("Get-Command").AddArgument(helpParams); | ||
IEnumerable<object> isCommand = await editorSession.PowerShellContext.ExecuteCommand<object>(psCommand); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you think you could use something instead of object
here? It should be a CmdletInfo
I think
IEnumerable<object> relatedLinks = await editorSession.PowerShellContext.ExecuteCommand<object>(psCommand); | ||
psCommand = new PSCommand(); | ||
psCommand.AddCommand("Get-Help"); | ||
psCommand.AddArgument(helpParams); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chain ALL the thingssss
psCommand.AddArgument(helpParams); | ||
psCommand.AddCommand("Select-Object").AddArgument("RelatedLinks"); | ||
IEnumerable<object> relatedLinks = await editorSession.PowerShellContext.ExecuteCommand<object>(psCommand); | ||
psCommand = new PSCommand(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could probably be a bit more descriptive here :) have a new variable instead of reusing psCommand
and call it like... getHelpCommand
... call the previous one getRelatedLinksCommand
etc.
bool sendOutput = false; | ||
// Check if the first returned item converted to string is an empty object. | ||
// From experience this is the return when there are no RelatedLinks. | ||
if (relatedLinks != null && relatedLinks.First().ToString() != "@{RelatedLinks=}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we could probably handle this a little better.
Also something I noticed:
A module could have a related links section but Online version would be empty:
(Get-Help AdvancedHistory).RelatedLinks
Online Version:
(Get-Help AdvancedHistory | Select-Object RelatedLinks)
relatedLinks
------------
@{navigationLink=@{linkText=Online Version:; uri=}}
So comparing the ToString value might not be enough. You can use PSCustomObjects in C# and drill into them like a hashtable so maybe try to do that.
(Get-Help AdvancedHistory | Select-Object RelatedLinks)[0].relatedLinks.navigationLink.uri
for example returns nothing. @omniomi is to blame for that module :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another option (which I'm liking better) is to convert 95% of this logic into a PowerShell script and just use AddScript
. Especially since this function doesn't return anything, this would be a good time to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funny, I asked about the related links in slack and was told that there would never be a related link without a online version. Clearly this is false, so this needs to be fixed. I like the idea of the powershell script instead. I might even still have one in the commit history (or I might have removed it...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drilling down a PSObject is kind of obtuse in C#, but it's still probably better to keep it in C#. I'd just make it a static helper method like this
internal static bool TryGetHelpUri(PSObject helpInfo, out string helpUri)
{
PSObject links = helpInfo.Properties['relatedLinks']?.Value as PSObject;
if (links == null)
{
return false;
}
PSObject[] navigation = links.Properties['navigationLink']?.Value as PSObject[];
if (navigation == null)
{
return false;
}
helpUri = navigation.FirstOrDefault()?.Properties['uri']?.Value as string;
return !string.IsNullOrWhiteSpace(helpUri);
}
PSObject helpInfo = MethodThatInvokesGetHelp();
if (TryGetHelpUri(helpInfo, out string helpUri)
{
// use help uri
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's better. 👌
I've refactored the code to use a PowerShell function to check for if the command exists instead of executing a bunch of times and then delving into a property that doesn't seem to be completely consistent. The PowerShell function operates off of the presumption that the Get-Command and Get-Help cmdlets will error with predictable exceptions and we catch those exceptions only for our handling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good :) just a couple changes
Get-Command $Command -ErrorAction Stop | ||
$CommandExists = $true | ||
} catch [System.Management.Automation.CommandNotFoundException] { | ||
Write-Warning ""$Command does not exist."" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a warning, I'd prefer if it just let the exception come through.
Maybe to clean up the error message a little bit by using ThrowTerminatingError
(requires [CmdletBinding()]
)
} catch [System.Management.Automation.CommandNotFoundException] {
$PSCmdlet.ThrowTerminatingError($PSItem)
return
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! I was trying to do Write-Error, but it was too much information, and it output the __Check-Help function name. The only thing perhaps is that this causes an uncaught exception in the debugger. Should we be wrapping the script execution in a try catch block?
Also output to Host. This is an expiriment on vscode-powershell issue 884.
If not a command, Get-Help takes 4-5 seconds to return, and we will crash PSES if we don't account for the return of a 0 count.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I just have a few comments :)
await editorSession.PowerShellContext.ExecuteCommand<object>(psCommand); | ||
|
||
if (helpParams == null) { helpParams = "Get-Help"; } | ||
string script = @" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should pull this script out to a static private property so it's not created every time the function is run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved this to a static private property, not sure if positioning it at the top of the file is the best spot for it, or what the convention is for this type of scenario.
Try { | ||
Microsoft.PowerShell.Core\Get-Command $CommandName -ErrorAction Stop | Out-Null | ||
} catch [System.Management.Automation.CommandNotFoundException] { | ||
$PSCmdlet.ThrowTerminatingError($PSItem) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, based on your logic here, that this this ThrowTerminatingError
is redundant if you already have ErrorAction Stop
@SeeminglyScience correct me if I'm wrong here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in other words you might be able to ditch the try/catch all together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it with the try catch because without it looks like this:
But I will go with whichever you and @SeeminglyScience want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tylerl0706 the benefit of using ThrowTerminatingError
over letting the exception propagate is that it changes the "context" of the error from the callee(?) to the caller.
Here's a little function you can use to check it out
function Test-TerminatingError {
[CmdletBinding()]
param(
[Parameter(Position = 0, Mandatory)]
[ValidateSet('NormalThrow', 'ThrowTerminatingError')]
[string] $ThrowType
)
end {
if ($ThrowType -eq 'NormalThrow') { j
Get-Command DefinitelyDoesntExist -ErrorAction Stop
}
try {
Get-Command DefinitelyDoesntExist -ErrorAction Stop
} catch {
$PSCmdlet.ThrowTerminatingError($PSItem)
}
}
}
If NormalThrow
is specified, this is what is displayed
Get-Command : The term 'DefinitelyDoesntExist' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:11 char:13
+ Get-Command DefinitelyDoesntExist -ErrorAction Stop
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (DefinitelyDoesntExist:String) [Get-Command], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand
It shows the line in the function/script itself that failed, which is implementation detail the user doesn't care about. Contrast that to this:
Test-TerminatingError : The term 'DefinitelyDoesntExist' is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct
and try again.
At line:1 char:1
+ Test-TerminatingError ThrowTerminatingError
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (DefinitelyDoesntExist:String) [Test-TerminatingError], CommandNotFoundE
xception
+ FullyQualifiedErrorId : CommandNotFoundException,Test-TerminatingError
It also lets you fully (well mostly) customize the displayed error by creating your own ErrorRecord
All that said, @corbob that is definitely not how I expected that to look... something in our host does not handle that right...
We should still stick with it, but we should definitely look into why that's doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SeeminglyScience should we be opening an issue for "something in our host does not handle that right...
...
we should definitely look into why that's doing that." ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few more things ;)
Also: * make CheckHelpScript constant * assign output of Get-Command to $null * Move CheckHelpScript to top of class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🎉 thanks for putting up with our comments 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@@ -251,8 +251,9 @@ protected Task Stop() | |||
{ | |||
if (helpParams == null) { helpParams = "Get-Help"; } | |||
|
|||
PSCommand checkHelpPSCommand = new PSCommand(); | |||
checkHelpPSCommand.AddScript(CheckHelpScript, useLocalScope: true).AddArgument(helpParams); | |||
PSCommand checkHelpPSCommand = new PSCommand() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was about to complain about the lack of var
here, but technically the type here is the return type of the method. So all I feel is ambivalence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used PSCommand due to all the other comments about being explicit about the variable type 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wholly agree. In general you wouldn't lose explicit variable type constraints with var
when the constructor is on the RHS of the assignment (var x = new Banana();
), but here it's more nuanced because of a sort of Builder pattern scenario...
{ | ||
public static readonly | ||
RequestType<string, object, object, object> Type = | ||
RequestType<string, object, object, object>.Create("powerShell/showOnlineHelp"); | ||
RequestType<string, object, object, object>.Create("powerShell/showHelp"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to play Devil's advocate here:
Is the reason for the breaking change just that "showOnlineHelp" would be an inaccurate name? Or does possibly getting offline help make the change breaking too?
Just thinking that there are plenty of APIs where the message name doesn't quite mean what it used to because changing the message name is a bigger breaking change than changing what the message does.
It may be that we want to break the message compatibility anyway, but we do have other clients that might benefit from us not changing the name.
Anyway, just want to ask the question: "if we change the functionality but not the message name, is this still a breaking change?" with the followup "if the message name change is the breaking change, is it worth the breakage?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given this is a command in the command pallet and not a settings related change or something along those lines... I think if someone complains we can consider a patch that will re-ADD the old functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what @rjmholt is talking about is breaking on both sides with the change of the message as PSES isn't used exclusively by vscode-powershell. I'm not opposed to keeping the message name the old one (in fact I think it should be a matter of just backing out a single commit on both sides...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds reasonable!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm game 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh sure, now I need to first remove my big foot from my mouth and figure out how to rewrite the git history...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There we go, apparently it's a simple interactive rebase off of master 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depending on how brave you feel:
Brave way that deletes history
git reset --hard HEAD~1
There's a safer way to do it without git revert
that I can't find a good answer for.
It makes no difference to the repo, since it will all be squashed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the interactive rebase allowed me to delete the commits that changed the wording of the message (which is partly why I made them separate commits) while still preserving the super difficult minor bug fix commit at the end there.
Last minute commit that hopefully doesn't change the approvals 😜 I was looking at the overall changes and was reminded of a scenario where I found if nothing was sent across it was actually empty string and not null (discovered while working on the Command Explorer). I believe the only way for this to happen with the Show Help is if we have a completely empty file and try, but this at least prevents an error in that instance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're watching you @corbob 😎
@@ -249,7 +249,7 @@ protected Task Stop() | |||
string helpParams, | |||
RequestContext<object> requestContext) | |||
{ | |||
if (helpParams == null) { helpParams = "Get-Help"; } | |||
if (helpParams == "") { helpParams = "Get-Help"; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth just making this string.IsNullOrEmpty(helpParams)
. We lose nothing really if the string is never null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what you're talking about... it's definitely string.IsNullOrEmpty whistles innocently
helpParams doesn't actually come over null... It comes over as empty string. Fix this to prevent a likely rare bug condition because we can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 😊
[String]$CommandName | ||
) | ||
Try { | ||
$null = Microsoft.PowerShell.Core\Get-Command $CommandName -ErrorAction Stop |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for module prefixed commands!
param ( | ||
[String]$CommandName | ||
) | ||
Try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below you use a lower case try
(and everywhere else uses lower case keywords). Probably should tweak that here to be consistent. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll get this corrected after the below comment is replied to so I'm not doing a bunch of extra work :)
[String]$CommandName | ||
) | ||
Try { | ||
$null = Microsoft.PowerShell.Core\Get-Command $CommandName -ErrorAction Stop |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this script is only used in the HandleShowOnlineHelpRequest
method, then it should be moved inside that method as a const string
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to make sense. As was said in slack: if it's a const string
it won't be stack alloc'd each time the methos is invoked. https://stackoverflow.com/questions/7616448/const-string-inside-a-function
Unless @tylerl0706 @SeeminglyScience or @rjmholt have any objections I'll move the string back into the function as const
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reasonable to me! Let's hear what 1 other has to say
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep no issues with that 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the string into the function as const
(also creeped the scope a bit by handling both commands that could come in (although not from vscode-powershell...) and marking one as deprecated.
If someone calls showOnlineHelp we will write a warning that it's deprecated and then call showHelp. This should allow us to more easily update to remove the references to Online. Also: Move CheckHelpScript into the function and make it constant...
) | ||
{ | ||
const string deprecatedWarning = @" | ||
Write-Warning ""'powerShell/showOnlineHelp' has been deprecated. Use 'powerShell/showHelp' instead."""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooh, does this show in the Integrated Console?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does 😃 it's due to sendOutputToHost: true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM3!
@@ -7,10 +7,18 @@ | |||
|
|||
namespace Microsoft.PowerShell.EditorServices.Protocol.LanguageServer | |||
{ | |||
// We don't expect ShowOnlineHelpRequest to come from vscode anymore, but it could come from another editor. | |||
// TODO: Note that it's deprecated if it's called??? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might be able to mark this with the [Obsolete]
attribute :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🎉
public class ShowOnlineHelpRequest | ||
{ | ||
public static readonly | ||
RequestType<string, object, object, object> Type = | ||
RequestType<string, object, object, object>.Create("powerShell/showOnlineHelp"); | ||
} | ||
public class ShowHelpRequest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: the indentation of this line is a bit off
@@ -230,22 +231,45 @@ protected Task Stop() | |||
} | |||
}); | |||
} | |||
|
|||
protected async Task HandleShowOnlineHelpRequest( | |||
protected async Task HandleShowHelpRequest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: newline between functions
Write-Warning ""'powerShell/showOnlineHelp' has been deprecated. Use 'powerShell/showHelp' instead."""; | ||
PSCommand commandDeprecated = new PSCommand() | ||
.AddScript(deprecatedWarning); | ||
await editorSession.PowerShellContext.ExecuteCommand<PSObject>(commandDeprecated, sendOutputToHost: true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of (or in addition to) a PSIC warning, we could log a warning to the log file. I could go either way on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 on log file Actually, users won't read the log file, and it won't be relevant when looking back through the logs. We should warn the user somehow.
The ideal would be to launch a popup. But that would be a lot for this PR. Perhaps instead we can leave it as a PSIC message and open an issue to make a popup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
) | ||
{ | ||
const string deprecatedWarning = @" | ||
Write-Warning ""'powerShell/showOnlineHelp' has been deprecated. Use 'powerShell/showHelp' instead."""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of AddScript
you could use AddCommand
here instead.
pwsh.AddCommand("Microsoft.PowerShell.Utility\\Write-Verbose")
.AddParameter("Message", "'powerShell/showOnlineHelp' has been deprecated. Use 'powerShell/showHelp instead.");
Using command instead allows it to create a command processor for that command specifically, instead of having to parse a script.
PSCommand commandDeprecated = new PSCommand() | ||
.AddScript(deprecatedWarning); | ||
.AddCommand("Microsoft.PowerShell.Utility\\Write-Verbose") | ||
.AddParameter("Message", ";powerShell/showOnlineHelp' has been deprecated. Use 'powerShell/showHelp' instead."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo here I think (from ; to ')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok this looks good to me! If you can just make the whitespace changes, we can merge this in and then the vscode one :)
|
||
namespace Microsoft.PowerShell.EditorServices.Protocol.LanguageServer | ||
{ | ||
[Obsolete("This class is deprecated. Use ShowHelpRequest instead.")] | ||
public class ShowOnlineHelpRequest | ||
{ | ||
public static readonly | ||
RequestType<string, object, object, object> Type = | ||
RequestType<string, object, object, object>.Create("powerShell/showOnlineHelp"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a newline here?
@@ -122,6 +122,7 @@ public void Start() | |||
this.HandleDocumentRangeFormattingRequest); | |||
|
|||
this.messageHandlers.SetRequestHandler(ShowOnlineHelpRequest.Type, this.HandleShowOnlineHelpRequest); | |||
this.messageHandlers.SetRequestHandler(ShowHelpRequest.Type, this.HandleShowHelpRequest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add newlines around this line to keep the style consistent?
} catch [System.Management.Automation.PSInvalidOperationException] { | ||
Microsoft.PowerShell.Core\Get-Help $CommandName -Full | ||
}"; | ||
if (string.IsNullOrEmpty(helpParams)) { helpParams = "Get-Help"; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a newline above this if
PSCommand checkHelpPSCommand = new PSCommand() | ||
.AddScript(CheckHelpScript, useLocalScope: true) | ||
.AddArgument(helpParams); | ||
await editorSession.PowerShellContext.ExecuteCommand<PSObject>(checkHelpPSCommand, sendOutputToHost: true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a newline above the first await
statement
await requestContext.SendResult(null); | ||
} | ||
protected async Task HandleShowOnlineHelpRequest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely add a newline before this method definition here
PSCommand commandDeprecated = new PSCommand() | ||
.AddCommand("Microsoft.PowerShell.Utility\\Write-Verbose") | ||
.AddParameter("Message", ";powerShell/showOnlineHelp' has been deprecated. Use 'powerShell/showHelp' instead."); | ||
await editorSession.PowerShellContext.ExecuteCommand<PSObject>(commandDeprecated, sendOutputToHost: true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a newline above this await
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ship it 🚢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sold!
This doesn't seem to be working now that it's merged in. Going to investigate today. |
Can't reproduce the behaviour I saw earlier. But it looks like What scenarios would trigger the offline help? I'm trying to think of a way to identify when online help is inaccessible and fall back appropriately. |
Spoke to @adityapatwardhan offline.
There's also no simple way to get the help URL out of He suggested getting local help first and falling back to online instead. The problem is the Ideally what we turn this into would be:
|
What about Note: The |
Current behavior is to attempt to show online help. This returns an error when there is no online help. Would be better to return full output of online help if there is some.
Furthermore: if you try to get help for a command that doesn't exist, currently it takes 4-5 seconds and doesn't do anything. This will change that to less than a second and return an error.
Addresses some of the discussion around PowerShell/vscode-powershell#884