summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcmd2.py51
-rw-r--r--docs/freefeatures.rst17
-rw-r--r--docs/hooks.rst61
-rw-r--r--docs/index.rst1
-rw-r--r--docs/install.rst15
5 files changed, 116 insertions, 29 deletions
diff --git a/cmd2.py b/cmd2.py
index 987a4bcd..6dcef5f9 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -833,7 +833,7 @@ class Cmd(cmd.Cmd):
# noinspection PyMethodMayBeStatic
def preparse(self, raw):
- """Hook that runs before parsing the command-line and as the very first hook for a command.
+ """Hook method executed just before the command line is interpreted, but after the input prompt is generated.
:param raw: str - raw command line input
:return: str - potentially modified raw command line input
@@ -842,7 +842,7 @@ class Cmd(cmd.Cmd):
# noinspection PyMethodMayBeStatic
def postparse(self, parse_result):
- """Hook that runs immediately after parsing the command-line but before parsed() returns a ParsedString.
+ """Hook that runs immediately after parsing the command-line but before ``parsed()`` returns a ParsedString.
:param parse_result: pyparsing.ParseResults - parsing results output by the pyparsing parser
:return: pyparsing.ParseResults - potentially modified ParseResults object
@@ -888,8 +888,9 @@ class Cmd(cmd.Cmd):
If you wish to fatally fail this command and exit the application entirely, set stop = True.
If you wish to just fail this command you can do so by raising an exception:
- raise EmptyStatement - will silently fail and do nothing
- raise <AnyOtherException> - will fail and print an error message
+
+ - raise EmptyStatement - will silently fail and do nothing
+ - raise <AnyOtherException> - will fail and print an error message
:param statement: - the parsed command-line statement
:return: (bool, statement) - (stop, statement) containing a potentially modified version of the statement
@@ -909,25 +910,13 @@ class Cmd(cmd.Cmd):
"""
return stop
- def func_named(self, arg):
- """Gets the method name associated with a given command.
-
- If self.abbrev is False, it is always just looks for do_arg. However, if self.abbrev is True,
- it allows abbreivated command names and looks for any commands which start with do_arg.
+ def precmd(self, statement):
+ """Hook method executed just before the command is processed by ``onecmd()`` and after adding it to the history.
- :param arg: str - command to look up method name which implements it
- :return: str - method name which implements the given command
+ :param statement: ParsedString - subclass of str which also contains pyparsing ParseResults instance
+ :return: ParsedString - a potentially modified version of the input ParsedString statement
"""
- result = None
- target = 'do_' + arg
- if target in dir(self):
- result = target
- else:
- if self.abbrev: # accept shortened versions of commands
- funcs = [fname for fname in self.keywords if fname.startswith(arg)]
- if len(funcs) == 1:
- result = 'do_' + funcs[0]
- return result
+ return statement
def onecmd_plus_hooks(self, line):
"""Top-level function called by cmdloop() to handle parsing a line and running the command and all of its hooks.
@@ -1039,6 +1028,26 @@ class Cmd(cmd.Cmd):
os.remove(self._temp_filename)
self._temp_filename = None
+ def func_named(self, arg):
+ """Gets the method name associated with a given command.
+
+ If self.abbrev is False, it is always just looks for do_arg. However, if self.abbrev is True,
+ it allows abbreivated command names and looks for any commands which start with do_arg.
+
+ :param arg: str - command to look up method name which implements it
+ :return: str - method name which implements the given command
+ """
+ result = None
+ target = 'do_' + arg
+ if target in dir(self):
+ result = target
+ else:
+ if self.abbrev: # accept shortened versions of commands
+ funcs = [fname for fname in self.keywords if fname.startswith(arg)]
+ if len(funcs) == 1:
+ result = 'do_' + funcs[0]
+ return result
+
def onecmd(self, line):
""" This executes the actual do_* method for a command.
diff --git a/docs/freefeatures.rst b/docs/freefeatures.rst
index a036973d..ddde62ca 100644
--- a/docs/freefeatures.rst
+++ b/docs/freefeatures.rst
@@ -65,7 +65,7 @@ quotation marks if it is more than a one-word command.
.. note::
- if you wish to disable cmd2's consumption of command-line arguments, you can do so by setting the ``allow_cli_args``
+ If you wish to disable cmd2's consumption of command-line arguments, you can do so by setting the ``allow_cli_args``
attribute of your ``cmd2.Cmd`` class instance to ``False``. This would be useful, for example, if you wish to use
someting like Argparse_ to parse the overall command line arguments for your application::
@@ -105,6 +105,21 @@ app's value of ``self.redirector`` to use a different string for output redirect
line1
line2
+.. note::
+
+ If you wish to disable cmd2's output redirection and pipes features, you can do so by setting the ``allow_redirection``
+ attribute of your ``cmd2.Cmd`` class instance to ``False``. This would be useful, for example, if you want to restrict
+ the ability for an end user to write to disk or interact with shell commands for security reasons::
+
+ from cmd2 import Cmd
+ class App(Cmd):
+ def __init__(self):
+ self.allow_redirection = False
+
+ cmd2's parser will still treat the ``>``, ``>>``, and `|` symbols as output redirection and pipe symbols and will strip
+ arguments after them from the command line arguments accordingly. But output from a command will not be redirected
+ to a file or piped to a shell command.
+
.. _pywin32: http://sourceforge.net/projects/pywin32/
.. _xclip: http://www.cyberciti.biz/faq/xclip-linux-insert-files-command-output-intoclipboard/
diff --git a/docs/hooks.rst b/docs/hooks.rst
new file mode 100644
index 00000000..3849cce0
--- /dev/null
+++ b/docs/hooks.rst
@@ -0,0 +1,61 @@
+.. cmd2 documentation for application and command lifecycle and the hooks which are available
+
+cmd2 Application Lifecyle and Hooks
+===================================
+
+The typical way of starting a cmd2 application is as follows::
+
+ from cmd2 import Cmd
+ class App(Cmd):
+ # customized attributes and methods here
+ app = App()
+ app.cmdloop()
+
+There are several pre-existing methods and attributes which you can tweak to control the overall behavior of your
+application before, during, and after the main loop.
+
+Application Lifecycle Hook Methods
+----------------------------------
+The ``preloop`` and ``postloop`` methods run before and after the main loop, respectively.
+
+.. automethod:: cmd2.Cmd.preloop
+
+.. automethod:: cmd2.Cmd.postloop
+
+Application Lifecycle Attributes
+--------------------------------
+
+There are numerous attributes (member variables of the ``cmd2.Cmd``) which have a signficiant effect on the applicaiton
+behavior upon entering or during the main loop. A partial list of some of the more important ones is presented here:
+
+- **intro**: *str* - if provided this serves as the intro banner printed once at start of application, after ``preloop`` runs
+- **allow_cli_args**: *bool* - if True (default), then searches for -t or --test at command line to invoke transcript testing mode instead of a normal main loop
+ and also processes any commands provided as arguments on the command line just prior to entering the main loop
+- **echo**: *bool* - if True, then the command line entered is echoed to the screen (most useful when running scripts)
+- **prompt**: *str* - sets the prompt which is displayed, can be dynamically changed based on applicatoin state and/or
+ command results
+
+
+Command Processing Hooks
+------------------------
+
+Inside the main loop, every time the user hits <Enter> the line is processed by the ``onecmd_plus_hooks`` method.
+
+.. automethod:: cmd2.Cmd.onecmd_plus_hooks
+
+As the ``onecmd_plus_hooks`` name implies, there are a number of *hook* methods that can be defined in order to inject
+applicaiton-specific behavior at various points during the processing of a line of text entered by the user. ``cmd2``
+increases the 2 hooks provided by ``cmd`` (**precmd** and **postcmd**) to 6 for greater flexibility. Here are
+the various hook methods, presented in chronological order starting with the ones called earliest in the process.
+
+.. automethod:: cmd2.Cmd.preparse
+
+.. automethod:: cmd2.Cmd.postparse
+
+.. automethod:: cmd2.Cmd.postparsing_precmd
+
+.. automethod:: cmd2.Cmd.precmd
+
+.. automethod:: cmd2.Cmd.postcmd
+
+.. automethod:: cmd2.Cmd.postparsing_postcmd
diff --git a/docs/index.rst b/docs/index.rst
index 2251b435..c532c1c6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -65,6 +65,7 @@ Contents:
settingchanges
unfreefeatures
integrating
+ hooks
alternatives
Compatibility
diff --git a/docs/install.rst b/docs/install.rst
index 248d3c3c..dae100a9 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -24,13 +24,6 @@ install from PyPI_.
sudo pip install <package_name>
-.. warning::
-
- Versions of ``cmd2`` before 0.7.0 should be considered to be of unstable "beta" quality and should not be relied upon
- for production use. If you cannot get a version >= 0.7 from either pip or your OS repository, then we recommend
- installing from GitHub - see :ref:`github`.
-
-
Requirements for Installing
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* If you have Python 2 >=2.7.9 or Python 3 >=3.4 installed from `python.org
@@ -51,6 +44,8 @@ Requirements for Installing
python -m pip install -U pip setuptools
+.. _`pip_install`:
+
Use pip for Installing
~~~~~~~~~~~~~~~~~~~~~~
@@ -88,6 +83,12 @@ For Python 3::
This will also install the required 3rd-party dependencies.
+.. warning::
+
+ Versions of ``cmd2`` before 0.7.0 should be considered to be of unstable "beta" quality and should not be relied upon
+ for production use. If you cannot get a version >= 0.7 from your OS repository, then we recommend
+ installing from either pip or GitHub - see :ref:`pip_install` or :ref:`github`.
+
Deploy cmd2.py with your project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~