Psreadline: Fish-like autocompletion

Created on 17 May 2018  Â·  61Comments  Â·  Source: PowerShell/PSReadLine

I tried to figure this out but couldn't find out. Is there a way to get autocompletion like in the fish shell?

fish-shell-demo

Basically what I am looking for is automatically searching the history on every keystroke, then showing a grey suggestion behind the cursor that can be accepted with → (if the cursor is at the end of the line).

We can get close with Set-PSReadLineKeyHandler -Key ArrowRight -Function HistorySearchBackward but it doesn't show the suggestion and it prevents moving the cursor to the right.

Issue-Enhancement

Most helpful comment

I'm working on a prototype of this, and here is the zip package if any of you want to try it (_any feedback would be very helpful!_).

PSReadLine.zip

Currently:

  • The only suggestion source is the PSReadLine history. The ultimate goal is to call into a prediction API in S.M.A that is powered by a prediction plugin.
  • Currently there is no way to configure the style that the suggestion text is rendered with, the default style (color only) works OK with a black background. (of course, more work is needed here)
  • VI mode - now the suggestion is disabled when switching to the command mode, and enabled when switching to insert mode.
  • So far, I haven't really focused on the VI/Emacs experience, so it could be pretty raw, and feedback is very welcome.

When using this PSReadLine, please add the following key binding to your profile:

Set-PSReadLineKeyHandler -Key "Ctrl+f" -Function ForwardWord
  • Pressing RightArrow at the end of current typing will accept the suggestion text
  • Pressing Ctrl+f at the end of current typing will accept a word from the suggestion text
  • Pressing Ctrl+z will get you back to where you were before accepting all or part of the suggestion

Important note: don't forget to unblock the zip file after you download it, otherwise you will face weird exceptions thrown from PowerShell.

predict

All 61 comments

This feature wasn't much of a priority with limited console support for VT sequences, but now Windows has real support for VT sequences, it makes sense to add this capability.

This type of experience is what we envisioned when we originally thought about "Machine Learning autocompletion". Since then, we dropped the ML part and thought about simply exposing an interface to enable this (https://github.com/PowerShell/PowerShell-RFC/pull/123/files) and just use local history.

@lzybkr is there any way this is currently already possible with PSReadLine customization? If not, what would be needed to make it possible? It would really improve my workflow so I would be willing to put some work in

@SteveL-MSFT So the plan would be to ship a function that handles the searching logic with Get-History so it is easy to opt-in to using that with PSReadLine?

PSReadLine doesn't use Get-History - it keeps it's own history.

Here are my thoughts on implementing this feature:

  • Add an option to Set-PSReadLineOption and document it
  • Add a configuration color for the autosuggestion text with a suitable default.
  • In SelfInsert, you will add smarts to find the autosuggestion. If you want command history, HistorySearchBackward has much of what you want, for other completions, GetCompletions is probably what you should use.
  • The autosuggestion text which is not accepted could be stored in a different StringBuilder. In ReallyRender, you would write this text out with the autosuggestion color.
  • In ForwardChar, if you are at the end of the buffer and there is autosuggestion text, add it to the buffer and clear the autosuggestion.
  • Probably add a binding to Ctrl+f in Windows mode to ForwardChar.
  • Add a new function AcceptFirstSuggestedWord and maybe AcceptFirstSuggestedShellWord, binding one or the other to Alt+RightArrow and Alt+f if the keys are not already bound (Emacs binds Alt+f by default, and hmm, maybe Alt+RightArrow won't work at all.) At any rate, the functions should be available so folks can get this functionality if they want as well.

As for relying on PowerShell for any new fancy suggestions - I'm not excited about that unless it means no api changes. Today a single build of PSReadLine works with any version of PowerShell > 5.0 and I'd like to keep it that way.

So, is it coming? :D

Yessss! Please. Looks like there's a whole lot of interest in this. I just saw similar functionality on a livestream and it was awesome!

https://i.vgy.me/PAn45j.mp4

I'm working on a prototype of this, and here is the zip package if any of you want to try it (_any feedback would be very helpful!_).

PSReadLine.zip

Currently:

  • The only suggestion source is the PSReadLine history. The ultimate goal is to call into a prediction API in S.M.A that is powered by a prediction plugin.
  • Currently there is no way to configure the style that the suggestion text is rendered with, the default style (color only) works OK with a black background. (of course, more work is needed here)
  • VI mode - now the suggestion is disabled when switching to the command mode, and enabled when switching to insert mode.
  • So far, I haven't really focused on the VI/Emacs experience, so it could be pretty raw, and feedback is very welcome.

When using this PSReadLine, please add the following key binding to your profile:

Set-PSReadLineKeyHandler -Key "Ctrl+f" -Function ForwardWord
  • Pressing RightArrow at the end of current typing will accept the suggestion text
  • Pressing Ctrl+f at the end of current typing will accept a word from the suggestion text
  • Pressing Ctrl+z will get you back to where you were before accepting all or part of the suggestion

Important note: don't forget to unblock the zip file after you download it, otherwise you will face weird exceptions thrown from PowerShell.

predict

This is great to hear! I would love to see the previous pipeline command considered in the prediction.
For instance, Get-ADUser shouldn't suggest Get-ACL when used in the pipeline.

@mpearon Can you please elaborate on it a bit more? A screenshot would be useful :)

Issues found

  1. prediction shouldn't kick in during history operations like Ctrl+r, but it's shown today:
    image

@daxian-dbw This isn't the way it is currently behaving (just a suggestion), so there isn't a screenshot to share.

Maybe I'm missing the point, but my thought was that when ML is leveraged, the suggestions that it makes (not necessarily from history), should take the previous pipeline item into consideration.
So, if I use Get-ADUser, the next pipeline commands to be suggested should be those included in that module (or related to the previous command).

Yeah, that probably makes sense. I'd generally assume that you could do something like this, suggested in order of importance or probability to be accurate.

  1. Suggest commands that accept the previous command's declared [OutputType()] as pipeline input by value.
  2. Suggest more general utility commands like Where-Object and Select-Object (and so forth)
  3. Suggest commands that accept the previous command's OutputType as pipeline input by property name.
  4. Suggest other commands from the module that the previous command is in.

I'd also recommend that commands that match either 1 or 3 _and_ are in the same module as the previous command should be suggested first. Any sorting beyond that should probably be related to frequency of usage or just alphabetical perhaps.

Great to see this being worked on, it's the one feature I miss from Fish!

Question: Have you considered the up/down prefixed history search? So if you type the start of a command then hit the Up Arrow, history searches only through commands with that prefix. Example:

fish

@Southclaws - do you already set these bindings (which I think should be changed to be the default)?

Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward

Oh, amazing, thanks!

Looking forward to the above update too, I'd be interested in testing it out but not sure how to install a module directly from a .zip

@Southclaws - I wasn't entirely sure how to force PS to default to a different PSReadline module either (short of removing/reimporting the module in a profile, or something).
Maybe a bad practice, but I just replaced the contents of the original PSReadline directory. (You can get that by issuing (Get-Module PSReadline).path)

@daxian-dbw Are we creating new issues for the preview here?
After registering the Set-PSReadlineKeyHandler options mentioned by @lzybkr, my cursor moves to character 0 of the line instead of the end of the command.
I understand that in the case that I've type a bit of a command, this would be desired - but if my cursor is already at character 0, I would expect it to move to the end of the line.
PSReadLineIssue

@mpearon - try:

Set-PSReadLineOption -HistorySearchCursorMovesToEnd 

@mpearon Replacing the original PSReadline directory is the way to use the private zip package. It should be stable enough to not crash. If you decide to get the official PSReadLine module, just use the same "upgrading" instructions from the README.md.

Also, if not yet, take a look at https://github.com/PowerShell/PSReadLine/blob/master/PSReadLine/SamplePSReadLineProfile.ps1. It contains many useful configurations to PSReadLine from @lzybkr.

@lzybkr and @daxian-dbw - Those configuration items have corrected the behavior for me! Thank you.

just wanted to say: Awesome work - Thank you!

  • VI mode - now the suggestion is disabled when switching to the command mode, and enabled when switching to insert mode.
  • So far, I haven't really focused on the VI/Emacs experience, so it could be pretty raw, and feedback is very welcome.

Suggestion seems to stay when switching modes, until an edit is made (then it's removed). I'd like to see it always update even in VI mode personally. Also ViForwardChar doesn't seem to trigger accepting the suggestion.

Very cool though.

@daxian-dbw FYI I may be messing something up but I think something changed in the latest 2020.3.1 preview and it stopped working in the integrated console.

EDIT: And yes I made sure to replace it in the extension modules folder

Thanks @JustinGrote for reporting the issue.
Looping in @TylerLeonhardt -- can you please verify it in the latest PS extension preview and see what might be the cause?

@TylerLeonhardt Checking the logs it looks like it can't load PSReadline dll for some reason
image

If I swap it back with the non-Fish one it works fine.
EDIT: And yes I did check that the files were unblocked since it was a downloaded zip

I think something changed in the latest 2020.3.1 preview

Nothing has change anywhere near the PSReadLine code path so it'd be really bizarre if that update broke it...

EDIT: And yes I made sure to replace it in the extension modules folder

Run this to double check you're replacing the right one (the one in the extension modules folder is typically for Windows PowerShell):

Get-Module PSReadLine | Select-Object Path

Checking the logs it looks like it can't load PSReadline dll for some reason

Very odd... what version of PS? PS7?

@TylerLeonhardt if nothing changed in editor services then it's probably me, let me keep banging on it for a bit. For reference it still works in my 5.1 and 7 standalone terminals, just not in Integrated.

Looks like we don't support prereleases of PSReadLine:
https://github.com/PowerShell/PowerShellEditorServices/blob/fdb5d7175c8c9c27c639a4d8d7b485b67b8908a6/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs#L30-L46

That was done last month... so the first that showed up was in 2020.2.0 or 2020.3.0 probably...

@TylerLeonhardt you nailed it
image

The zip has rc2 as a prerelease tag.

EDIT: I remember that I fixed this last time I installed it and then subsequently forgot when the new preview came out yesterday. I'll make a script to make this easier.

I think that check should be removed. There will be newer prerelease coming out for PSReadLine, and that check prevents users from adopting it.

Yep :/ if you remove the Prerelease tag from the psd1 it works.

@daxian-dbw we originally had a check that said -ge 2.0.0 & not beta1, beta2, beta3 because a critical PSReadLine fix for PSES was in beta3 or something like that...

Where-Object { $_.PrivateData.PSData.Prerelease -notin 'beta1','beta2','beta3' }

Then when PSRL GA'd that check was updated. I agree we shouldn't check for prerelease.

Maybe it should be:

$version -gt '2.0.0' -or ($version -eq '2.0.0' -and -not $_.PrivateData.PSData.Prerelease)

@SeeminglyScience that would be the ideal since there _are_ bad prereleases in 2.0.0... but then PSRL will need to update to 2.1.0-preview.1 or something for this Fish-like beta... since it's currently still using 2.0.0-rc.2

@daxian-dbw can you rebase your autocomplete branch to the latest master? I can have my script pull from your latest appveyor build for us bleeding edge testers.

but then PSRL will need to update to 2.1.0-preview.1 or something for this Fish-like beta... since it's currently still using 2.0.0-rc.2

Yeah I'm sure @daxian-dbw plans to increment the version eventually anyway. Any of us folks running the daily he posted can just alter the manifest for now probably.

@JustinGrote I rebased against master and just pushed the fish branch. But I haven't addressed all the test changes yet, so the CI build in my fork fails and produces no package.

But, I updated the uploaded .zip package in https://github.com/PowerShell/PSReadLine/issues/687#issuecomment-586629500, which now uses the 2.0.0 GA version. Hopefully that helps for the time being :)

@daxian-dbw I made an autoinstaller script for the psreadline beta for people to try it out. It installs both for the powershell used to run the script as well as any vscode powershell extensions it finds.

pwsh.exe -noni -nop -c "iwr -useb https://git.io/InstallPSReadlineAutocompleteBeta.ps1 | iex"
Capture

Tested on both win and linux but leave me feedback and comments to issues
https://gist.github.com/JustinGrote/dc10c6120007dceba2da1825ace6b073

Appreciate it @JustinGrote!

To get more feedback, the v2.1.0-beta1 of PSReadLine was published, which includes the prototype of the auto-suggestion support. This makes it easy for people to try out.

There is only one addition comparing to the zip package shared before: PredictionColor is made configurable through Set-PSReadLineOption. So you can choose the color for the suggestion text if the default color doesn't work for you.

I just wanted to say I've been using this for multiple weeks and it's AMAZING. Exactly what I imagined.

Fish also has smart tab auto-completion for various other commands e.g. git. If you write git add and hit tab, it will only show files that are changed or untracked. What would be a good way to do the same thing in Powershell? Will it be part of PSReadLine module or some other component?
https://github.com/fish-shell/fish-shell/blob/master/share/completions/git.fish

@bbhopesh the posh-git module already supplies this feature:

image

The only issue I found is that when you invoke a tab autocompletion, the history suggestion disappears, even if the new text would still match the history suggestion. Typing one more character then brings it back again. This can feel a bit diruptive/buggy.

@daxian-dbw is it possible to wire it up to register-argumentcompleter activities to refresh the history suggestion? after an argumentcompletion is suggested with tab?

For cross-reference _Predictive IntelliSense_ #1468

One thing that stands a bit in the way of these being _as good_ as fish's completion is that in PowerShell, tab-completion completes relative paths with a ./ prefix. This prefix then prevents history suggestions from being matched if you use tab completion and had typed the command before without a ./, or prevents history suggestions if you submitted only the tab-completed ./ path in the past but are now typing a path without ./. Generally I don't manually type the ./ because it is redundant (I might as well type ./././ or no prefix, it's the same thing, just more to type).

In fish and bash, paths get completed without a ./ prefix. Is there any reason this is different in PowerShell? Could this perhaps be changed?

Superb! This is excellent. :shipit:

Sent with GitHawk

@felixfbecker the de facto reason for that is that if you try to execute a script or other executable in the current location without the ./ or .\ prefix, PS will refuse to execute the item and prompt you to do that instead.

It might be a bit complicated to make that a little more specific to only apply to item and & item rather than application ./item where it currently is mistakenly applied, but it is probably possible.

Maybe it's just me but I have to specify -NonInteractive when creating powershell in windows terminal for it to do the autosuggest (I'm doing -Command Import-Module from the command line).

  • it's _so_ worth it though. It's fantastic.

@felixfbecker it doesn't have to be perfect for v1 - it just needs to be a significant improvement on what came before. That kind of functionallity could be added in later. A fishy MVP :-)

Thanks for the work on this, it's great! One thing I can't figure out is how to accept the autocomplete when using the vi editmode. The suggestion is there but neither right arrow nor any vi movements will move to the end in either normal or insert mode. Do I need to change a keyhandler or something?

@Liquidmantis there are 2 issues in VI mode today:

  • Suggestion seems to stay when switching modes
  • ViForwardChar doesn't seem to trigger accepting the suggestion.

I just installed the latest release of Powershell Core 7, is there any way to turn this off/replace the suggested text with the tab-complete text instead of history suggestions?

@chinmaya1011 that part has not been completed yet, please follow: https://github.com/PowerShell/PSReadLine/issues/1468

And contribute your input for what you would like it to look like if it doesn't meet your needs.

Hi All - Just found an issue with the autocompletion through an RDP session. Issue created here: https://github.com/PowerShell/PSReadLine/issues/1558

Maybe it's just me but I have to specify -NonInteractive when creating powershell in windows terminal for it to do the autosuggest (I'm doing -Command Import-Module from the command line).

* it's _so_ worth it though. It's fantastic.

I am having an issue with this aswell... I didn't have the "NonInteractive" parameter for my pwsh session before, but I still had this functionality working. Now, all of a sudden, it doesn't work anymore. I have tried to set the "NonInterative" parameter for my pwsh now, but it still doesn't work. I am importing PSReadLine in my profile file (along with oh-my-posh and other things) and it is picking it up when using powershell. But this fish-autocomplete isn't working.

WindowsTerminal_d1fPclJ1r1

@Fooughhy can you verify that you are using the new setting? This recently changed to not be on by default, you want to add set-psreadlineoption -predictionsource history

get-psreadlineoption | % predictionsource

There we go! I was trying to find a setting for this, but couldn't... Thank you! It works now.

One more question, does it require "NonInteractive" as my quoted comment suggested? I guess I could try it out.

EDIT: It doesn't seem to be required for me, at least.

This is so awesome - Have all the awards

Thank you for the awesome update! BTW, can function EndOfLine accept the suggestion similar to ForwardChar as well?

Was this page helpful?
0 / 5 - 0 ratings