Cleaner separation of help() and interactive help.

Currently any call to help() uses the pager in pydoc. Because of that, you can't do some things (easily) like...
result = help(thing)
It also can be annoying (to me) when I use help and the result is cleared after the pager is done with it. That requires me to re-do the same help requests to recheck details rather than simply scroll back in the current console window. The alternative is to keep another console open just for using help. That's not always good when you already have multiple windows open for doing other things. In python 3.3, I would like to have help() return the results as a string, and only use the pager if you are actually in interactive-help mode.
help(thing) # return a help string of a thing.
help() # enter interactive help mode where the pager is used.
Separating these even more might be good, ... help() and ihelp(). In this case, the current help() function could just be renamed to ihelp(), and a new help() function would return a result as a string. The default might be help(thing='help'). The help on 'help' would refer to 'ihelp' for the interactive help. Sometime later, I want to look into moving the pager in pydoc to the cmd module as cmd.pager(). (I think it fits well there.) And related to that... I am going to look into re-implementing pydocs interactive help with the cmd module. I think it will remove some duplication, and both modules will benefit. Cheers, Ron

Ron Adam wrote:
It also can be annoying (to me) when I use help and the result is cleared after the pager is done with it.
Yeah, that annoys me too. I can't imagine why anyone thought it was a good idea to design a pager that way. Come to think of it, the whole concept of a pager is something of an anti-feature nowadays, when most people's "terminal" is really a gui window with its own scrolling facilities that are considerably better than the pager's. What I'd really like is for interactive help output to appear in a new window, preferably using by favourite text editor so I can use its searching facilities, which are also considerably better than the pager's. -- Greg

Greg Ewing wrote:
Do you have a reliable source for that claim about "most" people that is relevant to Python coders? We're not all using Microsoft VisualStudio :) This is open source, and people scratch their own itch. I daresay help() was written to suit the working processes of the creator. That suits me fine, because I like help() just the way it is, I like the pager just the way it is, and I don't want it to change. So -1 on any change to the default behaviour.
Personally, I hate it when applications decide to launch additional applications without an explicit request. What you're describing *is* a pager. The default pager is the (almost) lowest common denominator which should work for anyone anywhere. (Possibly not if they're using a teletype.) Perhaps help() should come with some more pagers and an easy interface for setting which one is used. -- Steven

Steven D'Aprano wrote:
Do you have a reliable source for that claim about "most" people that is relevant to Python coders? We're not all using Microsoft VisualStudio :)
I'm not talking about IDEs. I'm talking about things like the Terminal in MacOSX, the cmd window in Windows, and equivalent things in the Linux and X11 worlds. It's very rare nowadays for anyone to be using a command-line style interface in anything that doesn't have scroll bars attached to it.
What you're describing *is* a pager.
Yes, of course, but it's one better matched to the characteristics of the environment I usually find myself working in nowadays. Using a pager designed for glass ttys in a Terminal window is actually *worse* in many ways than just dumping the text out with no pager at all.
Perhaps help() should come with some more pagers and an easy interface for setting which one is used.
Yes, that would be good. -- Greg

On 7 Feb, 2011, at 23:34, Greg Ewing wrote:
Yes, but that doesn't mean I want help(something) to dump loads of text in my terminal window and require me to scoll back in the terminal to see the bit I want.
I don't agree. I'm quite happy with help in its current form. Ronald

On Tue, Feb 15, 2011 at 10:23 PM, Ronald Oussoren <ronaldoussoren@mac.com> wrote:
I don't agree. I'm quite happy with help in its current form.
Indeed, if the default pager isn't suitable for the default terminal program, that sounds like something to bring up with the OS developer. (I have no problems with the default setup in Kubuntu) Separating out the string generation from the display process for 3.3. may be a reasonable idea, though (similar to the separation of dis.code_info() and dis.show_code() in 3.2) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 02/15/2011 09:18 AM, Nick Coghlan wrote:
That would be a good first step to any further improvements as well. I was playing around with this today, and noticed the pager isn't used for everything, just for individual object results no matter how short or long. It's not used with any of the following commands: 'help', 'keywords', 'topics', 'symbols', or 'modules'. And if you give 'modules' a key, then the synopsis function uses print(). For example, help('modules test') results in a very long list that uses print() to output each line. Some parts of pydoc are designed so you can replace stdin and stdout, but others parts still don't seem to work that way. Does anyone actually use that feature? Cheers, Ron

On 02/15/2011 09:18 AM, Nick Coghlan wrote:
The frustrating part is trying to do this in a way that is acceptable. Actually doing it is not that difficult. I've been working on it by chipping away from the outside, but it's going to be a very slow process if we need to depreciate each existing API, and then add alternative new API's as we go. Here is a patch on rietveld which includes the items listed below. http://codereview.appspot.com/4173064 * Remove old web server stuff depreciated in 3.2. (Will be done in 3.3) * Separate the topics and topic retrieval parts into a single HelpData class with a single method to get the topic text and xrefs list. We can make this better by making the three dictionaries (keywords, topics, and symbols) use the same value formats. Currently there are slightly different ways they each store their value. It may be possible to have the xrefs auto generated and stored along with the topic text. * Rewrote the helper class by using the cmd.Cmd class. This works out nicely. After doing this, and a few other things to make it all work, there is only a single call to the pager in the Helper.default() method. It's behavior is not changed in any way. In fact, it could very easily be moved out of pydoc and refactored at this point. But I don't think we can do all of this at one time for backward compatibility reasons.(?) So currently I'm looking for guidance on what and how I can best go ahead with some parts of this. Cheers, Ron (Away for most of today. will respond to comments this evening.)

On Sun, Feb 20, 2011 at 2:36 AM, Ron Adam <rrr@ronadam.com> wrote:
I believe the approach we ended up using for the HTML parts in 3.2 (i.e. leave the "old" way around, but deprecated, for anyone using the undocumented-but-public APIs, while adding new APIs for the new, better way) should work in this case as well. It does delay the removal of the old code until 3.4, but it's the most conservative way to give people a chance to fix anything that breaks (the downside of course being that anyone using the APIs has to do some version specific tap-dancing to select which API to use). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 02/19/2011 06:35 PM, Nick Coghlan wrote:
The server replacement wasn't too bad as the old server and tkinter gui panel were not written so they could be used independently of pydoc. The new server and supporting code was either made private or put inside a function body so they could changed easily and/or be moved out of pydoc and be made available for other modules to be used. So what we did made sense in the context of what was done. As we go further with updating pydoc, it's going to have a fair amount of re-factoring. If we follow the same pattern as the server upgrade, much of the existing pydoc API will be renamed and/or removed. I'm not sure that makes as much sense. At what point is it better to depreciate the whole module and create a new replacement module? And conversely, are there limits on how much, and how fast, a module can be changed? Pydoc fortunately is almost exclusively used "as is" rather than as an extension module. So it is less likely that re-factoring it will break other peoples programs. (possible though) With other modules, we'd probably freeze the current module and create a new one with a different name, if it was going to require major re-factoring. In those cases, how long do the old modules versions stick around? Cheers, Ron

On 2/21/2011 1:56 PM, Ron Adam wrote:
As I said somewhere on the tracker, the only (intended) public apis of the pydoc module are the help function and the command-line interface. I consider the rest private and subject to change. -- Terry Jan Reedy

On 02/22/2011 07:27 PM, Terry Reedy wrote:
I agree, but I've gotten different opinions on that. It certainly would make it easier to re-factor if we can get a consensus on just what the public API is. What do you think about extending help() so it is the only pydoc API? In other words, everything is done through the help function either by directly calling help(something) or by passing args from the command line to help, ... help(args.) This already works, but not for everything. Cheers, Ron

Steven D'Aprano <steve@pearwood.info> writes:
Greg Ewing wrote:
(Greg's message isn't showing up on my Usenet server.)
Not at all. Most of my GUI terminal windows are running a terminal multiplexer, which is constantly controlling the whole terminal output as a full-terminal application. That totally defeats the GUI scrolling capability, and means that any scrolling I want to occur needs to be done via the terminal features. Terminal multiplexers include BSD's ‘tmux’ and GNU Screen.
Indeed. Even if it werent the case that the GUI scrolling capability were useless in this case, I would still want to use PgUp and PgDn keys to do it – which are (correctly) captured by the terminal program, and not available for GUI scrolling.
You might want that, and I can see that it's a valid request. It's not at all what I want, though. Switching context to another window costs me valuable attention and “flow”. Having the help appear in exactly the same window is priceless for maintaining my attention on the task.
Personally, I hate it when applications decide to launch additional applications without an explicit request.
Yup. -- \ “It has yet to be proven that intelligence has any survival | `\ value.” —Arthur C. Clarke, 2000 | _o__) | Ben Finney

On Mon, Feb 7, 2011 at 8:59 PM, Ben Finney <ben+python@benfinney.id.au> wrote:
I am -1 for changing the default behavior, and +1 for having a way of help to simply return a a text string. Maybe the addition of a keyword argumetn to help() to select this function could make everyone happy. (Or just leave default help as is, and add another function like nhelp() or ahelp() to simply return a string) js -><-

On 02/07/2011 04:08 PM, Steven D'Aprano wrote:
Ok, I'm not the only one. ;-)
I don't want to remove it. Just change where it lives and make non-paged output easy to get. So I'm looking for the best way's to do that, and then of out those ways, find the one with the least objections. :-)
I'm not sure what you mean by default pager. I guess that would be the plainpager. Which is just writing to the stdout. But it's not what you get if anything else works. The way it works, is when you first call help, it calls the pager function that then tries to create a pager from various options including looking at on environment variables PAGER and TERM. It's easier to post the code so you can see for yourself. Look in pydoc for the rest of it. In any case, I'm not proposing any changes to the pager. Cheers, Ron def pager(text): """The first time this is called, determine what kind of pager to use.""" global pager pager = getpager() pager(text) def getpager(): """Decide what method to use for paging through text.""" if not hasattr(sys.stdout, "isatty"): return plainpager if not sys.stdin.isatty() or not sys.stdout.isatty(): return plainpager if 'PAGER' in os.environ: if sys.platform == 'win32': # pipes completely broken in Windows return lambda text: tempfilepager(plain(text), os.environ['PAGER']) elif os.environ.get('TERM') in ('dumb', 'emacs'): return lambda text: pipepager(plain(text), os.environ['PAGER']) else: return lambda text: pipepager(text, os.environ['PAGER']) if os.environ.get('TERM') in ('dumb', 'emacs'): return plainpager if sys.platform == 'win32' or sys.platform.startswith('os2'): return lambda text: tempfilepager(plain(text), 'more <') if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: return lambda text: pipepager(text, 'less') import tempfile (fd, filename) = tempfile.mkstemp() os.close(fd) try: if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0: return lambda text: pipepager(text, 'more') else: return ttypager finally: os.unlink(filename) [skip various pager alternatives ....] def plainpager(text): """Simply print unformatted text. This is the ultimate fallback.""" sys.stdout.write(plain(text))

Ron Adam wrote:
I've not often needed to do that, not enough to really care, and the few times I have wanted it, result = thing.__doc__ was good enough. But I can see that it might occasionally be useful. But not enough to make it the default behaviour of help()! Something like one of these might be good though: result = help(thing, interactive=False) result = help(thing, pager=None)
Really? I find that a feature, not an annoyance. Otherwise, I'd have to scroll back to recheck results in the console window.
Then what's the problem with one more tab in your xterm app?
-1. I use help(thing) dozens of times a session, and help() on its own maybe a handful of times a year. Why would I want to get half a page of instructions *every single time* I use help() when I can just say help(thing) and go straight to the part I care about? I sympathize with your desire for a way to get help to return the text rather than feed it through a pager, but don't want it to be the default. -- Steven

On 2/7/2011 3:21 PM, Ron Adam wrote:
?? On windows, both the command prompt and IDLE shell windows keep the help text. I scroll up and down all the time. Multi-screen text would be pretty useless otherwise. I consider any other behavior buggy. Indeed, interposing the pager is a nuisance as it requires multiple returns before one can get the full text for scrolling. By whatever means, IDLE does not visibly page but gives the whole text at once. None is still the return object. help(ob) returning a string is a different issue. Since the text is ofter more than ob.__doc__ (see help(int) versus int.__doc__, for instance), returning the composed text would at minimum make it easier to test help, or to check the composed result for a particular module or class. One might even use the result as a quick ref manual, or a first draft for one. -- Terry Jan Reedy

Terry Reedy <tjreedy@udel.edu> writes:
The default pager program on many GNU+Linux systems is ‘less’. The default behaviour of ‘less’ when it quits is to restore the screen contents to what they were before the program started. Actually, I can't find any way to configure ‘less’ not to do that. Of course, one can choose a different pager by setting the ‘PAGER’ environment variable:: $ PAGER=more python Python 2.6.6 (r266:84292, Dec 27 2010, 10:20:06) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> help(os) but I'd prefer to keep ‘less’ and just fix its behaviour on quit. Does anyone know how? -- \ “Unix is an operating system, OS/2 is half an operating system, | `\ Windows is a shell, and DOS is a boot partition virus.” —Peter | _o__) H. Coffin | Ben Finney

On Tue, 08 Feb 2011 12:24:55 +1100 Ben Finney <ben+python@benfinney.id.au> wrote:
Not quite.
Actually, I can't find any way to configure ‘less’ not to do that.
That's because this behavior isn't controlled by less, it's controlled by TERMINFO. For some reason, the xterm terminal de-initialization strings in TERMINFO clears the screen. This is different from TERMCAP, and as others have noted, can be really annoying. One fix for this is to fix the TERMINFO entries, but that's 1) not universal, and 2) probably another battle last to the barbarians. An easier fix is to feed less the "-X" flag (via either the LESS or MORE environment variables, depending on which your fingers know), which causes it to not use the TERMINFO initialization/de-initialization strings. I recommend using -c with it, which clears the screen and draws from the top, so you get a screen clear at startup. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Mike Meyer <mwm@mired.org> writes:
An easier fix is to feed less the "-X" flag (via either the LESS or MORE environment variables, depending on which your fingers know),
Yep, that works for me. Another way is to set the ‘PAGER’ variable to the exact command to be used. For those experimenting at home, try this:: $ PAGER="less -cX" python Python 2.6.6 (r266:84292, Dec 27 2010, 10:20:06) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> help(os) and see whether you like that setting for the ‘PAGER’ variable. -- \ “Pinky, are you pondering what I'm pondering?” “I think so, | `\ Brain, but if the plural of mouse is mice, wouldn't the plural | _o__) of spouse be spice?” —_Pinky and The Brain_ | Ben Finney

On 02/07/2011 06:36 PM, Terry Reedy wrote:
I'm using Ubuntu now... I use to (and occasionally switch to) windows, which is why it may be annoying for me now. It doesn't act the same. I think it may be different still on Macs. I like the how the pager uses the arrow and page up keys on linux systems, but don't always want that. So I do want to keep it and make it available for use in other projects. I also want to simplify how help works and this was one thing that would do that. But there seems to be some some support for the current behaviour.
Indeed, interposing the pager is a nuisance as it requires multiple returns before one can get the full text for scrolling.
Yes, I've run across that before also.
I'm not sure if idle is doing anything other than just getting what is sent to stdout. The pager selection and control is complex enough that it is hard to tell just what is happening and how.
The complete text (as a string) for each request is sent to the pager all at once. So the content isn't an issue. The only thing that might be an issue is the bold mark ups. Which I do like. :-/ Cheers, Ron

Ron Adam wrote:
It also can be annoying (to me) when I use help and the result is cleared after the pager is done with it.
Yeah, that annoys me too. I can't imagine why anyone thought it was a good idea to design a pager that way. Come to think of it, the whole concept of a pager is something of an anti-feature nowadays, when most people's "terminal" is really a gui window with its own scrolling facilities that are considerably better than the pager's. What I'd really like is for interactive help output to appear in a new window, preferably using by favourite text editor so I can use its searching facilities, which are also considerably better than the pager's. -- Greg

Greg Ewing wrote:
Do you have a reliable source for that claim about "most" people that is relevant to Python coders? We're not all using Microsoft VisualStudio :) This is open source, and people scratch their own itch. I daresay help() was written to suit the working processes of the creator. That suits me fine, because I like help() just the way it is, I like the pager just the way it is, and I don't want it to change. So -1 on any change to the default behaviour.
Personally, I hate it when applications decide to launch additional applications without an explicit request. What you're describing *is* a pager. The default pager is the (almost) lowest common denominator which should work for anyone anywhere. (Possibly not if they're using a teletype.) Perhaps help() should come with some more pagers and an easy interface for setting which one is used. -- Steven

Steven D'Aprano wrote:
Do you have a reliable source for that claim about "most" people that is relevant to Python coders? We're not all using Microsoft VisualStudio :)
I'm not talking about IDEs. I'm talking about things like the Terminal in MacOSX, the cmd window in Windows, and equivalent things in the Linux and X11 worlds. It's very rare nowadays for anyone to be using a command-line style interface in anything that doesn't have scroll bars attached to it.
What you're describing *is* a pager.
Yes, of course, but it's one better matched to the characteristics of the environment I usually find myself working in nowadays. Using a pager designed for glass ttys in a Terminal window is actually *worse* in many ways than just dumping the text out with no pager at all.
Perhaps help() should come with some more pagers and an easy interface for setting which one is used.
Yes, that would be good. -- Greg

On 7 Feb, 2011, at 23:34, Greg Ewing wrote:
Yes, but that doesn't mean I want help(something) to dump loads of text in my terminal window and require me to scoll back in the terminal to see the bit I want.
I don't agree. I'm quite happy with help in its current form. Ronald

On Tue, Feb 15, 2011 at 10:23 PM, Ronald Oussoren <ronaldoussoren@mac.com> wrote:
I don't agree. I'm quite happy with help in its current form.
Indeed, if the default pager isn't suitable for the default terminal program, that sounds like something to bring up with the OS developer. (I have no problems with the default setup in Kubuntu) Separating out the string generation from the display process for 3.3. may be a reasonable idea, though (similar to the separation of dis.code_info() and dis.show_code() in 3.2) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 02/15/2011 09:18 AM, Nick Coghlan wrote:
That would be a good first step to any further improvements as well. I was playing around with this today, and noticed the pager isn't used for everything, just for individual object results no matter how short or long. It's not used with any of the following commands: 'help', 'keywords', 'topics', 'symbols', or 'modules'. And if you give 'modules' a key, then the synopsis function uses print(). For example, help('modules test') results in a very long list that uses print() to output each line. Some parts of pydoc are designed so you can replace stdin and stdout, but others parts still don't seem to work that way. Does anyone actually use that feature? Cheers, Ron

On 02/15/2011 09:18 AM, Nick Coghlan wrote:
The frustrating part is trying to do this in a way that is acceptable. Actually doing it is not that difficult. I've been working on it by chipping away from the outside, but it's going to be a very slow process if we need to depreciate each existing API, and then add alternative new API's as we go. Here is a patch on rietveld which includes the items listed below. http://codereview.appspot.com/4173064 * Remove old web server stuff depreciated in 3.2. (Will be done in 3.3) * Separate the topics and topic retrieval parts into a single HelpData class with a single method to get the topic text and xrefs list. We can make this better by making the three dictionaries (keywords, topics, and symbols) use the same value formats. Currently there are slightly different ways they each store their value. It may be possible to have the xrefs auto generated and stored along with the topic text. * Rewrote the helper class by using the cmd.Cmd class. This works out nicely. After doing this, and a few other things to make it all work, there is only a single call to the pager in the Helper.default() method. It's behavior is not changed in any way. In fact, it could very easily be moved out of pydoc and refactored at this point. But I don't think we can do all of this at one time for backward compatibility reasons.(?) So currently I'm looking for guidance on what and how I can best go ahead with some parts of this. Cheers, Ron (Away for most of today. will respond to comments this evening.)

On Sun, Feb 20, 2011 at 2:36 AM, Ron Adam <rrr@ronadam.com> wrote:
I believe the approach we ended up using for the HTML parts in 3.2 (i.e. leave the "old" way around, but deprecated, for anyone using the undocumented-but-public APIs, while adding new APIs for the new, better way) should work in this case as well. It does delay the removal of the old code until 3.4, but it's the most conservative way to give people a chance to fix anything that breaks (the downside of course being that anyone using the APIs has to do some version specific tap-dancing to select which API to use). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 02/19/2011 06:35 PM, Nick Coghlan wrote:
The server replacement wasn't too bad as the old server and tkinter gui panel were not written so they could be used independently of pydoc. The new server and supporting code was either made private or put inside a function body so they could changed easily and/or be moved out of pydoc and be made available for other modules to be used. So what we did made sense in the context of what was done. As we go further with updating pydoc, it's going to have a fair amount of re-factoring. If we follow the same pattern as the server upgrade, much of the existing pydoc API will be renamed and/or removed. I'm not sure that makes as much sense. At what point is it better to depreciate the whole module and create a new replacement module? And conversely, are there limits on how much, and how fast, a module can be changed? Pydoc fortunately is almost exclusively used "as is" rather than as an extension module. So it is less likely that re-factoring it will break other peoples programs. (possible though) With other modules, we'd probably freeze the current module and create a new one with a different name, if it was going to require major re-factoring. In those cases, how long do the old modules versions stick around? Cheers, Ron

On 2/21/2011 1:56 PM, Ron Adam wrote:
As I said somewhere on the tracker, the only (intended) public apis of the pydoc module are the help function and the command-line interface. I consider the rest private and subject to change. -- Terry Jan Reedy

On 02/22/2011 07:27 PM, Terry Reedy wrote:
I agree, but I've gotten different opinions on that. It certainly would make it easier to re-factor if we can get a consensus on just what the public API is. What do you think about extending help() so it is the only pydoc API? In other words, everything is done through the help function either by directly calling help(something) or by passing args from the command line to help, ... help(args.) This already works, but not for everything. Cheers, Ron

Steven D'Aprano <steve@pearwood.info> writes:
Greg Ewing wrote:
(Greg's message isn't showing up on my Usenet server.)
Not at all. Most of my GUI terminal windows are running a terminal multiplexer, which is constantly controlling the whole terminal output as a full-terminal application. That totally defeats the GUI scrolling capability, and means that any scrolling I want to occur needs to be done via the terminal features. Terminal multiplexers include BSD's ‘tmux’ and GNU Screen.
Indeed. Even if it werent the case that the GUI scrolling capability were useless in this case, I would still want to use PgUp and PgDn keys to do it – which are (correctly) captured by the terminal program, and not available for GUI scrolling.
You might want that, and I can see that it's a valid request. It's not at all what I want, though. Switching context to another window costs me valuable attention and “flow”. Having the help appear in exactly the same window is priceless for maintaining my attention on the task.
Personally, I hate it when applications decide to launch additional applications without an explicit request.
Yup. -- \ “It has yet to be proven that intelligence has any survival | `\ value.” —Arthur C. Clarke, 2000 | _o__) | Ben Finney

On Mon, Feb 7, 2011 at 8:59 PM, Ben Finney <ben+python@benfinney.id.au> wrote:
I am -1 for changing the default behavior, and +1 for having a way of help to simply return a a text string. Maybe the addition of a keyword argumetn to help() to select this function could make everyone happy. (Or just leave default help as is, and add another function like nhelp() or ahelp() to simply return a string) js -><-

On 02/07/2011 04:08 PM, Steven D'Aprano wrote:
Ok, I'm not the only one. ;-)
I don't want to remove it. Just change where it lives and make non-paged output easy to get. So I'm looking for the best way's to do that, and then of out those ways, find the one with the least objections. :-)
I'm not sure what you mean by default pager. I guess that would be the plainpager. Which is just writing to the stdout. But it's not what you get if anything else works. The way it works, is when you first call help, it calls the pager function that then tries to create a pager from various options including looking at on environment variables PAGER and TERM. It's easier to post the code so you can see for yourself. Look in pydoc for the rest of it. In any case, I'm not proposing any changes to the pager. Cheers, Ron def pager(text): """The first time this is called, determine what kind of pager to use.""" global pager pager = getpager() pager(text) def getpager(): """Decide what method to use for paging through text.""" if not hasattr(sys.stdout, "isatty"): return plainpager if not sys.stdin.isatty() or not sys.stdout.isatty(): return plainpager if 'PAGER' in os.environ: if sys.platform == 'win32': # pipes completely broken in Windows return lambda text: tempfilepager(plain(text), os.environ['PAGER']) elif os.environ.get('TERM') in ('dumb', 'emacs'): return lambda text: pipepager(plain(text), os.environ['PAGER']) else: return lambda text: pipepager(text, os.environ['PAGER']) if os.environ.get('TERM') in ('dumb', 'emacs'): return plainpager if sys.platform == 'win32' or sys.platform.startswith('os2'): return lambda text: tempfilepager(plain(text), 'more <') if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: return lambda text: pipepager(text, 'less') import tempfile (fd, filename) = tempfile.mkstemp() os.close(fd) try: if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0: return lambda text: pipepager(text, 'more') else: return ttypager finally: os.unlink(filename) [skip various pager alternatives ....] def plainpager(text): """Simply print unformatted text. This is the ultimate fallback.""" sys.stdout.write(plain(text))

Ron Adam wrote:
I've not often needed to do that, not enough to really care, and the few times I have wanted it, result = thing.__doc__ was good enough. But I can see that it might occasionally be useful. But not enough to make it the default behaviour of help()! Something like one of these might be good though: result = help(thing, interactive=False) result = help(thing, pager=None)
Really? I find that a feature, not an annoyance. Otherwise, I'd have to scroll back to recheck results in the console window.
Then what's the problem with one more tab in your xterm app?
-1. I use help(thing) dozens of times a session, and help() on its own maybe a handful of times a year. Why would I want to get half a page of instructions *every single time* I use help() when I can just say help(thing) and go straight to the part I care about? I sympathize with your desire for a way to get help to return the text rather than feed it through a pager, but don't want it to be the default. -- Steven

On 2/7/2011 3:21 PM, Ron Adam wrote:
?? On windows, both the command prompt and IDLE shell windows keep the help text. I scroll up and down all the time. Multi-screen text would be pretty useless otherwise. I consider any other behavior buggy. Indeed, interposing the pager is a nuisance as it requires multiple returns before one can get the full text for scrolling. By whatever means, IDLE does not visibly page but gives the whole text at once. None is still the return object. help(ob) returning a string is a different issue. Since the text is ofter more than ob.__doc__ (see help(int) versus int.__doc__, for instance), returning the composed text would at minimum make it easier to test help, or to check the composed result for a particular module or class. One might even use the result as a quick ref manual, or a first draft for one. -- Terry Jan Reedy

Terry Reedy <tjreedy@udel.edu> writes:
The default pager program on many GNU+Linux systems is ‘less’. The default behaviour of ‘less’ when it quits is to restore the screen contents to what they were before the program started. Actually, I can't find any way to configure ‘less’ not to do that. Of course, one can choose a different pager by setting the ‘PAGER’ environment variable:: $ PAGER=more python Python 2.6.6 (r266:84292, Dec 27 2010, 10:20:06) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> help(os) but I'd prefer to keep ‘less’ and just fix its behaviour on quit. Does anyone know how? -- \ “Unix is an operating system, OS/2 is half an operating system, | `\ Windows is a shell, and DOS is a boot partition virus.” —Peter | _o__) H. Coffin | Ben Finney

On Tue, 08 Feb 2011 12:24:55 +1100 Ben Finney <ben+python@benfinney.id.au> wrote:
Not quite.
Actually, I can't find any way to configure ‘less’ not to do that.
That's because this behavior isn't controlled by less, it's controlled by TERMINFO. For some reason, the xterm terminal de-initialization strings in TERMINFO clears the screen. This is different from TERMCAP, and as others have noted, can be really annoying. One fix for this is to fix the TERMINFO entries, but that's 1) not universal, and 2) probably another battle last to the barbarians. An easier fix is to feed less the "-X" flag (via either the LESS or MORE environment variables, depending on which your fingers know), which causes it to not use the TERMINFO initialization/de-initialization strings. I recommend using -c with it, which clears the screen and draws from the top, so you get a screen clear at startup. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

Mike Meyer <mwm@mired.org> writes:
An easier fix is to feed less the "-X" flag (via either the LESS or MORE environment variables, depending on which your fingers know),
Yep, that works for me. Another way is to set the ‘PAGER’ variable to the exact command to be used. For those experimenting at home, try this:: $ PAGER="less -cX" python Python 2.6.6 (r266:84292, Dec 27 2010, 10:20:06) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> help(os) and see whether you like that setting for the ‘PAGER’ variable. -- \ “Pinky, are you pondering what I'm pondering?” “I think so, | `\ Brain, but if the plural of mouse is mice, wouldn't the plural | _o__) of spouse be spice?” —_Pinky and The Brain_ | Ben Finney

On 02/07/2011 06:36 PM, Terry Reedy wrote:
I'm using Ubuntu now... I use to (and occasionally switch to) windows, which is why it may be annoying for me now. It doesn't act the same. I think it may be different still on Macs. I like the how the pager uses the arrow and page up keys on linux systems, but don't always want that. So I do want to keep it and make it available for use in other projects. I also want to simplify how help works and this was one thing that would do that. But there seems to be some some support for the current behaviour.
Indeed, interposing the pager is a nuisance as it requires multiple returns before one can get the full text for scrolling.
Yes, I've run across that before also.
I'm not sure if idle is doing anything other than just getting what is sent to stdout. The pager selection and control is complex enough that it is hard to tell just what is happening and how.
The complete text (as a string) for each request is sent to the pager all at once. So the content isn't an issue. The only thing that might be an issue is the bold mark ups. Which I do like. :-/ Cheers, Ron
participants (10)
-
Ben Finney
-
Greg Ewing
-
Joao S. O. Bueno
-
Mike Meyer
-
Nick Coghlan
-
Ron Adam
-
Ronald Oussoren
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Terry Reedy