Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Fish-like autosuggestions #43

Closed
rashil2000 opened this issue Dec 29, 2020 · 26 comments
Closed

[Feature Request] Fish-like autosuggestions #43

rashil2000 opened this issue Dec 29, 2020 · 26 comments
Labels
enhancement New feature or request

Comments

@rashil2000
Copy link
Contributor

Originally introduced by the fish shell, this shows most recent commands matching up to the current character, in a muted color.

My first question is whether something like this is even possible with Clink. It'd be very useful!

In case it is possible, here are some links for reference:

@chrisant996
Copy link
Owner

Can you give a brief description in the issue here? I see there are links I could go read to find out what is being requested, but I'd like for issue descriptions to be self contained without needing to follow links to find out what they're about.

@rashil2000
Copy link
Contributor Author

So here's how the suggestions work: You type in a few characters, and the Readline tries to autocomplete the command based on your last history (this can be configured, like, to fetch completions using Intellisense). It doesn't replace your entire typed command, but just shows the rest of the characters in a muted color. To accept the suggestion, you just press the Right arrow (again, configurable).

See this gif as an example:

autosuggestions

I provided the links for possible implementation details, sorry for the lack of clarity!

@chrisant996
Copy link
Owner

chrisant996 commented Dec 29, 2020

Thanks, it makes sense now.

This is a great thing to have on the list. Readline doesn't support colors in the input text, and its drawing routines are very complicated due to the need to interact with a bunch of different kinds of terminals.

I'm being very cautious in how much (and in what ways) I change the GNU Readline library. Diverging too much can make it expensive to safely pick up new versions of Readline.

It would be nice to be able to do this eventually. Though it doesn't seem to add much benefit beyond binding Up to history-search-backward. I wonder how often the predictions would be accurate. The cost/benefit ratio probably puts it low-ish on my priority list.

These key bindings might serve the same purpose:

"\e[A":     history-search-backward     # up; find prev history entry matching what's typed so far
"\e[B":     history-search-forward      # down; find next history entry matching what's typed so far
"\e[5~":    clink-popup-history         # pgup; popup list showing all history entries matching what's typed so far

@chrisant996 chrisant996 added the enhancement New feature or request label Dec 29, 2020
@rashil2000
Copy link
Contributor Author

Here's a quick demo I recorded from Powershell:

hmmm

I'm being very cautious in how much (and in what ways) I change the GNU Readline library. Diverging too much can make it expensive to safely pick up new versions of Readline.

True, if the Readline doesn't have some kind of built in support already, then it's a huge task (that's why ble.sh was a complete rewrite).

These key bindings might serve the same purpose:

Thanks, I already had those in my .inputrc for the time being.

Though it doesn't seem to add much benefit beyond binding Up to history-search-backward.

Yes, the Up key does the same. But since the prediction source can be configured, the suggestions would differ if configured so.

@rashil2000
Copy link
Contributor Author

Readline doesn't support colors in the input text, and its drawing routines are very complicated due to the need to interact with a bunch of different kinds of terminals.

@chrisant996 Just curious, is this why Clink doesn't support syntax highlighting (like PowerShell, Zsh) too? Bash also doesn't support text coloring.

@chrisant996
Copy link
Owner

Probably there are multiple reasons. But certainly neither feature can be implemented without first implementing the ability to apply different colors to different characters in the input text. And that's probably non-trivial because of how complex the display routines currently are.

@rashil2000
Copy link
Contributor Author

rashil2000 commented Dec 30, 2020

Thanks for the info! Closing this for now, then.

@chrisant996
Copy link
Owner

The issue is marked as a feature enhancement suggestion, and it's a good one. It's reasonable to keep it open, even if it can't be implemented quickly.

@chrisant996 chrisant996 reopened this Dec 30, 2020
@rashil2000
Copy link
Contributor Author

Oh okay, my bad for assuming it was out of scope. Apologies!

@akinomyoga
Copy link

akinomyoga commented Dec 30, 2020

Probably there are multiple reasons. But certainly neither feature can be implemented without first implementing the ability to apply different colors to different characters in the input text.

FWIW, the recently released Readline 8.1 newly supports faces (though only two styles, normal and standout, are available for the faces for now). The patch was originally provided at bug-bash mailing list:

https://lists.gnu.org/archive/html/bug-bash/2018-03/msg00056.html

Now different faces for different characters are stored in the array struct line_state::lface (defined in display.c).

/* From lib/readline/display.c */

/* State of visible and invisible lines. */
struct line_state
  {
    char *line;
    char *lface; // <- THIS
    int *lbreaks;
    int lbsize;
#if defined (HANDLE_MULTIBYTE)
    int wbsize;
    int *wrapped_line;
#endif
  };

To implement colors, I guess putc_face (display.c:1574) can be modified to output SGR sequences. I guess the face determination of each character can be, for example, performed on inv_face in rl_redisplay (display.c:742).

@chrisant996
Copy link
Owner

chrisant996 commented Dec 30, 2020

Oh, thank you for alerting me that Readline 8.1 is available! This looks very interesting indeed...

UPDATE: Ah! So good! The face change in Readline uses the same approach I was considering implementing. Except that it's hard-coded to only have two faces, and I was going to make it configurable by the host. The latter should be a minor change.

This is exciting -- the initial official release from the new Clink fork should be able to include the feature where it colors arguments and flags etc in the input line. And it lays some of the groundwork that would be necessary for implementing fish-like predictive suggestions (which definitely won't be in the initial release).

@rashil2000
Copy link
Contributor Author

That's awesome news!!!

@chrisant996
Copy link
Owner

Input line colorization is working now. The changes have been pushed to the repo, but a couple further things need to be done before a new build is published (such as updating the documentation).

@rashil2000
Copy link
Contributor Author

@chrisant996 I recently got to know about this, I thought I'd mention here to keep this issue well-documented.

Though it doesn't seem to add much benefit beyond binding Up to history-search-backward.

I was only partially correct. The autosuggestions aren't just limited to the history, it can suggest tab completion candidates and file/folder path completion candidates too (of course if no history items are found).

Zsh, fish and ble.sh - all three generate autosuggestions based on history items, autocomplete items, and path complete items - in that order. Actually, zsh-autosuggestions Readme explains it nicely here:

image

And this is an excerpt from the fish documentation:

image

Ble.sh does this in a similar way too.

@mukul-mehta
Copy link

Hello!

I'm an avid user of Clink and firstly Thank You! I moved over from fish on a mac (God I haven't been happier) and this is one of the only killer-features that I miss. I think having a better auto-suggestion system would be awesome.

Do you happen to have any update on this feature request? cc: @rashil2000

@chrisant996
Copy link
Owner

No update.

The Readline library has no way to display text that is not actually part of the input line.

I may explore ways to "trick" Readline into showing text that is not part of the input line. Or I may explore writing my own custom routines to display text.

This is the next major thing on the list, but no ETA is available.

@rashil2000
Copy link
Contributor Author

Thanks for the info @chrisant996!

A month ago I tried writing a custom Lua script to display match suggestions, but I couldn't wrap my head around it. I don't know if it's possible now (I saw some new APIs were added in recent releases).

@chrisant996
Copy link
Owner

Finding the suggestions is easy, and can be done in Lua, though I would build it into Clink using native C++ code.

But there's no way to show the suggestions. That has always been the only roadblock here.

@chrisant996
Copy link
Owner

UPDATE: dfe78c1 and 987efda have introduced the code for drawing and inserting suggestions. It turned out to be reasonably straightforward to trick Readline into showing additional text that isn't actually part of the input line.

What remains is the code to produce suggestions. That will happen during my Thanksgiving break.

And yes, scripts will be able to produce suggestions as well, very similar to how scripts can filter the prompt, generate matches, and etc.

@chrisant996
Copy link
Owner

This is implemented, and coming in v1.2.47.

@mukul-mehta
Copy link

Thanks for doing this so quickly! Appreciate it!

@chrisant996
Copy link
Owner

Thanks for doing this so quickly! Appreciate it!

You're welcome. But I've been planning it off and on for months. It hasn't been very quick, overall. 😉

@rashil2000
Copy link
Contributor Author

rashil2000 commented Nov 26, 2021

I built Clink from source to try out the feature. I seem to have run into a bug.

When the autosuggestion strategy is set to 'completion', the suggestion doesn't appear until the prefix becomes non-ambiguous.

There are 2 directories in the GIF that start from Do - Downloads and Documents. When I type just Do, no suggestion appears. When I type Doc, (i.e. now the prefix can only complete to one item, meaning it's non-ambiguous), the suggestion appears:

cmd

For comparison, here's how it appears in Zsh with the 'completion' strategy:

zsh

Note that the suggestion that appears is the first item (alphabetically) among the possible completion candidates. Same case for ble.sh:

bash

For fish:

fish

@chrisant996
Copy link
Owner

I built Clink from source to try out the feature. I seem to have run into a bug.

When the autosuggestion strategy is set to 'completion', the suggestion doesn't appear until the prefix becomes non-ambiguous.

Interesting. In fish on my ubuntu WSL installation, fish seems to be showing the longest common prefix. Maybe there is a configuration setting to choose which it does?

It's easy to make it do either, but the current behavior is intentional.

With that said, a friend likes to say "if it does it for me, it's a feature; if it does it to me, it's a bug". 🙂

I'll dig into the discrepancy, thanks!

@rashil2000
Copy link
Contributor Author

Maybe there is a configuration setting to choose which it does?

Fish does not have the option to change autosuggestion settings (only colors can be changed), like zsh (and now 🚀) clink. Other than that, I have the default settings for all GIFs.

I'll dig into the discrepancy, thanks!

Happy to help :)

@rashil2000
Copy link
Contributor Author

The latest commits fix the issue 👍

(One small nit: in the Building Documentation section in Readme, it should be npm install -g marked instead of npm install marked. Otherwise it will create node_modules in the current directory, and premake5 docs will fail.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants