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.11k stars 718 forks source link

avoid that HSplit produces gaps between children #777

Open rofl0r opened 5 years ago

rofl0r commented 5 years ago

hi @jonathanslenders, i'd appreciate if you could give me a hint how to produce the desired effect.

from __future__ import unicode_literals
from prompt_toolkit.layout.containers import HSplit, VSplit, Window, ScrollOffsets, VerticalAlign
from prompt_toolkit import Application
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout.dimension import LayoutDimension, Dimension
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.styles import Style

def gen_win(name, lines):
    def get_text_fragments():
        tokens = []
        tokens.extend([('class:blah.title', name + '\n')])
        for i in xrange(lines):
            tokens.append(('class:blah', '#####################'))
            tokens.append(('class:blah', '\n'))
        tokens.pop()
        return tokens
    return Window(
        FormattedTextControl(get_text_fragments),
        style='class:blah',
        width=Dimension.exact(16),
        height=Dimension(min=3),
    )

cont = HSplit([
    gen_win('foo', 3),
    gen_win('bar', 9),
], align=VerticalAlign.TOP)

kb = KeyBindings()
@kb.add(u'q')
@kb.add(u'c-q')
def exit_(event):
    event.app.exit()

app = Application(
    layout = Layout(
        cont,
    ),
    full_screen=True,
    key_bindings=kb,
    style = Style.from_dict(
        {
            'blah':       'bg:#bbbbbb #000000',
            'blah.title': 'bg:#668866 #ffffff',
        }
    ),
)

app.run()

what i'd like is basically

foo
##########
##########
##########

bar
##########
##########
...

<empty space here>

but what i get is

foo
##########
##########
##########

<empty space here>

bar
##########
##########
...
jonathanslenders commented 5 years ago

Hi @rofl0r,

The empty space is not introduced by the HSplit, but by the Window instead. HSplit has a padding option to create whitespace between children, but that's not what's happening. You can see it easily by setting a background-color on the Window. (Window(..., style='bg:ansired')).

What happens is that a Window can typically take any size, although it prefers the size of its content (unless ignore_content_height=False would be given). But now, that the terminal window provides enough vertical space and each Window can take any amount, the HSplit divides it proportionally with the total height. You can fix it in this case, using:

    height=Dimension(min=3, max=lines),
rofl0r commented 5 years ago

cool, thanks! is there an official way to assign a style to the "space-eater" window in the HSplit ? what i do now is:

controls['sidebar']._remaining_space_window.style = 'class:blah'
jonathanslenders commented 5 years ago

Hi @rofl0r,

Sorry for the very late reply. I think we have to fix this in prompt_toolkit. Both HSplit and VSplit have to be modified so that this _remaining_space_window applies the padding style. Would this work: https://github.com/prompt-toolkit/python-prompt-toolkit/pull/845/files ?