Skip to content

Commit

Permalink
Introduce DESCRIPTION_MORE attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
acehreli committed Mar 13, 2018
1 parent 68dc43e commit e4cb7db
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
26 changes: 25 additions & 1 deletion plumbum/cli/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ def main(self, src, dst):
* ``DESCRIPTION`` - a short description of your program (shown in help). If not set,
the class' ``__doc__`` will be used. Can be in color.
* ``DESCRIPTION_MORE`` - a detailed description of your program (shown in help). The text will be printed
by paragraphs, delimited by empty lines. The indentation of each paragraph will be determined from the
indentation of its first line. The text may use the {progname} format specifier, which will be replaced
with the value of PROGNAME.
* ``USAGE`` - the usage line (shown in help)
* ``COLOR_USAGE`` - The color of the usage line
Expand All @@ -115,6 +120,7 @@ def main(self, src, dst):

PROGNAME = None
DESCRIPTION = None
DESCRIPTION_MORE = None
VERSION = None
USAGE = None
COLOR_USAGE = None
Expand Down Expand Up @@ -618,6 +624,25 @@ def help(self): # @ReservedAssignment
if self.DESCRIPTION:
print(self.DESCRIPTION.strip() + '\n')

cols, _ = get_terminal_size()

if self.DESCRIPTION_MORE:
# Yields each paragraph and its indentation
def paragraphs(text):
for part in text.lstrip("\n").split("\n\n"):
len_pre_strip = len(part)
part = part.lstrip()
len_post_strip = len(part)
paragraph = " ".join(part.split())
indentation = " " * (len_pre_strip - len_post_strip)
yield paragraph, indentation

for paragraph, indentation in paragraphs(self.DESCRIPTION_MORE):
wrapper = TextWrapper(width = cols, initial_indent=indentation, subsequent_indent=indentation)
for line in wrapper.wrap(paragraph.format(progname=self.PROGNAME)):
print(line)
print()

m = six.getfullargspec(self.main)
tailargs = m.args[1:] # skip self
if m.defaults:
Expand Down Expand Up @@ -666,7 +691,6 @@ def switchs(by_groups, show_groups):
print("")

sw_width = max(len(prefix) for si, prefix, color in switchs(by_groups, False)) + 4
cols, _ = get_terminal_size()
description_indent = " {0}{1}{2}"
wrapper = TextWrapper(width = max(cols - min(sw_width, 60), 50) - 6)
indentation = "\n" + " " * (cols - wrapper.width)
Expand Down
29 changes: 29 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ def cleanup(self, retcode):
print("geet commit cleaning up with rc = %s" % (retcode,))

class Sample(cli.Application):
DESCRIPTION = "A sample cli application"
DESCRIPTION_MORE = '''
This is just a sample help text typed with a Dvorak keyboard.
Although this paragraph is not left or right justified, we expect it to appear
formatted nicely. Multiple spaces should be replaced with single spaces and the
program name should be replaced with the actual program name, which happens to be '{progname}' in this case.
Here is a usage example:
{progname} --foo
Here is another paragraph.
Extra spaces should be removed.
'''

foo = cli.SwitchAttr("--foo")

Sample.unbind_switches("--version")
Expand Down Expand Up @@ -166,6 +182,19 @@ def test_unbind(self, capsys):
assert "--foo" in stdout
assert "--version" not in stdout

def test_description(self, capsys):
_, rc = Sample.run(["sample", "--help"], exit = False)
assert rc == 0
stdout, stderr = capsys.readouterr()
# Paragraph indentation should be preserved
assert " This is just a sample help text" in stdout
assert " Here is a usage example:" in stdout
# Extra spaces should be removed (hoping that this text won't be wrapped at end of line.)
assert "Extra spaces should be removed" in stdout
# {progname} should be replaced
assert "'sample'" in stdout
assert "sample --foo" in stdout

def test_default_main(self, capsys):
_, rc = Sample.run(["sample"], exit = False)
assert rc == 1
Expand Down

0 comments on commit e4cb7db

Please sign in to comment.