I'm prototyping a Python app with the cmd module.
Some messages to the user will be quite long and I'd like to paginate them. The first 10 (or a configurable number) lines of the message would appear, and pressing the SPACE bar would display the next page, until the end of the message.
I don't want to reinvent something here, is there a simple mean to implement this feature?
The simple thing would just be to pipe your script through "less" or a similar command at runtime.
Here's a simple method that does approximately what you want, though:
def print_and_wait(some_long_message):
lines = some_long_message.split('\n')
i=0
while i < len(lines):
print '\n'.join(lines[i:i+10])
raw_input("press enter to read more...")
i += 10
You could also look into using curses.
As Yoni said above the right way to do this is to provide a print method that pages automatically inside your running cmd instance. The constructor of Cmd takes stdin and stdout arguments. So simple provide an object that works like stdout and supports your paging print method.
class PagingStdOut(object):
def write(self, buffer, lines_before_pause=40):
# do magic paging here...
I had the same question. There is a pager built in to the pydoc module. I incorporated it thusly (which I find hackish and unsatisfying... I'm open to better ideas though).
I like the idea that it would autopage if there are more than x results and paging is on, which is possible to implement, but not done here.
import cmd
from pydoc import pager
from cStringIO import StringIO
import sys
PAGER = True
class Commander(cmd.Cmd):
prompt = "> "
def do_pager(self,line):
global PAGER
line = line + " 1"
tokens = line.lower().split()
if tokens[0] in ("on","true","t", "1"):
PAGER = True
print "# setting PAGER True"
elif tokens[0] in ("off","false","f","0"):
PAGER = False
print "# setting PAGER False"
else:
print "# can't set pager: don't know -> %s" % tokens[0]
def do_demo(self,line):
results = dict(a=1,b=2,c=3)
self.format_commandline_results(results)
def format_commandline_results(self,results):
if PAGER:
ofh = StringIO()
else:
ofh = sys.stdout
for (k,v) in sorted(results.items()):
print >> ofh, "%s -> %s" % (k,v)
if PAGER:
ofh.seek(0)
pager(ofh.read())
return None
def do_EOF(self,line):
print "",
return True
if __name__ == "__main__":
Commander().cmdloop("# try: \n> pager off \n> demo \n> pager on \n> demo \n\n")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With