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.39k stars 716 forks source link

Preferred way to display charts/plots #872

Open WojciechMigda opened 5 years ago

WojciechMigda commented 5 years ago

I am planning to display ascii-art plots / charts within full screen application. My initial idea was to have Window/BufferControl/Buffer combo where I would simply set contents of the buffer with data I would like to display. However, rendering such content requires knowledge of drawable area dimensions, which to my knowledge, are not accessible directly. I know there is a create_content method for BufferControl, which is called with height/width values. With that, does it require that I would need to create a new UI Control, that would create plot content upon call to create_content? Or maybe there's a simpler way to just use generic Window/BufferControl/Buffer combo I don't see yet? Or maybe there exists a different dedicated control that can help me with doing the above?

Thank you for any tips and for creating such a useful library.

jonathanslenders commented 5 years ago

Hi @WojciechMigda,

There is indeed no easy way yet to do this (this should be improved).

A good starting point is the FormattedTextcontrol, see: https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/prompt_toolkit/layout/controls.py#L220 The important method there is create_content, which receives width and height, but they are not passed to _get_formatted_text_cached in there. Maybe you can override some methods of this class, or create a custom UIControl that does the job?

The UIControl should still be wrapped in a Window, but in this case, you won't need the text wrapping or scrolling functionality of the window, as the UIControl should generate the content that fits exactly.

WojciechMigda commented 5 years ago

Thank you for replying. After posting my question I experimented on my own. What I did was as follows:

  1. I created my own control PlotControl, and used it nested within a Window
  2. PlotControl goes like this:
    
    from prompt_toolkit.layout import BufferControl

class PlotControl(BufferControl): def init(self, *args, *kwargs): self.document_renderer = kwargs.pop('document_renderer', None) super(PlotControl, self).init(args, **kwargs)

def create_content(self, width, height, preview_search=False):
    if self.document_renderer:
        self.buffer.set_document(self.document_renderer(width, height), bypass_readonly=True)

    return super(PlotControl, self).create_content(width, height, preview_search)

where I pass a callable renderer as one of the arguments to the constructor. It is called within `create_content`, and its result is used as the `Document` subsequently set within the `buffer`.
I have noticed that if I returned a new document with each call then the app was using significantly more cpu time than usual, so I did my own caching within the rendering class where I return the same document if the plot content hasn't changed.
I have noticed though that when I focus the window with my `PlotControl` with the cursor set at position 0 then the cursor doesn't move in response to arrow keys, but I haven't investigated it yet.

The renderer I wrote uses `drawille` for plotting + `HTML` color formatting.

Re `_get_formatted_text_cached` - is it something I should take look into even if I don't use `FormattedTextControl` or it is not relevant in such case?
ShaneKosieradzki commented 2 years ago

Is extending FormattedTextcontrol still the best available method to implement this type of behavior?

I am a researcher and I would like a way to display our data--binary-tree like data currently rendered with graphviz--in a Window and display available manipulations in another Window. Is it possible to display our data if it is in an image format such as a png or svg?

UsmanAfzaal commented 2 years ago

Is extending FormattedTextcontrol still the best available method to implement this type of behavior?

I am a researcher and I would like a way to display our data--binary-tree like data currently rendered with graphviz--in a Window and display available manipulations in another Window. Is it possible to display our data if it is in an image format such as a png or svg?

Has there been any progress on this? I am trying to see if a new subclass of UIContent can do it, but I am not sure.