laike9m / pdir2

Pretty dir() printing with joy:beer:
MIT License
1.32k stars 47 forks source link

Add paging #2

Open tmr232 opened 7 years ago

tmr232 commented 7 years ago

Some classes return a very long output. Maybe paginate it?

laike9m commented 7 years ago

Using something like curses? It may adds more complexity so I'll think over it.

tmr232 commented 7 years ago

No, curses isn't supported on Windows. I thought of something simpler. Just print to fill the screen, then wait for input to continue.

laike9m commented 7 years ago

That's a good point. I'll take your advice, thanks.

aluttik commented 7 years ago

I'd recommend against doing this manually, just use one of the pydoc interfaces (source).

It's part of the standard library and works great.

laike9m commented 7 years ago

Thanks @aluttik, I'll take a look.

liwt31 commented 5 years ago

There's already an in-production solution implemented by IPython, easy to use and cross-platform, hardly documented though. Try:

import IPython
IPython.core.page.page("\n".join(map(str, range(100))

The output would be pretty much like a man page.


As I see it, the biggest problem is not the technical problem, rather, it's about user-interface. As demonstrated by the example in the README of this project, we usually use pdir in interactive shell, and the reason why we can see the output is that the shell auto evaluated the repr of the returned PrettyDir class. Add a paging logic to the process can be quite tricky. A straight forward solution is to make a judgement in the __repr__ method and invoke the paging logic when the output is too long. This isn't something beautiful because in this way __repr__ method does more than formatting a string (invoke an interactive UI actually!). The return value is also hard to define -- should __repr__ return the full output or nothing? Another solution is to implement a separate print function for the PrettyDir class which can deal with the paging in a satisfactory manner. However this is clearly not some outstanding UI design. And yet another solution is to completely refactor PrettyDir to a single function like dir. This is rather promising but I'm afraid filtering and chaining won't be easy then.

laike9m commented 5 years ago

I'm not against adding the paging logic to __repr__, as long as we do it nicely, and take care of every use case.

I'm not quite sure what you mean by "refactor PrettyDir to a single function like dir".

liwt31 commented 5 years ago

I'm not quite sure what you mean by "refactor PrettyDir to a single function like dir".

What I meant is to define a new interface for users:

def pdir(obj):
    output = repr(PrettyDir(obj))
    if too_long(output):
        paging(output)
    else:
        print(output)

At first glance chaining and filtering become impossible because nothing is returned. After some workaround they may be realized though to my knowledge it'll be less simple and elegant than previous implementation.

laike9m commented 5 years ago

I see. As the first step, we can verify if things work by creating a program and overriding __dir__. If it works, we can then migrate the implementation to pdir2. The IPython thing you mentioned is worth a try, it would be nice if if we can reimplement the logic, so that pdir2 does not rely on IPython.

iamgodot commented 2 years ago
  1. To make things simple, we can just use Python Shells for paging. There's %page command in IPython.

  2. Pydoc's pager is useful(and pretty stable), as well as Click's echo_via_pager(which basically has the same implementation). The paging function provided by IPython is able to apply conditionally by determining current screen size(inside it uses curses).

  3. How about provide a param in API(or config file) for paging and just use pydoc, instead of reinventing the wheel off of IPython?

laike9m commented 2 years ago

I don't have a strong preference on implementation, as long as they work across all supported REPLs, or at least don't break existing functionality when not compatible.

iamgodot commented 2 years ago

I don't have a strong preference on implementation, as long as they work across all supported REPLs, or at least don't break existing functionality when not compatible.

Alright, I'll see what I can do with it.