PSReadLine Error with Uncuddled 'Else'

Created on 25 Oct 2019  Â·  18Comments  Â·  Source: PowerShell/PSReadLine

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

Resolution-Duplicate

Most helpful comment

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.

All 18 comments

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.

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.

I just performed a single test each of the right-click vs. Ctrl+V paste
options in several places and here's what I found:

  • In a PowerShell 6.2 shell, Ctrl+V works and pastes correctly, while
    right-click does not.
  • In a PowerShell 5.1 shell, both fail equally
  • In a PowerShell 5.1 terminal in VS Code, both fail equally
  • In a PowerShell 6.2 terminal in VS Code, both fail equally

Also, even if changing the method of paste fixed the issue (which it
doesn't appear to do), the Run Selection (F8) command in VS Code still
produces the issue, which is a problem.

Additionally, given that the issue only occurs when PSReadLine is imported
and doesn't occur when PSReadLine has been removed suggests the issue isn't
a problem with the terminal implementation, so much as how PSReadLine is
interacting with the terminal.

On Fri, Oct 25, 2019, 8:22 AM vexx32 notifications@github.com wrote:

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.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/PowerShell/PSReadLine/issues/1127?email_source=notifications&email_token=AB77O3PAYVWMGUR62KHMIWTQQLXIXA5CNFSM4JFCQQEKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECIKT5I#issuecomment-546351605,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AB77O3J3JXBZA4Y3TEZW7Y3QQLXIXANCNFSM4JFCQQEA
.

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.

@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

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.

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.

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. :)

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).

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.

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)

I'll look into this

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.

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.

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

Dupe of #579

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.

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.

Was this page helpful?
0 / 5 - 0 ratings