Skip to content

Conversation

@bicycle1885
Copy link
Member

@bicycle1885 bicycle1885 commented Jan 17, 2022

This is a proposal to introduce a fish/ipython-like completion feature to Julia's REPL. The current completion is not complete as it cannot select one from completion candidates. With this change, you can select one just by hitting the tab key several times. The following screencast demonstrates the behavior of proposed tab completion and navigation with arrow keys after fi[Tab].
Screen Recording 2022-01-17 at 17 22 45

This pull request is just a crude draft to demonstrate my proposal. If you like the idea, I'm happy to polish the code to review.


  • Conceptually, it introduces "completion mode" to the ordinary prompt. In completion mode,
    • Completion candidates are displayed as a table below the input.
    • Keybindings are changed so that you can select a candidate with tab, shift+tab, ctrl+n/p, and arrow keys.
    • A selected candidate is highlighted.
    • Any other keys make the prompt exit from completion mode (perhaps, narrowing candidates may be more useful).
  • When you hit a tab key in edit mode with a partial string, one of three completions will happen:
    1. if there is one and only one completion candidate, the partial string is extended to it.
    2. if there are two or more candidates, the partial string is expanded to the common prefix of these candidates and the prompt enters completion mode (nothing is selected at this moment).
    3. if sum([tab] (say), a list of methods is displayed (technically, this is not a completion).

TODO

  • Pagination
  • Method listing
  • Keybinding improvement
  • Fallback for poor terminal emulators
  • Documentation
  • Test

@bicycle1885 bicycle1885 added the REPL Julia's REPL (Read Eval Print Loop) label Jan 17, 2022
@yuyichao
Copy link
Contributor

As long as there's a way to turn this off...

@bicycle1885
Copy link
Member Author

bicycle1885 commented Jan 17, 2022

Can you elaborate a little more? I would like to minimize configurable options so I want to know the reason. I think you lose nothing in terms of functionality because hitting a tab key only once just shows a list of candidates, which is the same as the current behavior (except underlines for highlighting matching prefixes).

@DNF2
Copy link

DNF2 commented Jan 18, 2022

Any other keys make the prompt exit from completion mode.

Instead of exiting completion mode, could it narrow the search?

@domluna
Copy link

domluna commented Jan 18, 2022

Could this be used with https://github.com/JunoLab/FuzzyCompletions.jl ?

@giordano
Copy link
Member

You mean like #40691?

@bicycle1885
Copy link
Member Author

Any other keys make the prompt exit from completion mode.

Instead of exiting completion mode, could it narrow the search?

Yes, it is easy to implement. Indeed, I tried it before and it worked nicely. But I didn't do that in this pull request because neither fish nor ipython works in that way. I have no idea why but people may be more familiar with the fish/ipython-style behavior.

Could this be used with https://github.com/JunoLab/FuzzyCompletions.jl ?

Also yes. This pull request doesn't touch the internal functions of completion and only UI functions are changed. So, I think it is easy to adopt third-party completion providers like FuzzyCompletions.jl.

@yuyichao
Copy link
Contributor

. I think you lose nothing in terms of functionality because hitting a tab key only once just shows a list of candidates,

But the behavior after hitting the tab twice does change and tapping tab twice do sometimes have different behavior compared to a single tab even when it's not making a selection.

For one, in current repl, by default (or at least I don't think I've made any non-default changes) tapping tab once isn't even doing anything so tapping twice is required anyway. Even if you think it's reasonable to expect the user to distinguish one tap and two tap accurately, distinguishing two and three+ when there isn't a behavioral difference is asking too much and I do often tap tab more than twice when trying to get completion. I highly doubt I'm alone on this.

Also, in zsh, with minimal setting/by default, tapping twice is needed to show the full list of completion result when there are many pages.

Now if the tab is just for highlighting one option but isn't going to put it in by default (and require a space/enter/right arrow to put it in) I could live with it, since then it won't be much different from paging and when I type manually after typing tab the bahavior isn't going to be different by too much.

@yuyichao
Copy link
Contributor

yuyichao commented Jan 19, 2022

(so in short, the thing that is lost is when tapping tab multiple times and then trying to manually type more after seeing the completions to narrow down the options)

Edit: and along this line the behavior from #43838 (comment) might be something I could live with, especially if it's accompanied by a hotkey (Esc/C-c/C-g etc) to abort the completion mode. The ipython terminal completion behavior was way too annoy for me for the reason I stated above.

@bicycle1885
Copy link
Member Author

bicycle1885 commented Jan 20, 2022

I got your point. The currently proposed implementation is a basis for further discussion, and I'm open-minded for new ideas and proposals.

Now if the tab is just for highlighting one option but isn't going to put it in by default (and require a space/enter/right arrow to put it in) I could live with it, since then it won't be much different from paging and when I type manually after typing tab the bahavior isn't going to be different by too much.

Perhaps this point is the largest difference of our opinions. I would like to put a selected candidate in by default because it needs less typing and the user does not need to remember another keybinding to put it in.

IMO, doing nothing with the first tab key, which is the current behavior of master, doesn't make sense. If there is a good reason to do so, I would like to know that. Narrowing down candidates as you type seems to be a nice feature to have, so if other people like it, too, I would like to adopt it in this pull request. Also, keybinding to abort completion is not implemented yet but it is in my task list.

For our discussion, I've summarized below the current behaviors of julia (master), python, bash, ipython, fish, and zsh with the default setting when hitting tab keys several times in a row. Unfortunately, they are very inconsistent about tab completion.

When there are few candidates:

Tool 1st tab 2nd tab 3rd tab
julia do nothing list candidates list candidates
python do nothing list candidates list candidates
bash do nothing list candidates list candidates
ipython list candidates select first select second
fish list candidates select first select second
zsh list candidates select first select second

EDIT: zsh was wrong. updated.

When there are many candidates with the first tab:

  • julia and python behave in the same way as above.
  • bash does nothing, and another tab make it ask if you wish to see all candidates.
  • ipython starts pagination.
  • fish shows first few candidates, and another tab makes it start pagination.
  • zsh asks if you wish to see all candidates, and another tab makes it show all.

@yuyichao
Copy link
Contributor

yuyichao commented Jan 20, 2022

bash does nothing, and another tab make it ask if you wish to see all candidates.

And it show different pages on each tap, which is actually my favorate.

zsh | list candidates | do nothing | select first

The select first behavior can be disabled (and I do)

There's clearly a difference in the behavior when multiple hit of tab matters or not. For everything I use frequently, it doesn't matter and julia is also among them. I do see why someone may like to select the options automatically (fwiw, it's also the behavior of cmd on windows and that's actually where I have to face this behavior most often) and it's why I asked for a way to disable it.

@stevengj
Copy link
Member

Currently I can hit tab, then type one additional character and hit tab again to filter the list of completions. If I accidentally hit tab twice and it has substituted a possible completion X for me, can I still hit a character to filter the original tab completion, or is the character I type appended to X?

@bicycle1885
Copy link
Member Author

If I accidentally hit tab twice and it has substituted a possible completion X for me, can I still hit a character to filter the original tab completion, or is the character I type appended to X?

The latter is the proposed behavior (as in fish and ipython). I plan to implement a shortcut to abort completion even after you have selected a proposed one. If possible, I'd like to use Esc to abort the current completion but it is breaking because some shortcuts start with Esc key. So, hitting Esc twice seems to be a good choice.

@Moelf
Copy link
Contributor

Moelf commented Jan 26, 2022

Please do not complete to the first entry by default which requires users to hit backspace in order to narrow down based on the original.

Because of JIT, two time and three time can be hard to distinguish, one can easily hit three times by accident, a delay after showing the list which if tab is pressed again would complete to the first word is possible but maybe annoying to implement

As a compromise, I suggest tabbing never put in any words (so it wont ruin users ability to keep typing and narrowing things down), instead, an arrow key (or in vim style, ctrl-n) is needed.

Honestly I really like this, and personally don't mind three-tabbing because I already use fish, but I see the problem of others have raised

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

REPL Julia's REPL (Read Eval Print Loop)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants