pdir2 icon indicating copy to clipboard operation
pdir2 copied to clipboard

Add paging

Open tmr232 opened this issue 7 years ago • 12 comments

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

tmr232 avatar Mar 10 '17 15:03 tmr232

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

laike9m avatar Mar 10 '17 15:03 laike9m

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

tmr232 avatar Mar 10 '17 15:03 tmr232

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

laike9m avatar Mar 10 '17 15:03 laike9m

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.

aluttik avatar Mar 11 '17 00:03 aluttik

Thanks @aluttik, I'll take a look.

laike9m avatar Mar 11 '17 06:03 laike9m

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.

liwt31 avatar Nov 14 '18 02:11 liwt31

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".

laike9m avatar Nov 14 '18 13:11 laike9m

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.

liwt31 avatar Nov 15 '18 01:11 liwt31

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.

laike9m avatar Nov 15 '18 02:11 laike9m

  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?

iamgodot avatar Apr 01 '22 16:04 iamgodot

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.

laike9m avatar Apr 02 '22 18:04 laike9m

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.

iamgodot avatar Apr 03 '22 00:04 iamgodot