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.28k stars 715 forks source link

Multiline prompts? #1377

Open DavidVentura opened 3 years ago

DavidVentura commented 3 years ago

I am trying to use a Completion where the display_meta is very long (like help text). But I can't get it to wrap / render new lines (\r nor \n). newlines render as ^J. I also tried using <br/> when parsing as HTML but that also doesn't work. is this supported/ easy to support?

Example image attached Screenshot_20210220_160414

MrMino commented 3 years ago

You need to give people some code that exemplifies what you are trying to do, otherwise you're making it difficult to help you.

DavidVentura commented 3 years ago

Sure, that's a screenshot of the example colored-completions.py, i assumed the example unnecessary, but here's one:

from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.shortcuts import prompt

class ColorCompleter(Completer):
    def get_completions(self, document, complete_event):
        word = document.get_word_before_cursor()
        yield Completion("Some value", display_meta="Line1\nLine2")
prompt("Prompt ", completer=ColorCompleter())

this snippet does not show 2 lines, instead it shows Line1^JLine2

MrMino commented 3 years ago

Quick notes (updated as I go):

DavidVentura commented 3 years ago

I think there's something else - I modified create_content to return duplicated completions if there are newlines:

    def create_content(self, width: int, height: int) -> UIContent:
        """
        Create a UIContent object for this control.
        """
        complete_state = get_app().current_buffer.complete_state
        if complete_state:
            completions = []
            for c in complete_state.completions:
                for line in c.display_meta_text.splitlines():
                    completions.append(c)

but still get_line only ever gets called with idx 0 -- i presume the height of the "popup" is not related to the # of completions in the UIContent.

and from my rudimentary understanding, a lot of the logic depends on cursor_position.y, so returning more lines would require many changes..

it looks like returning "thicker" lines and accounting for per-line height while rendering would be a lot easier

DavidVentura commented 3 years ago

hey, i followed the idea from @MrMino and hacked something together that kinda works: Screenshot_20210314_132634

however the floating window does not show all rows even with space. not sure where to start digging for that. i will open a PR later today for some discussion on the approach