Skip to content
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

PSReadLine Error with Uncuddled 'Else' #1127

Closed
gabrieljtaylor opened this issue Oct 25, 2019 · 18 comments
Closed

PSReadLine Error with Uncuddled 'Else' #1127

gabrieljtaylor opened this issue Oct 25, 2019 · 18 comments
Labels
Resolution-Duplicate There's another issue on the tracker that's pretty much the same thing.

Comments

@gabrieljtaylor
Copy link

PSReadLine frequently (but inconsistently) throws an error when running multiline 'If' statements with uncuddled 'Else' clauses, either by Copy/Pasting the text into the terminal or using the "Run Selection" (F8) command in Visual Studio Code. It appears that sometimes PSReadLine is interpreting the pasted text as a multiline string/command (pasting the full content at once with the subsequent lines being preceded by ">>" instead of the normal prompt"), while other times each line is processed individually, causing the 'If' statement to be seen as concluded after it's closing brace, since the uncuddled 'Else' clause is not yet being processed.

The specific error text is this:

else : The term 'else' 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

I have tested pasting/running the same text in terminals/shells both with and without PSReadLine loaded; the error receiving the pasted text never occurs when PSReadLine is unloaded, only occurring when PSReadLine has been imported. That being said, the error is inconsistent - there are times (though more infrequent) that I can paste text (or Run selection) and it is processed properly even with PSReadLine present, though most frequently the error is thrown. This inconsistency can be within a single session - the multiline statements are sometimes interpreted correctly several times before PSReadLine begins to fail processing (instead processing the input line-by-line rather than as one multiline command). Additionally, sometimes after the errors have been generated several times, suddenly the multiline command will begin being processed properly for a bit. It is wildly inconsistent.

Environment data

Issue encountered in multiple places:

(VS code terminal)
PS version: 5.1.18362.145
PSReadline version: 2.0.0-beta5
os: 10.0.18362.1 (WinBuild.160101.0800)
PS file version: 10.0.18362.1 (WinBuild.160101.0800)
HostName: ConsoleHost
BufferWidth: 236
BufferHeight: 19

(VS code integrated terminal)
PS version: 5.1.18362.145
PSReadline version: 2.0.0-beta5
os: 10.0.18362.1 (WinBuild.160101.0800)
PS file version: 10.0.18362.1 (WinBuild.160101.0800)
HostName: Visual Studio Code Host
BufferWidth: 236
BufferHeight: 19

(PS 6 shell)
PS version: 6.2.0
PSReadline version: 2.0.0-beta3
os: 10.0.18362.1 (WinBuild.160101.0800)
PS file version: 6.2.0.0
HostName: ConsoleHost
BufferWidth: 200
BufferHeight: 5000

(Windows PS 5.1 shell)
PS version: 5.1.18362.145
PSReadline version: 2.0.0-beta5
os: 10.0.18362.1 (WinBuild.160101.0800)
PS file version: 10.0.18362.1 (WinBuild.160101.0800)
HostName: ConsoleHost
BufferWidth: 120
BufferHeight: 3000

Steps to reproduce or exception report

Using the following sample code:

$service = Get-Service -Name wuauserv
if ($service.Status -eq "Running")
{
Write-Host "Service $($service.ServiceName) is Running"
}
elseif ($service.Status -eq "Stopped")
{
Write-Host "Service $($service.ServiceName) is Stopped"
}
else
{
Write-Host "Service $($service.ServiceName) is neither Running nor Stopped. It's actual status is $($service.Status)."
}

In a PowerShell terminal in VSCode or a PowerShell shell (tested in v5.1 and v6.2), paste the above text, without pressing 'Enter'.

Desired Result:
image
image
(this second image has the PSReadLine module removed first because I was not lucky enough to be able to reproduce the desired result while the module was installed. This does also illustrate that the problem does not exist when the module is not installed.)

Actual Result:
image
image

@msftrncs
Copy link
Collaborator

There are a few factors that control this.

  1. The line endings in the pasting. LF will work better than CR/LF. The line endings can vary depending on where you are pasting from, and the method used to paste, right click or CTRL-V. This is because LF is not the same as the ENTER key, that's CR, so LF doesn't execute the current statement, CR does, if it can.
  2. The presence of a surrounding grouping. A surrounding grouping will encourage PSReadline to accept more input in the current command.
  3. The method used for pasting. CTRL-V should always work better (in ConsoleHost anyway), results will vary with right-click pasting, because that's provided by the console host, and not PSReadLine. Note, CTRL-V in VS Code is not the same as CTRL-V in ConsoleHost.

A quick test of your example demonstrates that CTRL-V works fine, right click paste will fail with uncuddled continuing statements. Note that I copied directly from this post using Microsoft Edge. I could not demonstrate a difference attempting to set line endings in VS Code to LF, but I know, at least at one time, there used to be a difference.

@vexx32
Copy link

vexx32 commented Oct 25, 2019

Right-click paste typically fails regardless of line endings in my experience. It enters the lines as-is, and I don't think the right-click-paste typically has the capability to differentiate between a line break and a return (because that difference is made possible by PSReadLine, which has zero control over the right-click-paste functionality).

Right-click-paste is implemented by a given terminal implementation; PSReadLine can't touch it, as far as I'm aware.

@gabrieljtaylor
Copy link
Author

gabrieljtaylor commented Oct 25, 2019 via email

@msftrncs
Copy link
Collaborator

I've never had F8 fail to work with PowerShell Extension in VS Code. I'll have to play with that. However, the F8 function of the extension uses internal methods to pass the command to the integrated console, so its a whole different animal.

I cannot replicate your findings with Windows PowerShell (5.1). This might be a setting in your console? There is a setting as to whether to support CTRL-V, and I think it needs to be turned off, so that PSReadLine can handle it instead.

@msftrncs
Copy link
Collaborator

@vexx32, @gabrieljtaylor … I think I see where this might fail with F8 … Its the F8 function that potentially sends the selection exactly as its file data represents in the editor, so if line endings are LF, then F8 only sends LF's, else it sends CRLF. It then behaves differently again between a regular shell, and the integrated PowerShell console.

Example: (put in a file, use F8, changing line endings and shell)

"
hello
" | format-hex

@msftrncs
Copy link
Collaborator

It appears that F8 to a regular PowerShell terminal performs the same operation as paste, where as F8 to the PowerShell Integrated Console uses a private method to pass the command, and so does not replicate this issue.

@vexx32
Copy link

vexx32 commented Oct 25, 2019

Yeah, F8 to a standard console just uses whatever VS Code's standard pasting functionality uses, it doesn't have a direct hook-in like the integrated terminal.

@gabrieljtaylor
Copy link
Author

With respect, I think the core issue is being overlooked with the focus being on the method of copy/paste and/or the VS Code terminal's standard behavior. The reality is that the behavior never happens when PSReadLine is not present, and only happens when PSReadLine is present. Regardless of what the method used to copy/paste is, regardless of the VS Code terminal's standard behavior, the erroneous behavior is only occurring when PSReadLine is present, suggesting that the issue has something to do with the way PSReadLine is modifying or interacting with the terminal.

If there is a setting to change somewhere that would fix this, I would welcome learning of it. I can tell you that I've had the problem for months off and on and I have scoured the internet prior to opening this issue looking for some setting I could change to fix it, or some other person having the same issue, and I've found neither. This suggests that whatever the issue is, it may be unique to "me", but I've been able to replicate it on multiple Windows computers, both ones that have been around for a while and brand new installs with no settings or anything else moved over.

I honestly have no clue what is causing the issue. I opened the issue in hopes that someone who knows more about how PSReadLine works under the hood may be able to have some insight into what interaction might generate these inconsistent results (and they are truly inconsistent - I can F8 or paste the same code multiple times in a row and it will sometimes work as desired and sometimes generate errors, with nothing done in between, not even re-copying or re-selecting the text, which makes no sense).

If there are any files I can share, or other logs you want me to collect, or test code to run, or anything at all, I am more than willing to do what you ask and fuel an investigation. I may have found a rare, hard-to-reproduce issue, but signs suggest it is an issue nonetheless, and my goal is simply to try and solve it and improve the overall quality of the module. :)

@rkeithhill
Copy link
Contributor

rkeithhill commented Oct 26, 2019

I can't repro this at all in a stand-alone PowerShell Core console or in Windows Terminal Strike that. I've had so little luck with right-click paste that I reflexively use ctrl+v which works reliably everywhere except in the VSCode terminal.

So yeah, right-click paste in a stand-alone PS console or Windows Terminal repro's easily as does Run Selected Text in VSCode in both the VSCode regular and the PoweShell Integrated Console terminals. For the latter, this only repros when you're not using the PowerShell extension's impl of F8 which you can do by putting the text in a plaintext file. And I can confirm that if you remove PSReadline it works just fine as shown here:

image

My issues are worse with PSReadLine because I have keyhandlers for auto-closing {, [ and (. And those handlers can't tell when a human is typing versus a right-click paste so it winds up modifying the pasted stream of text.

FYI unless you are running the PowerShell-Preview extension, the PowerShell Integrated Console does not load PSReadLine but it still fails to handle the pasted text (again only when VSCode doesn't know the file is a PS script).

@msftrncs
Copy link
Collaborator

This is interesting .. as I don't actually remember being able to do this BEFORE PSReadLine … But it appears that this has always worked prior to PSReadLine. I just tested on a stock Windows 7 SP1 Windows PowerShell 3.0 via remote desktop and it worked perfectly as well. (Other than non-PSReadLine multiline mode is quite difficult to use, or it doesn't behave as intuitively.)

@SteveL-MSFT or @lzybkr, any input on this? It might seem this regression wasn't noticed when PSReadLine became included with the distribution.

@gabrieljtaylor
Copy link
Author

FYI unless you are running the PowerShell-Preview extension, the PowerShell Integrated Console does not load PSReadLine but it still fails to handle the pasted text (again only when VSCode doesn't know the file is a PS script).

In my case, this happens despite VSCode knowing that the file is a PS script, at least in PowerShell terminals that aren't the PS Integrated Terminal. For the PS Integrated Terminal, neither right-click nor Ctrl+V paste works, and the PS extension's F8 / Run Selection command sometimes works and sometimes doesn't. The inconsistency is possibly the most frustrating part of the issue.

(I am running the PowerShell-Preview extension, FYI)

@SteveL-MSFT SteveL-MSFT self-assigned this Oct 28, 2019
@SteveL-MSFT
Copy link
Member

I'll look into this

@lzybkr
Copy link
Member

lzybkr commented Oct 28, 2019

I consider this issue a duplicate of #579, but I believe this is the first complaint for this specific symptom.

If the parser ever reports an "incomplete parse" - that was a signal to the host (e.g. console host) to keep reading more input.

Without PSReadLine, after seeing an incomplete parse, you must enter a single blank line before the input will be accepted.

PSReadLine doesn't bother waiting for that extra blank line. There are multiple reasons for this:

  • With proper multi-line editing, it's annoying.
  • With a proper paste, it's not really necessary.
  • The old logic in this area had some annoying flaws where it was near impossible to break out and start a new command line.

@SteveL-MSFT
Copy link
Member

So, stepping through the debugger it seems the problem is:

Ctrl+V is being handled by the Terminal, not PSRL (Paste() doesn't get called). So each character comes in one at a time. When it hits a newline, it's a CTRL+ENTER which is correct, but it seems that the characters is \r\n so \r is processed as Enter and accepts the line, then the next char is \n with CTRL modifier which would have produced the right behavior, but \r was already processed. Not sure what to do about this other than treating \r\n as one key on Windows.

@lzybkr
Copy link
Member

lzybkr commented Oct 28, 2019

@SteveL-MSFT - then you can consider this a definite duplicate, the \r\n issue is called out explicitly in #579.

@SteveL-MSFT
Copy link
Member

Dupe of #579

@SteveL-MSFT SteveL-MSFT removed their assignment Oct 28, 2019
@SteveL-MSFT SteveL-MSFT added the Resolution-Duplicate There's another issue on the tracker that's pretty much the same thing. label Oct 28, 2019
@msftrncs
Copy link
Collaborator

So that something is clear to all, pasting in VS Code in any format, or using Right-Click in ConHost or Windows Terminal, or using any other terminal's pasting function results in the pasted data being 'typed' in. If you take the example above and type it in by hand, you get exactly the same result. If the sample above was spaced out (blank lines inserted before the ELSEs, then it would always fail with PSReadline removed.

OTBS is preferred because of this, but obviously its not mandatory.

However, to state an option, I am not sure that just because PSReadLine provides a better editing experience, that is not reason to not behave in the same way as PowerShell did natively. PSReadLine's better editing experience actually would compliment PowerShell's native behavior.

I tried performing a similar operation on a Ubuntu 18.04 VM using PS 6.2.3 in the Ubuntu terminal, with and without PSReadLine 2.0.0-beta5. While the experience with PSReadLine was faster, the command was not accepted correctly because of the lack of a 'incomplete parse" condition at the ending brace of the IF statement block.

@SeeminglyScience
Copy link
Contributor

FYI, the issue with VSCode and ctrl + v can be fixed by adding this to your keybindings.json:

{
    "key": "ctrl+v",
    "command": "-workbench.action.terminal.paste",
    "when": "terminalFocus"
},

That removes the default ctrl + v action mapped by VSCode and resumes sending only the raw input.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution-Duplicate There's another issue on the tracker that's pretty much the same thing.
Projects
None yet
Development

No branches or pull requests

7 participants