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

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.

Related

how to get tab autocompletion to echo all possible options like bash?

In bash there's a nice feature that when a string is partially completed (like a path) and we use tab for autocompletion, we get ALL the possible options echoed out at once to aid the next character we might want to type.
In PowerShell, it just cycles through one option at a time, so you are relatively blind where numerous possibilities are involved.
Is equivalent behaviour possible in PowerShell?
Use Set-PSReadLineKeyHandler to redefine what happens when you press Tab as follows:
Set-PSReadLineKeyHandler Tab MenuComplete
Note that you'll have to add this command to your $PROFILE file in order to make it take effect in future sessions too.
The behavior of the MenuComplete function is as follows:
If there is no possible completion, no action is taken.
If there is only one possible completion, it is performed instantly, in-line.
If there are two or more possible completions, an interactive menu of the possible completions is shown below the input line:[1]
Use Tab or the arrow keys to cycle through the completions and press Enter to select one, which completes what was typed based on that selection and closes the menu.
Alternatively, continue typing, which prefix-matches against the parameter names and shrinks the menu dynamically (delete characters to expand it again).
Note that the highlighted menu item also shows that parameter's data type below the menu.
Once a parameter name has been completed, if you want data-type information plus a verbal description of that parameter, you can use the ShowParameterHelp function, available in PowerShell (Core) 7.2+, which is bound to Alt+h by default.
Additional PSReadLine tips:
To see a list of available functions:
Consult the about_PSReadLine_Functions help topic; if it isn't available locally (with Get-Help about_PSReadLine_Functions), run Update-Help -Module PSReadLine.
To list all functions grouped by functional category, using Get-PSReadLineKeyHandler:
Get-PSReadLineKeyHandler -Bound -Unbound
To see a flat list sorted by function name instead:
Get-PSReadLineKeyHandler -Bound -Unbound |
Sort-Object Function |
Select-Object Function, Key, Description
To check what key chord(s) a given function is currently bound to:
# This example looks for function names that contain the word "menu"
# Use -eq with a full function name, if known.
Get-PSReadLineKeyHandler | Where-Object Function -like *Menu*
To discover what function is currently bound to a given key chord:
Use the WhatIsKey function, which on Windows is bound to Alt+? by default; on Unix-like platforms, where the range of usable key chords is limited, there is no default binding, but you can define one as follows, using Alt+w as an example:
Set-PSReadLineKeyHandler Alt+w WhatIsKey
Pressing the key chord that WhatIsKey is bound to then prompts for pressing the key chord of interest, which, if it is bound, prints the bound function name and its description.
[1] The possible completions are not shown in alphabetical order; instead, the order appears to be based on the parameter definition order, combined with some additional logic: an exact match is listed first, alias names are listed after their original names, dynamic parameters are listed after static ones, and matching common parameter names come last.

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.

Double angle bracket mode

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.

Matlab - Path to the Current Script

Under any two years recent version of MATLAB, I am looking for the path of the current script being executed (ref.1, 2, 3, 4, 5),
Let's say, for a script through any of the following user procedures, in general, when a user runs a script:
The "Run", "Run and Advance", "Run Section" or "Run and Time" menu buttons,
The "Evaluate Selection" or "Evaluate Current Selection" contextual menus from the Editor,
The F9 or Ctrl+Enter keyboard shortcuts from the Editor.
User procedures that could not be accepted by the solution, because there would be no associated script, are:
Executing a piece of code directly in the command line,
The contextual or keyboard shortcuts for executing a code from a Matlab interface or windows outside the Editor -Document, Browser, Help.
User procedures out of the scope of the question related to functions, which could be solved easily through any of the following indicated solutions, is:
Calling the script as a function from the command line, from another script or from a function.
This is not for a function, which is trivially done through any of the following alternatives:
mfilename
mfilename('fullpath')
which(mfilename)
which('mfilename')
S = dbstack('-completenames');S(1).file
[folder,name,ext] = fileparts(which('object'))
And this is of course not the same that requesting the current folder through:
cd
pwd
edit I misunderstood the question initially...
So with hopefully a bit better understanding you could try and utilise:
matlab.desktop.editor.getActiveFilename
to get the current active file in the editor -> which should give the current script...
Note: this is an undocumented function which may change between releases -> it gives me the active filename in r2015b.

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.