Skip to content

Commit cb23c60

Browse files
committed
Dramatically changed the approach to this PR
Changes include: - pager is no longer a settable parameter which can be changed by the end user at runtime - The cmd2.Cmd class now has two different attributes: - pager - contains command-line command to use to display wrapped text using a pager - By default set to PAGER environment variable if it exists - 'more' on Windows or 'less -RXF' on POSIX - pager_chop - contains command-line command to use to display chopped (truncated) text using a pager - Set to same thing as pager unless pager starts with 'less', in which case a ' -S' gets appended - The cmd2.Cmd.ppaged() method now has an additional optional argument "chop" which defaults to False - If chop is True, then self.pager_chop gets used as the pager - If chop is False, then slef.pager gets used as the pager I couldn't think of any single solution which would somehow magically make all stakeholders perfectly happy. Hopefully this is a reasonable enough compromise that everyone feels that they can get what they need without too much pain ;-)
1 parent b8fa8ce commit cb23c60

File tree

3 files changed

+31
-23
lines changed

3 files changed

+31
-23
lines changed

cmd2/cmd2.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -385,17 +385,6 @@ class Cmd(cmd.Cmd):
385385
break
386386
feedback_to_output = False # Do not include nonessentials in >, | output by default (things like timing)
387387
locals_in_py = False
388-
pager = os.environ.get('PAGER')
389-
if not pager:
390-
if sys.platform.startswith('win'):
391-
pager = 'more'
392-
else:
393-
# Here is the meaning of the various flags we are using with the less command:
394-
# -S causes lines longer than the screen width to be chopped (truncated) rather than wrapped
395-
# -R causes ANSI "color" escape sequences to be output in raw form (i.e. colors are displayed)
396-
# -X disables sending the termcap initialization and deinitialization strings to the terminal
397-
# -F causes less to automatically exit if the entire file can be displayed on the first screen
398-
pager = 'less -SRXF'
399388
quiet = False # Do not suppress nonessential output
400389
timing = False # Prints elapsed time for each command
401390

@@ -408,7 +397,6 @@ class Cmd(cmd.Cmd):
408397
'editor': 'Program used by ``edit``',
409398
'feedback_to_output': 'Include nonessentials in `|`, `>` results',
410399
'locals_in_py': 'Allow access to your application in py via self',
411-
'pager': 'Command used for displaying paged output',
412400
'prompt': 'The prompt issued to solicit input',
413401
'quiet': "Don't print nonessential feedback",
414402
'timing': 'Report execution times'}
@@ -546,6 +534,24 @@ def __init__(self, completekey: str='tab', stdin=None, stdout=None, persistent_h
546534
# quote matches that are completed in a delimited fashion
547535
self.matches_delimited = False
548536

537+
# Set the pager(s) for use with the ppaged() method for displaying output using a pager
538+
self.pager = os.environ.get('PAGER')
539+
if not self.pager:
540+
if sys.platform.startswith('win'):
541+
self.pager = self.pager_chop = 'more'
542+
else:
543+
# Here is the meaning of the various flags we are using with the less command:
544+
# -S causes lines longer than the screen width to be chopped (truncated) rather than wrapped
545+
# -R causes ANSI "color" escape sequences to be output in raw form (i.e. colors are displayed)
546+
# -X disables sending the termcap initialization and deinitialization strings to the terminal
547+
# -F causes less to automatically exit if the entire file can be displayed on the first screen
548+
self.pager = 'less -RXF'
549+
self.pager_chop = 'less -SRXF'
550+
else:
551+
self.pager_chop = self.pager
552+
if self.pager_chop.startswith('less'):
553+
self.pager_chop += ' -S'
554+
549555
# ----- Methods related to presenting output to the user -----
550556

551557
@property
@@ -620,14 +626,18 @@ def pfeedback(self, msg: str) -> None:
620626
else:
621627
sys.stderr.write("{}\n".format(msg))
622628

623-
def ppaged(self, msg: str, end: str='\n') -> None:
629+
def ppaged(self, msg: str, end: str='\n', chop: bool=False) -> None:
624630
"""Print output using a pager if it would go off screen and stdout isn't currently being redirected.
625631
626632
Never uses a pager inside of a script (Python or text) or when output is being redirected or piped or when
627633
stdout or stdin are not a fully functional terminal.
628634
629-
:param msg: str - message to print to current stdout - anything convertible to a str with '{}'.format() is OK
630-
:param end: str - string appended after the end of the message if not already present, default a newline
635+
:param msg: message to print to current stdout - anything convertible to a str with '{}'.format() is OK
636+
:param end: string appended after the end of the message if not already present, default a newline
637+
:param chop: True -> causes lines longer than the screen width to be chopped (truncated) rather than wrapped
638+
- truncated text is still accessible by scrolling with the right & left arrow keys
639+
False -> causes lines longer than the screen width to wrap to the next line
640+
WARNING: On Windows, the text always wraps regardless of what the chop argument is set to
631641
"""
632642
import subprocess
633643
if msg is not None and msg != '':
@@ -647,7 +657,10 @@ def ppaged(self, msg: str, end: str='\n') -> None:
647657
# Don't attempt to use a pager that can block if redirecting or running a script (either text or Python)
648658
# Also only attempt to use a pager if actually running in a real fully functional terminal
649659
if functional_terminal and not self.redirecting and not self._in_py and not self._script_dir:
650-
self.pipe_proc = subprocess.Popen(self.pager, shell=True, stdin=subprocess.PIPE)
660+
pager = self.pager
661+
if chop:
662+
pager = self.pager_chop
663+
self.pipe_proc = subprocess.Popen(pager, shell=True, stdin=subprocess.PIPE)
651664
try:
652665
self.pipe_proc.stdin.write(msg_str.encode('utf-8', 'replace'))
653666
self.pipe_proc.stdin.close()

tests/conftest.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,8 @@
8080
"""
8181

8282
expect_colors = True
83-
pager = 'less -SRXF'
8483
if sys.platform.startswith('win'):
8584
expect_colors = False
86-
pager = 'more '
8785
# Output from the show command with default settings
8886
SHOW_TXT = """colors: {}
8987
continuation_prompt: >
@@ -92,11 +90,10 @@
9290
editor: vim
9391
feedback_to_output: False
9492
locals_in_py: False
95-
pager: {}
9693
prompt: (Cmd)
9794
quiet: False
9895
timing: False
99-
""".format(expect_colors, pager)
96+
""".format(expect_colors)
10097

10198
if expect_colors:
10299
color_str = 'True '
@@ -110,11 +107,10 @@
110107
editor: vim # Program used by ``edit``
111108
feedback_to_output: False # Include nonessentials in `|`, `>` results
112109
locals_in_py: False # Allow access to your application in py via self
113-
pager: {} # Command used for displaying paged output
114110
prompt: (Cmd) # The prompt issued to solicit input
115111
quiet: False # Don't print nonessential feedback
116112
timing: False # Report execution times
117-
""".format(color_str, pager)
113+
""".format(color_str)
118114

119115

120116
class StdOut(object):

tests/transcripts/regex_set.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ editor: /.*/
1212
feedback_to_output: False
1313
locals_in_py: False
1414
maxrepeats: 3
15-
pager: /.*/
1615
prompt: (Cmd)/ /
1716
quiet: False
1817
timing: False

0 commit comments

Comments
 (0)