Double angle bracket mode - powershell

I'm using PowerShell 7.1.3 and have noticed a strange behavior when entering a single quote to my prompt:
PS: '
>>
>>
The prompt is styled with >> and no matter what I type, nothing gets executed (or that's how it looks). I was wondering:
Is this activated by entering ' on the shell, or is this a side effect?
Is this mode called somehow?
Is this mode useful for a specific case?

Is this activated by entering ' on the shell, or is this a side effect?
It's an intentional side-effect of entering an unmatched ' as a command, yes.
It's technically not PowerShell itself, but rather the PSReadLine module (which ships with PowerShell 7 and is enabled by default).
PSReadLine provides a number of command line editing improvements - including syntax highlighting, customizable tab- and menu-completion, and multi-line editing - and it works by continously feeding your (partial) input to PowerShell's parser, and then uses the results returned by the parser to provide the correct syntax highlighting etc.
So when you press [Enter] after having typed a single ', PSReadLine sends your input to the parser like this:
# Parse the input script the same way PSReadLine would
$ParserErrors = #()
$AST = [System.Management.Automation.Language.Parser]::ParseInput("'", [ref]$null, [ref]$ParserErrors)
# Let's inspect any parser errors
$ParserErrors
If you run this in PowerShell 7.1.3, you'll see the following errors were reported:
Extent ErrorId Message IncompleteInput
------ ------- ------- ---------------
' TerminatorExpectedAtEndOfString The string is missing the terminator: '. True
Notice the last property of the error, IsInputIncomplete - PSReadLine sees that what you've typed in the prompt is incomplete - and it therefore assumes you're not done writing your command and continues the prompt on the next line for you.
[...] no matter what I type, nothing gets executed
That's not quite true - if you enter something that completes the input (eg. makes it valid PowerShell again), it'll let you submit it - in your case that would be by typing a closing ':
Is this mode called somehow?
No idea, I tend to think of >> as a "prompt continuation indicator", but it's not really a distinct mode per se.
Is this mode useful for a specific case?
Well, as shown above it prevents you from trying to execute syntactically invalid or incomplete code, that's pretty useful in itself I think.
The overall ability to do multi-line editing at the prompt is, in my personal opinion, one of the biggest strengths of PowerShell - you can start prototyping small functions and compose quite complex pipelines without having to switch back and forth between an editor.
As beatcracker mentions, you can also get prompt continuation (at least in the default Windows Console Host) by pressing Shift+Enter - this works regardless of whether the existing input is incomplete or not.
You can basically write and edit a whole script at the prompt if you wanted to.

Related

Powershell equivalent of MATLAB keyboard() command for debugging?

MATLAB has a feature to allow users to introduce a command in the script/function called keyboard and have the code stop there with a console/command prompt that gives direct access to the interpreter and the variable space. MATLAB keyboard() command docs
Is there something similar in Powershell? I don't want to deal with Powershell ISE as I don't like it's syntax highlighting (doesn't highlight all occurrences of selected phrase like Notepad++ does) and the macros is a lot weaker than what the plain Powershell console itself (like lacking F8 for recalling).
Stepping with a debugger is not quite as useful when you need to explore complex object structures and try a few things out with the current variable states, instead of just reading what the variables and values are in a docked window. It's much easier to work with the state of mind of the interpreted language at any point by interacting with it instead of ploughing through stack and trace information.
In both Powershell ISE and VSCode, you can read or update the same variables in your session from the terminal window at the bottom, even during debugging.

How to hide "PS C:\>" in powershell?

So you know how in powershell if you enter a command infront of it there will always be "PS (directory)>".
I know its possible in cmd with a simple command but how do you do this in powershell?
so:
Hide the text(PS C:>) thats infront of commands
If possible through a command
If any of you know the fix please let me know.
If i find it first i will self anwser.
(I later found this dup):Windows PowerShell: changing the command prompt
Just like Calculuswhiz mentioned, the following should work:
Function Prompt {" "}
Simply change it by adding anything else inside the double quotes.
Abraham Zinala's helpful answer shows that it is the prompt function - described in the about_Prompts conceptual help topic - that determines the string that PowerShell prints in interactive sessions when prompting the user for commands.
As Calculuswhiz notes, outputting the empty string ('') is not an option for not printing a prompt string at all, because PowerShell then defaults to PS>.
Printing a single space is one way to work around the problem, but that space does print. To prevent that, Dabombber proposes workarounds in a comment on Abraham's question, but the simplest solution as of Windows 10 is:
function prompt { "`0" } # Fully HIDES the prompt string.
"`0" outputs a NUL (null character), which effectively hides the prompt string, without side effects, including in Windows Terminal and ConEmu.[1]
On Windows 7, the NUL prints as a space, in which case Dabombber's alternative helps:
# A space followed by a backspace char. in effect amounts to the empty string.
function prompt { " `b" }
Add this function to your $PROFILE file to hide the prompt string in all future sessions.
[1] Verified on version v20.11.24.0. Dabombber mentions that ConEmu prints NUL characters as a space, but, given that ConEmu is conhost.exe-based, just like regular console windows, that applies only up to Windows 7.

PowerShell command prompt has sometimes >>>> instead of one

How come sometimes there are >>>> istead of simply >?
More than one > in the (default[1]) prompt string shows up in two scenarios:
Typing an incomplete command and pressing Enter, in which case >> at the start of the following indicates that more input is needed to complete the command; however, this string is always >>, i.e. fixed at 2 > chars; while this looks like a nested prompt (see below), it isn't.
Inside a nested prompt, where the number of > chars. indicates the nesting depth, as reflected in the automatic $NestedPromptLevel variable: a single > indicates the non-nested, top-level prompt at depth 0, >> indicates a nested prompt of depth 1, and so on. That said, a depth greater than 1 is unusual in practice.
A nested prompt is a temporary, interactive sub-shell that has full access to its parent shell's state and is terminated by submitting exit, at which point any ongoing script or function execution that was interrupted (suspended) by the nested prompt resumes.
The primary use of nested prompts is in debugging and troubleshooting, such as in the context of tracking down errors:
A nested prompt is automatically and invariably entered when a Wait-Debugger statement is executed.
Otherwise, entering a nested prompt is offered as the [S] Suspend choice of an interactive menu, in the following scenarios:
A command with a declared confirmation impact higher or equal to the current $ConfirmPreference value is executed, in which confirmation of the intent to execute the command is prompted for. For cmdlets and advanced functions/scripts you can trigger this confirmation prompt on demand with the
-Confirm switch.
One of the $*Preference preference variables is set to 'Inquire', and something is written to the relevant output stream. Alternatively, on a per-command basis for cmdlets and advanced function/scripts, you can use
-*Action Inquire common parameters, though note that the verbose and debug streams only have Boolean parameters, -Verbose and -Debug[2]; for instance:
If $DebugPreference is 'Inquire', execution of any Write-Debug statement triggers the interactive menu.
If $ErrorActionPreference is 'Inquire', any error that occurs triggers the interactive menu, and choosing [S] Suspend to enter a nested prompt allows investigation of the error.
From user code, you can enter a nested prompt on demand with $host.EnterNestedPrompt() (which doesn't make sense interactively).
[1] Given that you can define a custom prompt function to determine the prompt string, you could hypothetically define it with multiple > chars. by default, though that is not advisable; e.g.: function prompt { "$PWD>>> " }. To see the current body of the prompt function, submit $function:prompt
[2] In Windows PowerShell, passing -Debug to a cmdlet or advanced function/script implies 'Inquire', but this was changed in PowerShell [Core] v6+ to 'Continue' (only print the debug message, do not put up the menu) in order to be less disruptive.

How to type a tab (indent) in comments in PowerShell ISE?

This is weird.
I know tab is for command completion in the PowerShell ISE and fine so. But, it also messes up the editing pane.
Do this:
File > New (Untitled1.ps1 opens)
Press tab (all fine, you get an indent)
type enter, # (comment) and press tab after it
expected: one would get indentation after the hash
actual: one gets the hash replaced by $PSVersionTable or whatever the command prompt has in its history! (tab and Shift-tab circle through those)
Does this mean no-one uses tabs within comments in PowerShell scripts, or that no-one uses comments in PowerShell scripts?
Can I turn off this behavior anywhere?
Also, the behavior seems to be inconsistent. If I e.g. type ##, sometimes tab does not do the completion (it does not enter a tab either).
Can others reproduce this?
System:
Windows 8.1 Pro
PowerShell ISE
To answer the main question, you can enter Alt+09 (using numeric keypad) to enter <Tab>.
For the behavior described, I see this as expected behavior. You can get history completion by typing # and part of a previous command then pressing Tab repeatedly will cycle backwards through matching history. Typing # alone will match all history starting with the last command.
Does this mean no-one uses tabs within comments in PowerShell scripts?
Anecdotal, but I've never used tabs in a single line comment, but I do often use tabs within multiline comments which are bracketed by <# and #>. E.g.
<#
Functions
Get-Foo
Get-Bar
Variables
$Foo
$Bar
#>
Function Get-Foo { ...
With multiline comments, the auto-completion will not be an issue.
, or that no-one uses comments in PowerShell scripts?
I don't know why this would be implied by the behavior; I always use a single space to start a line comment.
I find this helpful when developing a script as I often try expressions in the command pane if I'm unsure of the behavior, then add the expression to the script if it works.
So, my workflow would be:
Ctrl-D to go to the Command Pane
Type a command
If the command did what I wanted, Ctrl-I to go to the Script Pane
Type #<Tab>, and the line is added to the script.

How to make the input not automatically execute when I paste in PowerShell

I have a feeling that this is a very simple fix, but whenever I try to paste into PowerShell using right-click, it automatically executes whatever it is I am trying to paste. The function is finding a computer name based on an input using AD and then copies the computer name to use in other functions. Here is the code for only the part that does the copying:
$strComputer = $output.Name
$strComputer | clip | Out-Null
So when I right-click to paste, it executes whatever $strComputer equals and obviously throws an error. Thanks!
The problem with pasting something into PowerShell (and clip.exe is very good example) is the fact, that any newline (and clip.exe used like that will add newline at the end) will trigger same reaction that you pressing enter would.
There are at least two ways around it:
paste without newlines (e.g. use [System.Windows.Clipboard]::SetText($output.Name))
if you are on v3 - use PSReadLine module and CTRL+V
For the first one - be sure to run Add-Type -AssemblyName PresentationCore first - this assembly is loaded by default only in PowerShell ISE. If you are on v3+ though I would really recommend to give PSReadLine a try.
I've found an easy solution, that doesn't require any Powershell modifications.
Steps:
Type if ($true) { into the terminal.
Paste in the code-block. Because you started an if-block, but didn't provide an end-bracket for it, Powershell interprets the code-block as incomplete, and so awaits the end-bracket before running anything.
Now you can use the arrow keys to edit the code block however you want.
When you're done with your edits, add the missing } to the very end, then press enter to execute it.
Alternatively you can use the ISE, where you can paste into the Script Pane (the top half), and edit until it appears as desired, and run when you want to.