summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2018-06-16 12:13:07 -0400
committerTodd Leonhardt <todd.leonhardt@gmail.com>2018-06-16 12:13:07 -0400
commitcb23c60fafa525066a4aeed60283a8a794e48ae7 (patch)
tree17d6bbe756c0358df79f4e288ed2f6698cc6c8c8
parentb8fa8ce48acacab29d7df52101bff3bcc58ca24f (diff)
downloadcmd2-git-cb23c60fafa525066a4aeed60283a8a794e48ae7.tar.gz
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 ;-)
-rw-r--r--cmd2/cmd2.py45
-rw-r--r--tests/conftest.py8
-rw-r--r--tests/transcripts/regex_set.txt1
3 files changed, 31 insertions, 23 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 80449a34..5244f73e 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -385,17 +385,6 @@ class Cmd(cmd.Cmd):
break
feedback_to_output = False # Do not include nonessentials in >, | output by default (things like timing)
locals_in_py = False
- pager = os.environ.get('PAGER')
- if not pager:
- if sys.platform.startswith('win'):
- pager = 'more'
- else:
- # Here is the meaning of the various flags we are using with the less command:
- # -S causes lines longer than the screen width to be chopped (truncated) rather than wrapped
- # -R causes ANSI "color" escape sequences to be output in raw form (i.e. colors are displayed)
- # -X disables sending the termcap initialization and deinitialization strings to the terminal
- # -F causes less to automatically exit if the entire file can be displayed on the first screen
- pager = 'less -SRXF'
quiet = False # Do not suppress nonessential output
timing = False # Prints elapsed time for each command
@@ -408,7 +397,6 @@ class Cmd(cmd.Cmd):
'editor': 'Program used by ``edit``',
'feedback_to_output': 'Include nonessentials in `|`, `>` results',
'locals_in_py': 'Allow access to your application in py via self',
- 'pager': 'Command used for displaying paged output',
'prompt': 'The prompt issued to solicit input',
'quiet': "Don't print nonessential feedback",
'timing': 'Report execution times'}
@@ -546,6 +534,24 @@ class Cmd(cmd.Cmd):
# quote matches that are completed in a delimited fashion
self.matches_delimited = False
+ # Set the pager(s) for use with the ppaged() method for displaying output using a pager
+ self.pager = os.environ.get('PAGER')
+ if not self.pager:
+ if sys.platform.startswith('win'):
+ self.pager = self.pager_chop = 'more'
+ else:
+ # Here is the meaning of the various flags we are using with the less command:
+ # -S causes lines longer than the screen width to be chopped (truncated) rather than wrapped
+ # -R causes ANSI "color" escape sequences to be output in raw form (i.e. colors are displayed)
+ # -X disables sending the termcap initialization and deinitialization strings to the terminal
+ # -F causes less to automatically exit if the entire file can be displayed on the first screen
+ self.pager = 'less -RXF'
+ self.pager_chop = 'less -SRXF'
+ else:
+ self.pager_chop = self.pager
+ if self.pager_chop.startswith('less'):
+ self.pager_chop += ' -S'
+
# ----- Methods related to presenting output to the user -----
@property
@@ -620,14 +626,18 @@ class Cmd(cmd.Cmd):
else:
sys.stderr.write("{}\n".format(msg))
- def ppaged(self, msg: str, end: str='\n') -> None:
+ def ppaged(self, msg: str, end: str='\n', chop: bool=False) -> None:
"""Print output using a pager if it would go off screen and stdout isn't currently being redirected.
Never uses a pager inside of a script (Python or text) or when output is being redirected or piped or when
stdout or stdin are not a fully functional terminal.
- :param msg: str - message to print to current stdout - anything convertible to a str with '{}'.format() is OK
- :param end: str - string appended after the end of the message if not already present, default a newline
+ :param msg: message to print to current stdout - anything convertible to a str with '{}'.format() is OK
+ :param end: string appended after the end of the message if not already present, default a newline
+ :param chop: True -> causes lines longer than the screen width to be chopped (truncated) rather than wrapped
+ - truncated text is still accessible by scrolling with the right & left arrow keys
+ False -> causes lines longer than the screen width to wrap to the next line
+ WARNING: On Windows, the text always wraps regardless of what the chop argument is set to
"""
import subprocess
if msg is not None and msg != '':
@@ -647,7 +657,10 @@ class Cmd(cmd.Cmd):
# Don't attempt to use a pager that can block if redirecting or running a script (either text or Python)
# Also only attempt to use a pager if actually running in a real fully functional terminal
if functional_terminal and not self.redirecting and not self._in_py and not self._script_dir:
- self.pipe_proc = subprocess.Popen(self.pager, shell=True, stdin=subprocess.PIPE)
+ pager = self.pager
+ if chop:
+ pager = self.pager_chop
+ self.pipe_proc = subprocess.Popen(pager, shell=True, stdin=subprocess.PIPE)
try:
self.pipe_proc.stdin.write(msg_str.encode('utf-8', 'replace'))
self.pipe_proc.stdin.close()
diff --git a/tests/conftest.py b/tests/conftest.py
index 0027ac7d..90d45bd9 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -80,10 +80,8 @@ SHORTCUTS_TXT = """Shortcuts for other commands:
"""
expect_colors = True
-pager = 'less -SRXF'
if sys.platform.startswith('win'):
expect_colors = False
- pager = 'more '
# Output from the show command with default settings
SHOW_TXT = """colors: {}
continuation_prompt: >
@@ -92,11 +90,10 @@ echo: False
editor: vim
feedback_to_output: False
locals_in_py: False
-pager: {}
prompt: (Cmd)
quiet: False
timing: False
-""".format(expect_colors, pager)
+""".format(expect_colors)
if expect_colors:
color_str = 'True '
@@ -110,11 +107,10 @@ echo: False # Echo command issued into output
editor: vim # Program used by ``edit``
feedback_to_output: False # Include nonessentials in `|`, `>` results
locals_in_py: False # Allow access to your application in py via self
-pager: {} # Command used for displaying paged output
prompt: (Cmd) # The prompt issued to solicit input
quiet: False # Don't print nonessential feedback
timing: False # Report execution times
-""".format(color_str, pager)
+""".format(color_str)
class StdOut(object):
diff --git a/tests/transcripts/regex_set.txt b/tests/transcripts/regex_set.txt
index eba5b105..b818c464 100644
--- a/tests/transcripts/regex_set.txt
+++ b/tests/transcripts/regex_set.txt
@@ -12,7 +12,6 @@ editor: /.*/
feedback_to_output: False
locals_in_py: False
maxrepeats: 3
-pager: /.*/
prompt: (Cmd)/ /
quiet: False
timing: False