Last active
January 7, 2018 03:09
-
-
Save sp1ff/f315e7074e0a03eeb1a6ee0d25b71aba to your computer and use it in GitHub Desktop.
Customize click help
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""""Click, by default, will re-purpose docstrings for help messages. I don't | |
care for this choice: docstrings are generally authored in ReStructredText | |
(cf. PEP-287), but the default click implementation does no rendering for the | |
terminal. Furthermore, if you don't want click to wrap lines for a given | |
paragraph (a code snippet, e.g.) you need to add click-specific markup | |
for it. Finally, it doesn't offer any support for paged help (like git e.g.) | |
The click .. _docs:http://click.pocoo.org/6/documentation/#help-texts state | |
that help pages "...are currently not customizable in terms of their | |
layout...", but that's not true. | |
""" | |
import click | |
def _help(ctx, value, header, synopsis, discussion, paged=True): | |
"""Print a nicely formatted help message. | |
:param ctx click.Context: The current click Context instance | |
:param header str: Heading for this help page | |
:param synopsis str: A brief description of this command | |
:param discussion str: A discussion of this command of arbitrary length | |
Print a help page in a nicer format using ANSI escape codes. | |
""" | |
from click.formatting import HelpFormatter | |
from click.termui import echo, echo_via_pager | |
if not value or ctx.resilient_parsing: | |
return | |
fmt = HelpFormatter() | |
fmt.write_text('[1m' + header + '[0m') | |
fmt.write_paragraph() | |
pieces = ctx.command.collect_usage_pieces(ctx) | |
fmt.write_usage(ctx.command_path, ' '.join(pieces), '[1mUsage[0m\n\n') | |
fmt.write_paragraph() | |
with fmt.indentation(): | |
fmt.write_text(synopsis) | |
ctx.command.format_options(ctx, fmt) | |
fmt.write_paragraph() | |
if discussion: | |
fmt.write_text('[1mDiscussion[0m') | |
fmt.write_paragraph() | |
with fmt.indentation(): | |
fmt.write_text(discussion) | |
if paged: | |
echo_via_pager(fmt.getvalue(), ctx.color) | |
else: | |
echo(fmt.getvalue(), ctx.color) | |
ctx.exit() | |
def help(**attrs): | |
"""A decorator for adding a customized help message. | |
:param header str: The header to be printed on this help page | |
:param synopsis str: A brief description of your command | |
:param discussion str: A lengthier description of your command | |
:param paged bool: Optional, if True, pipe the help page through a pager | |
""" | |
from click.decorators import _param_memo | |
header = attrs.pop('header') | |
synopsis = attrs.pop('synopsis') | |
discussion = attrs.pop('discussion') | |
paged = attrs.pop('paged', False) | |
def _shim(ctx, param, value): | |
_help(ctx, value, header, synopsis, discussion, paged) | |
def decorator(f): | |
_param_memo(f, click.Option(['-h', '--help'], | |
help='Print this message & exit with status zero', | |
is_flag=True, is_eager=True, expose_value=False, | |
callback=_shim)) | |
return f | |
return decorator | |
header = 'my command' | |
synopsis = 'This is a trivial click command.' | |
discussion = 'This is a longer discussion' | |
@click.command(add_help_option=False) | |
@help(header=header, synopsis=synopsis, discussion=discussion) | |
def cli(): | |
pass | |
if __name__ == '__main__': | |
cli() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment