I think the template might need to be updated:
PS version: 6.0.1
PSReadline version: 2.0.0-beta1
dir : Cannot find path '/System32/cmd.exe' because it does not exist.
At line:12 char:17
+ "os: $((dir $env:SystemRoot\System32\cmd.exe).VersionInfo.Fil ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (/System32/cmd.exe:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
os:
PS file version:
That said, here are the answers:
PS version: 6.0.1
PSReadline version: 2.0.0-beta1
OS: macOS High Sierra
PS file version: `(dir $pshome\pwsh).VersionInfo.FileVersion` yielded nothing
on macOS with the PSRL 2.0.0-beta1:
> gci #then hit SHIFT+ENTER
gci is executed, rather than a new line being generated.
If there's an unclosed brace, however, AddLine works. Ex:
> & { #now hit SHIFT+ENTER or just ENTER
a new line appears - it doesn't execute the code.
> & {
>>
Thanks, I updated the template for the variable name change to $IsMacOS
.
I don't think it's possible to use Shift+Enter
as a key binding on non-Windows machines, the shift state is not available to applications that use the normal tty routines for reading the keyboard. You can see this by using showkey -a
, it prints the same thing for Enter
and Shift+Enter
(this is on Linux, not sure about a Mac, I don't have access to one.)
We should just remove the binding or use another on non-Windows if there is one in common use.
@lzybkr I'm not sure if I'm doing something wrong here... As a test I tried setting this:
Set-PSReadLineKeyHandler -Key Ctrl+\ -Function AddLine
However, when I type Ctrl+\
after running that, I get this:
/Users/tylerleonhardt> asdf^\^\^\^\^\^\^\^\^\
Am I doing something wrong?
No, that looks like a bug.
There were a couple instances of where on macOS Alt+ something, gives you a special character like:
Alt+=
gives you â‰
. Alt+k
gives you Ëš
... etc and so Alt+=
wouldn't trigger PossibleCompletions like it should. I also tried this with Alt+?
which should run WhatIsKey but instead I get: ÷
.
I'm not sure if this related to the issue I just mentioned but I hope it helps.
I'll need help on stuff like that - it looks like it differs from Linux and I don't have access to a Mac.
@tylerl0706:
on macOS Alt+ something, gives you a special character
This is a system-wide feature for generating special characters on macOS, and by default it also applies to the default terminal, Terminal.app
(and also iTerm 2
, its popular third-party replacement).
However, you can opt out of this behavior, in which case the terminal translates Alt+{char} _chords_ into Esc, {char} _sequences_.
See https://github.com/lzybkr/PSReadLine/issues/529#issuecomment-380605610 for how to opt out.
@mklement0 that worked like a charm.
I have it set to Esc+
and was able to do:
Set-PSReadLineKeyHandler -Key Alt+l -Function AddLine
Note:
Set-PSReadLineKeyHandler -Key Alt+\ -Function AddLine
has some strange behavior along with:
Set-PSReadLineKeyHandler -Key Ctrl+\ -Function AddLine
as I mentioned above.
I wonder if there's a problem with using \
Here's the _list of usable chords_ with Set-PSReadlineHandler
on Unix-like platforms; compiled as of PowerShell Core 7.0.0-rc.1:
[Console]
API - see bottom section; @lzybkr has started the conversation about fixing the latter in this CoreFX issue.Control-based chords:
Chord | Comment
------ | ------
Control-a
|
Control-b
Control-c
| Caveat: handler not effective while a command is running
Control-d
| Caveat: users may expect this to end interactive input
Control-e
Control-f
Control-g
Control-k
Control-l
Control-n
Control-o
Control-p
Control-q
Control-r
Control-s
Control-t
Control-u
Control-v
Control-w
Control-x
Control-y
Control-z
| Caveat: if running via bash
, preempted by the latter's send-to-background feature
Note:
Alt
to these cords.Shift
- using Shift is effectively _ignored_ (behaves as if it hadn't been pressed).Alt-based chords:
Chord | Comment
------ | ------
Alt-a
... Alt-z
| English letters only
Alt-A
... Alt-Z
| Shift variations - do _not_ use Alt-Shift-a
(Alt-Shift-A
would be redundant)
Alt-1
... Alt-9
| Caveat: Shift variations _not_ supported; they trigger even if you don't press Shift, and don't trigger when you do.
Alt-/
| Curiously, this particular symbol seems to work, unlike others; no Shift support
Note:
Control
limits you to the chords available for Control-based chords./
).Shift-_only_-based chords:
Except for:
Alt
and Control
listed aboveyou _cannot_ define Shift
-based key handlers on Unix.
Notably, handlers such as Shift-Enter
or Shift-Backspace
are _not_ supported.
The _fundamental_ restrictions - which come from most Unix-like OSs running xterm
-emulation terminal programs are:
Control-based chords are in effect limited to a _subset_ of the 33 well-defined chords of _caret notation_ - plus a few _effective_ (but presumable _accidental_) _aliases_ (see bottom); the ^
symbol is known as the _caret_ and represents the Control key; for instance, ^A
represents the chord Control+A (strictly speaking, it is the _uppercase_ A
, but at least for letters it doesn't matter whether Shift is held down or not):
(0x0) NUL
/ ^A
through (0x1f) US
/ ^_
, plus (0x7F) DEL
/ ^?
) and programs running inside that terminal see only the resulting control character. From a terminal's perspective, there are _no_ Alt-based chords _at all_, but most modern terminal programs _translate_ Alt+{char}-based _chords_ (with some terminals on an opt-in basis, as on macOS) into Esc, {char} _sequences_, and programs running inside that terminal see only the resulting _sequence_.
That's why, in the bash
world, for instance, readline
definitions are expressed in terms of the latter.
Generally, only _characters_ are reported, not _key states_, so that there's no separate information about whether a given modifier key was (also) held down, notably not Shift.
Additionally, a given terminal program itself may have key bindings for Control-based and/or Alt-based chords, which may _preempt_ attempts by programs running inside these terminals to bind them.
_On top of that_ there are the shortcomings in CoreFX's [Console]::ReadKey()
implementation on Unix-like platforms, which affect PSReadLine too:
Note: I'm using _lowercase_ letters in the chord representations below to indicate chords _not_ involving the Shift key.
On Unix-like platforms, instead of letting programs see the _translation_ of key chords the same way as described above - which may be a single ASCII control character or an Esc, {char} _sequence_ - CoreFX retranslates that into a _chord_, as you would see it on Windows, but only for _some_ chords:
Control-based chords that translate into control characters that have _dedicated keys_ are reflected as such in the .Key
property (but the .KeyChar
property also contains the corresponding control character):
.Key
property value, not the actual _chord keys_ (e.g., Set-PSReadLineHandler 'Escape' ...
, not Set-PSReadLineHandler 'Control-[' ...
)^I
, which is control char. HT
, corresponds to the Tab key^H
, which is control char. BS
, corresponds to the Backspace key.Control+[ a.k.a ^[
, which is control char. ESC
, corresponds to the Escape key.
Control+j a.k.a ^J
, which is control char. LF
(0xA
) is _mistakenly conflated_ with Control+m a.k.a ^M
, which is control char. CR
: both result in the .KeyChar
property containing `r
(i.e., CR
) and .Key
containing Enter
:
^J
should have .KeyChar
value (`n
), its .Key
property should be J
, and its .Modifier
property should be Control
.Control-based chords that do _not_ work:
Control+z _works_ in principle, but may be preempted by bash
, if pwsh
happened to have been launched from it; note that Control+z has special meaning in traditional _shells_ (not the terminal emulators themselves): in cmd.exe
, it signals EOF during interactive input (copy con ...
); in bash
, it suspends the currently executing program and sends it to the background.
[Console]::ReadKey()
ignores the chord, but PSReadLine does see it.The remaining punctuation-based chords do _not_ work, either:
@
\
]
0x1e
, which prints as ^^
; you can't define a PSReadLine key handler for that._
[Console]::ReadKey()
passes the control character correctly in the .KeyChar
property (except for ^@
, where it is 0
), but fails to populate the .Key
and .Modifier
properties (both 0
, except for ^?
, where it is Backspace
) Redefining Control+c (probably not a good idea) isn't effective while a command is running; you get the default cancel-the-running-operation functionality then (if run [console]::TreatControlCAsInput = $true
first, you lose the cancel-the-running-operation functionality altogether). In other words: you can only redefine Control+c for command-line editing.
CoreFX tries to translate Esc, {char} _sequences_ , as reported by the terminal emulator, back into Alt+{char}-based chords, but not _consistently_:
_(English) letter and digit-based_ Alt-based chords, including uppercase variants, are correctly translated, and behave as on Windows.
By contrast, symbol-/punctuation-based Alt chords (e.g., Alt+') do appear to arrive as their raw Esc, {char} _sequences_, which [Console]::ReadKey()
and therefore PSReadLine cannot handle: [Console]::ReadKey()
only reports the Esc keypress, not the following {char}
.
As stated, Unix terminals report _characters_, not _key states_, so there is no separate information about the state of the Shift key.
CoreFx _infers_ that Shift was pressed _for uppercase letters_, and puts the value Shift
in the .Modifiers
property of the Sytem.ConsoleInfo
instance returned, but in _no other cases_.
Therefore, defining handlers for chords such as Shift-Enter
is fundamentally unsupported - they never trigger on Unix.
To test if chords work on Unix-like platforms, run something like the following from PowerShell:
# Alt-
'a'..'z' + '1'..'9' | % {
Set-PSReadLineKeyHandler "alt-$_" ([scriptblock]::Create("Write-Host -NoNewline 'alt-$_!'"))
}
# Ctrl- (not all of them will work)
'a'..'z' | % {
Set-PSReadLineKeyHandler "ctrl-$_" ([scriptblock]::Create("Write-Host -NoNewline 'ctrl-$_!'"))
}
Thank you so much for all the awesome information!
We can probably close this issue in favor of the issue in CoreFX and the known limitations.
Thanks again for the thorough explanation!
@tylerl0706: Glad it was helpful; feel free to close this issue (depending on what will and won't get fixed, parts of my previous post will hopefully at least make it into PSReadLine's read-me / Get-Help about_PSReadLine
).
Most helpful comment
Here's the _list of usable chords_ with
Set-PSReadlineHandler
on Unix-like platforms; compiled as of PowerShell Core 7.0.0-rc.1:[Console]
API - see bottom section; @lzybkr has started the conversation about fixing the latter in this CoreFX issue.Control-based chords:
Chord | Comment
------ | ------
Control-a
|Control-b
Control-c
| Caveat: handler not effective while a command is runningControl-d
| Caveat: users may expect this to end interactive inputControl-e
Control-f
Control-g
Control-k
Control-l
Control-n
Control-o
Control-p
Control-q
Control-r
Control-s
Control-t
Control-u
Control-v
Control-w
Control-x
Control-y
Control-z
| Caveat: if running viabash
, preempted by the latter's send-to-background featureNote:
Alt
to these cords.Shift
- using Shift is effectively _ignored_ (behaves as if it hadn't been pressed).Alt-based chords:
Chord | Comment
------ | ------
Alt-a
...Alt-z
| English letters onlyAlt-A
...Alt-Z
| Shift variations - do _not_ useAlt-Shift-a
(Alt-Shift-A
would be redundant)Alt-1
...Alt-9
| Caveat: Shift variations _not_ supported; they trigger even if you don't press Shift, and don't trigger when you do.Alt-/
| Curiously, this particular symbol seems to work, unlike others; no Shift supportNote:
Control
limits you to the chords available for Control-based chords.* Note the absence of _punctuation_-based chords (except for
/
).Shift-_only_-based chords:
Except for:
Alt
andControl
listed aboveyou _cannot_ define
Shift
-based key handlers on Unix.Notably, handlers such as
Shift-Enter
orShift-Backspace
are _not_ supported.Background Information
The _fundamental_ restrictions - which come from most Unix-like OSs running
xterm
-emulation terminal programs are:Control-based chords are in effect limited to a _subset_ of the 33 well-defined chords of _caret notation_ - plus a few _effective_ (but presumable _accidental_) _aliases_ (see bottom); the
^
symbol is known as the _caret_ and represents the Control key; for instance,^A
represents the chord Control+A (strictly speaking, it is the _uppercase_A
, but at least for letters it doesn't matter whether Shift is held down or not):(0x0) NUL
/^A
through(0x1f) US
/^_
, plus(0x7F) DEL
/^?
) and programs running inside that terminal see only the resulting control character.From a terminal's perspective, there are _no_ Alt-based chords _at all_, but most modern terminal programs _translate_ Alt+{char}-based _chords_ (with some terminals on an opt-in basis, as on macOS) into Esc, {char} _sequences_, and programs running inside that terminal see only the resulting _sequence_.
That's why, in the
bash
world, for instance,readline
definitions are expressed in terms of the latter.Generally, only _characters_ are reported, not _key states_, so that there's no separate information about whether a given modifier key was (also) held down, notably not Shift.
Additionally, a given terminal program itself may have key bindings for Control-based and/or Alt-based chords, which may _preempt_ attempts by programs running inside these terminals to bind them.
_On top of that_ there are the shortcomings in CoreFX's
[Console]::ReadKey()
implementation on Unix-like platforms, which affect PSReadLine too:Note: I'm using _lowercase_ letters in the chord representations below to indicate chords _not_ involving the Shift key.
On Unix-like platforms, instead of letting programs see the _translation_ of key chords the same way as described above - which may be a single ASCII control character or an Esc, {char} _sequence_ - CoreFX retranslates that into a _chord_, as you would see it on Windows, but only for _some_ chords:
Control-based chords
Control-based chords that translate into control characters that have _dedicated keys_ are reflected as such in the
.Key
property (but the.KeyChar
property also contains the corresponding control character):.Key
property value, not the actual _chord keys_ (e.g.,Set-PSReadLineHandler 'Escape' ...
, notSet-PSReadLineHandler 'Control-[' ...
)^I
, which is control char.HT
, corresponds to the Tab key^H
, which is control char.BS
, corresponds to the Backspace key.Control+[ a.k.a
^[
, which is control char.ESC
, corresponds to the Escape key.Control+j a.k.a
^J
, which is control char.LF
(0xA
) is _mistakenly conflated_ with Control+m a.k.a^M
, which is control char.CR
: both result in the.KeyChar
property containing`r
(i.e.,CR
) and.Key
containingEnter
:^J
should have.KeyChar
value (`n
), its.Key
property should beJ
, and its.Modifier
property should beControl
.Control-based chords that do _not_ work:
Control+z _works_ in principle, but may be preempted by
bash
, ifpwsh
happened to have been launched from it; note that Control+z has special meaning in traditional _shells_ (not the terminal emulators themselves): incmd.exe
, it signals EOF during interactive input (copy con ...
); inbash
, it suspends the currently executing program and sends it to the background.[Console]::ReadKey()
ignores the chord, but PSReadLine does see it.The remaining punctuation-based chords do _not_ work, either:
@
\
]
0x1e
, which prints as^^
; you can't define a PSReadLine key handler for that._
[Console]::ReadKey()
passes the control character correctly in the.KeyChar
property (except for^@
, where it is0
), but fails to populate the.Key
and.Modifier
properties (both0
, except for^?
, where it isBackspace
)Redefining Control+c (probably not a good idea) isn't effective while a command is running; you get the default cancel-the-running-operation functionality then (if run
[console]::TreatControlCAsInput = $true
first, you lose the cancel-the-running-operation functionality altogether). In other words: you can only redefine Control+c for command-line editing.Alt-based chords
CoreFX tries to translate Esc, {char} _sequences_ , as reported by the terminal emulator, back into Alt+{char}-based chords, but not _consistently_:
_(English) letter and digit-based_ Alt-based chords, including uppercase variants, are correctly translated, and behave as on Windows.
By contrast, symbol-/punctuation-based Alt chords (e.g., Alt+') do appear to arrive as their raw Esc, {char} _sequences_, which
[Console]::ReadKey()
and therefore PSReadLine cannot handle:[Console]::ReadKey()
only reports the Esc keypress, not the following{char}
.Shift-_only_-based chords:
As stated, Unix terminals report _characters_, not _key states_, so there is no separate information about the state of the Shift key.
CoreFx _infers_ that Shift was pressed _for uppercase letters_, and puts the value
Shift
in the.Modifiers
property of theSytem.ConsoleInfo
instance returned, but in _no other cases_.Therefore, defining handlers for chords such as
Shift-Enter
is fundamentally unsupported - they never trigger on Unix.To test if chords work on Unix-like platforms, run something like the following from PowerShell: