prompt-toolkit / python-prompt-toolkit

Library for building powerful interactive command line applications in Python
https://python-prompt-toolkit.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
9.37k stars 716 forks source link

Configure max number of rows for multicolumn completion interface #1078

Open ngoldbaum opened 4 years ago

ngoldbaum commented 4 years ago

See https://github.com/ipython/ipython/issues/11757 for a motivating issue.

I spent a little time hacking around with the min_rows attribute of MultiColumnCompletionsMenu but as far as I can see that attribute doesn't actually control the height of the completions menu.

If anyone has any pointers for where to start on this I'd be very happy to work more on this.

ngoldbaum commented 4 years ago

xonsh does this but looks like it uses some private APIs to accomplish it:

https://github.com/xonsh/xonsh/blob/e062afbf3c631b93dd08ecb17028d19b8629fa7b/xonsh/ptk2/completer.py#L91-L105

ngoldbaum commented 4 years ago

@jonathanslenders is there any chance you can give me some pointers on how to do this? I've been trying to wrap my head around the prompt_toolkit codebase and am having trouble figuring out how to get it to work, at least for IPython's usages.

@scopatz mentioned to me privately that xonsh does this by mutating the _last_screen attribute of the multi-column completion menu:

https://github.com/xonsh/xonsh/blob/master/xonsh/ptk2/completer.py#L91-L105

However it looks like the same hack wouldn't work for IPython, since for some reason _last_screen is always None. I think the difference is that IPython is using prompt_toolkit.shortcuts.PromptSession to set up its prompt_toolkit app, but it might be caused by something else.

Does any of that ring a bell? Thanks ahead of time for any help or pointers you can provide.

asmeurer commented 4 years ago

@ngoldbaum I would suggest looking into fixing this in prompt-toolkit itself. Working around it downstream will be very difficult, because prompt-toolkit makes it hard to modify things about the layout without recreating the entire layout from scratch.

It looks like the relevant code is here https://github.com/prompt-toolkit/python-prompt-toolkit/blob/888fcb6fa4efea0de8333177e1bbc792f3ff3c24/prompt_toolkit/layout/menus.py. From what I can see, you should add something to preferred_height.

ngoldbaum commented 4 years ago

Right, I am looking to fix this in prompt_toolkit itself. Thanks for the suggestion!

ngoldbaum commented 4 years ago

So it's not quite correct that the completions window is always vertically compressed, I can get a much longer list of completions if I give prompt_toolkit more vertical space to work with below the cursor. This gif first shows what happens when IPython creates a long completion list and prompt_toolkit doesn't have much vertical space below the cursor, then does the same things again when there is enough vertical space.

Peek 2020-03-03 14-25

I think what ultimately is preventing the completion window from expanding further is this code:

https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/prompt_toolkit/layout/containers.py#L945-L955

If I comment it out and trigger a long set of completions, the completions window is able to expand to many more rows, even if there isn't enough vertical space below the cursor:

Peek 2020-03-03 14-28

So I guess I need a way for the MultiColumnCompletionsMenu to signal to this block of code that I really need a minimum number of rows, not just the amount of space that happens to be available vertically. I don't think it makes a ton of sense to add some code to draw_float that is specific to the MultiColumnCompletionsMenu, but I don't see an obvious alternative way to get this to work.

asmeurer commented 4 years ago

This is potentially related to https://github.com/prompt-toolkit/python-prompt-toolkit/issues/887