summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2019-11-03 18:03:48 -0500
committerTodd Leonhardt <todd.leonhardt@gmail.com>2019-11-03 18:03:48 -0500
commitbd1c6660079398a406d2160dd6869ea2bb9b25d0 (patch)
tree4062a6b8583cfaa1710e83f0f29d1f1bfe03ea1b
parent34158ac44cb993ae64fd7ef0a6102eb20cba3c7a (diff)
downloadcmd2-git-bd1c6660079398a406d2160dd6869ea2bb9b25d0.tar.gz
Improved documentation for Argument Parsing and Tab-Completion
Also: - Added a couple examples
-rw-r--r--docs/features/argument_processing.rst24
-rw-r--r--docs/features/completion.rst46
-rwxr-xr-xexamples/arg_decorators.py59
-rwxr-xr-xexamples/basic.py43
4 files changed, 168 insertions, 4 deletions
diff --git a/docs/features/argument_processing.rst b/docs/features/argument_processing.rst
index a3d4a3aa..a8124292 100644
--- a/docs/features/argument_processing.rst
+++ b/docs/features/argument_processing.rst
@@ -1,5 +1,3 @@
-.. _decorators:
-
Argument Processing
===================
@@ -33,6 +31,7 @@ applications.
.. _argprint: https://github.com/python-cmd2/cmd2/blob/master/examples/arg_print.py
.. _decorator: https://github.com/python-cmd2/cmd2/blob/master/examples/decorator_example.py
+.. _decorators:
Decorators provided by cmd2 for argument processing
---------------------------------------------------
@@ -40,12 +39,12 @@ Decorators provided by cmd2 for argument processing
``cmd2`` provides the following decorators for assisting with parsing arguments
passed to commands:
-.. automethod:: cmd2.decorators.with_argument_list
- :noindex:
.. automethod:: cmd2.decorators.with_argparser
:noindex:
.. automethod:: cmd2.decorators.with_argparser_and_unknown_args
:noindex:
+.. automethod:: cmd2.decorators.with_argument_list
+ :noindex:
All of these decorators accept an optional **preserve_quotes** argument which
defaults to ``False``. Setting this argument to ``True`` is useful for cases
@@ -342,3 +341,20 @@ use subcommands in your ``cmd2`` application.
.. _subcommands: https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py
.. _tab_autocompletion: https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocompletion.py
+
+
+Argprase Extensions
+-------------------
+
+``cmd2`` augments the standard ``argparse.nargs`` with range tuple capability:
+
+- ``nargs=(5,)`` - accept 5 or more items
+- ``nargs=(8, 12)`` - accept 8 to 12 items
+
+``cmd2`` also provides the ``Cmd2ArgumentParser`` class which inherits from
+``argparse.ArgumentParser`` and improves error and help output:
+
+.. autoclass:: cmd2.argparse_custom.Cmd2ArgumentParser
+ :members:
+
+
diff --git a/docs/features/completion.rst b/docs/features/completion.rst
index 5d2a722c..dfeddb27 100644
--- a/docs/features/completion.rst
+++ b/docs/features/completion.rst
@@ -31,3 +31,49 @@ similar to the following to your class which inherits from ``cmd2.Cmd``::
# Make sure you have an "import functools" somewhere at the top
complete_bar = functools.partialmethod(cmd2.Cmd.path_complete, path_filter=os.path.isdir)
+
+
+Tab Completion Using Argparse Decorators
+----------------------------------------
+
+When using one the Argparse-based :ref:`decorators`, ``cmd2`` provides
+automatic tab-completion of flag names.
+
+Tab-completion of argument values can be configured by using one of five
+parameters to ``argparse.ArgumentParser.add_argument()``
+
+- ``choices``
+- ``choices_function`` / ``choices_method``
+- ``completer_function`` / ``completer_method``
+
+See the arg_decorators_ or colors_ example for a demonstration of how to
+use the ``choices`` parameter. See the tab_autocompletion_ example for a
+demonstration of how to use the ``choices_function`` and ``choices_method``
+parameters. See the arg_decorators_ or tab_autocompletion_ example for a
+demonstration of how to use the ``completer_method`` parameter.
+
+When tab-completing flags and/or argument values for a ``cmd2`` command using
+one of these decorators, ``cmd2`` keeps track of state so that once a flag has
+already previously been provided, it won't attempt to tab-complete it again.
+When no completion results exists, a hint for the current argument will be
+displayed to help the user.
+
+.. _arg_decorators: https://github.com/python-cmd2/cmd2/blob/master/examples/arg_decorators.py
+.. _colors: https://github.com/python-cmd2/cmd2/blob/master/examples/colors.py
+.. _tab_autocompletion: https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocompletion..py
+
+
+CompletionItem For Providing Extra Context
+------------------------------------------
+
+When tab-completing things like a unique ID from a database, it can often be
+beneficial to provide the user with some extra context about the item being
+completed, such as a description. To facilitate this, ``cmd2`` defines the
+``CompletionItem`` class which can be used in combination with
+``choices_function`` or ``choices_method``.
+
+.. autoclass:: cmd2.argparse_custom.CompletionItem
+ :members:
+
+See the tab_autocompletion_ example or the implementation of the built-in
+**set** command for demonstration of how this is used.
diff --git a/examples/arg_decorators.py b/examples/arg_decorators.py
new file mode 100755
index 00000000..a085341d
--- /dev/null
+++ b/examples/arg_decorators.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+# coding=utf-8
+"""An example demonstrating how use one of cmd2's argument parsing decorators"""
+import argparse
+import os
+
+import cmd2
+
+
+class ArgparsingApp(cmd2.Cmd):
+ def __init__(self):
+ super().__init__(use_ipython=True)
+ self.intro = 'cmd2 has awesome decorators to make it easy to use Argparse to parse command arguments'
+
+ # do_fsize parser
+ fsize_parser = cmd2.Cmd2ArgumentParser(description='Obtain the size of a file')
+ fsize_parser.add_argument('-c', '--comma', action='store_true',
+ help='add comma for thousands separator')
+ fsize_parser.add_argument('-u', '--unit', choices=['MB', 'KB'], help='unit to display size in')
+ fsize_parser.add_argument('file_path', help='path of file',
+ completer_method=cmd2.Cmd.path_complete)
+
+ @cmd2.with_argparser(fsize_parser)
+ def do_fsize(self, args: argparse.Namespace) -> None:
+ """Obtain the size of a file"""
+ expanded_path = os.path.expanduser(args.file_path)
+
+ try:
+ size = os.path.getsize(expanded_path)
+ except OSError as ex:
+ self.perror("Error retrieving size: {}".format(ex))
+ return
+
+ if args.unit == 'KB':
+ size /= 1024
+ elif args.unit == 'MB':
+ size /= 1024 * 1024
+ else:
+ args.unit = 'bytes'
+ size = round(size, 2)
+
+ if args.comma:
+ size = '{:,}'.format(size)
+ self.poutput('{} {}'.format(size, args.unit))
+
+ # do_pow parser
+ pow_parser = argparse.ArgumentParser()
+ pow_parser.add_argument('base', type=int)
+ pow_parser.add_argument('exponent', type=int, choices=range(-5, 6))
+
+ @cmd2.with_argparser(pow_parser)
+ def do_pow(self, args: argparse.Namespace) -> None:
+ """Raise an integer to a small integer exponent, either positive or negative"""
+ self.poutput('{} ** {} == {}'.format(args.base, args.exponent, args.base ** args.exponent))
+
+
+if __name__ == '__main__':
+ app = ArgparsingApp()
+ app.cmdloop()
diff --git a/examples/basic.py b/examples/basic.py
new file mode 100755
index 00000000..75672a6b
--- /dev/null
+++ b/examples/basic.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+# coding=utf-8
+"""A simple example demonstrating the following:
+ 1) How to add a command
+ 2) How to add help for that command
+ 3) Persistent history
+ 4) How to run an initialization script at startup
+ 5) How to add custom command aliases using the alias command
+ 6) Shell-like capabilities
+"""
+import cmd2
+from cmd2 import style
+
+
+class BasicApp(cmd2.Cmd):
+ CUSTOM_CATEGORY = 'My Custom Commands'
+
+ def __init__(self):
+ super().__init__(multiline_commands=['echo'], persistent_history_file='cmd2_history.dat',
+ startup_script='scripts/startup.txt', use_ipython=True)
+
+ self.intro = style('Welcome to PyOhio 2019 and cmd2!', fg='red', bg='white', bold=True) + ' 😀'
+
+ # Allow access to your application in py and ipy via self
+ self.locals_in_py = True
+
+ # Set the default category name
+ self.default_category = 'cmd2 Built-in Commands'
+
+ @cmd2.with_category(CUSTOM_CATEGORY)
+ def do_intro(self, _):
+ """Display the intro banner"""
+ self.poutput(self.intro)
+
+ @cmd2.with_category(CUSTOM_CATEGORY)
+ def do_echo(self, arg):
+ """Example of a multiline command"""
+ self.poutput(arg)
+
+
+if __name__ == '__main__':
+ app = BasicApp()
+ app.cmdloop()