Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions docs/examples/alternate_event_loops.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
Alternate Event Loops
=====================

Throughout this documentation we have focused on the **90%** use case, that is
the use case we believe around **90+%** of our user base is looking for. This
focuses on ease of use and the best out-of-the-box experience where developers
get the most functionality for the least amount of effort. We are talking
about running cmd2 applications with the ``cmdloop()`` method::

from cmd2 import Cmd
class App(Cmd):
# customized attributes and methods here
app = App()
app.cmdloop()

However, there are some limitations to this way of using ``cmd2``, mainly that
``cmd2`` owns the inner loop of a program. This can be unnecessarily
restrictive and can prevent using libraries which depend on controlling their
own event loop.

Many Python concurrency libraries involve or require an event loop which they
are in control of such as asyncio_, gevent_, Twisted_, etc.

.. _asyncio: https://docs.python.org/3/library/asyncio.html
.. _gevent: http://www.gevent.org/
.. _Twisted: https://twistedmatrix.com

``cmd2`` applications can be executed in a fashion where ``cmd2`` doesn't own
the main loop for the program by using code like the following::

import cmd2

class Cmd2EventBased(cmd2.Cmd):
def __init__(self):
cmd2.Cmd.__init__(self)

# ... your class code here ...

if __name__ == '__main__':
app = Cmd2EventBased()
app.preloop()

# Do this within whatever event loop mechanism you wish to run a single command
cmd_line_text = "help history"
app.runcmds_plus_hooks([cmd_line_text])

app.postloop()

The **runcmds_plus_hooks()** method is a convenience method to run multiple
commands via **onecmd_plus_hooks()**.

The **onecmd_plus_hooks()** method will do the following to execute a single
``cmd2`` command in a normal fashion:

#. Parse user input into `Statement` object
#. Call methods registered with `register_postparsing_hook()`
#. Redirect output, if user asked for it and it's allowed
#. Start timer
#. Call methods registered with `register_precmd_hook()`
#. Call `precmd()` - for backwards compatibility with ``cmd.Cmd``
#. Add statement to history
#. Call `do_command` method
#. Call methods registered with `register_postcmd_hook()`
#. Call `postcmd(stop, statement)` - for backwards compatibility with
``cmd.Cmd``
#. Stop timer and display the elapsed time
#. Stop redirecting output if it was redirected
#. Call methods registered with `register_cmdfinalization_hook()`

Running in this fashion enables the ability to integrate with an external event
loop. However, how to integrate with any specific event loop is beyond the
scope of this documentation. Please note that running in this fashion comes
with several disadvantages, including:

* Requires the developer to write more code
* Does not support transcript testing
* Does not allow commands at invocation via command-line arguments

Here is a little more info on ``runcmds_plus_hooks``:

.. automethod:: cmd2.cmd2.Cmd.runcmds_plus_hooks
:noindex:
2 changes: 2 additions & 0 deletions docs/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ Examples
:maxdepth: 1

first_app
removing_builtin_commands
alternate_event_loops
7 changes: 7 additions & 0 deletions docs/examples/removing_builtin_commands.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Removing Builtin Commands
=========================

Show how to remove built in comamnds. Say for example you don't like the
``quit`` command included in ``cmd2``. Your application has to subclass
``cmd2.Cmd`` to work, which means you inherit the ``quit`` command. Here's how
to remove it.
43 changes: 43 additions & 0 deletions docs/features/commands.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
Commands
========

.. _cmd: https://docs.python.org/3/library/cmd.html

How to create a command with a ``do_command`` method,

Parsed statements
-----------------

``cmd2`` passes ``arg`` to a ``do_`` method (or ``default``) as a Statement, a
subclass of string that includes many attributes of the parsed input:

command
Name of the command called

args
The arguments to the command with output redirection
or piping to shell commands removed

command_and_args
A string of just the command and the arguments, with
output redirection or piping to shell commands removed

argv
A list of arguments a-la ``sys.argv``, including
the command as ``argv[0]`` and the subsequent
arguments as additional items in the list.
Quotes around arguments will be stripped as will
any output redirection or piping portions of the command

raw
Full input exactly as typed.

terminator
Character used to end a multiline command



If ``Statement`` does not contain an attribute, querying for it will return
``None``.

(Getting ``arg`` as a ``Statement`` is technically "free", in that it requires
no application changes from the cmd_ standard, but there will be no result
unless you change your application to *use* any of the additional attributes.)


31 changes: 30 additions & 1 deletion docs/features/completion.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
Completion
==========

How tab completion works and how to implement it in your own project
``cmd2`` adds tab-completion of file system paths for all built-in commands
where it makes sense, including:

- ``edit``
- ``run_pyscript``
- ``run_script``
- ``shell``

``cmd2`` also adds tab-completion of shell commands to the ``shell`` command.

Additionally, it is trivial to add identical file system path completion to
your own custom commands. Suppose you have defined a custom command ``foo`` by
implementing the ``do_foo`` method. To enable path completion for the ``foo``
command, then add a line of code similar to the following to your class which
inherits from ``cmd2.Cmd``::

complete_foo = self.path_complete

This will effectively define the ``complete_foo`` readline completer method in
your class and make it utilize the same path completion logic as the built-in
commands.

The built-in logic allows for a few more advanced path completion capabilities,
such as cases where you only want to match directories. Suppose you have a
custom command ``bar`` implemented by the ``do_bar`` method. You can enable
path completion of directories only for this command by adding a line of code
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)
8 changes: 4 additions & 4 deletions docs/features/embedded_python_shells.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ the application::
The ``py`` command also allows you to run Python scripts via ``py
run('myscript.py')``. This provides a more complicated and more powerful
scripting capability than that provided by the simple text file scripts
discussed in :ref:`scripts`. Python scripts can include conditional control
flow logic. See the **python_scripting.py** ``cmd2`` application and the
**script_conditional.py** script in the ``examples`` source code directory for
an example of how to achieve this in your own applications.
discussed in :ref:`features/scripting:Scripting`. Python scripts can include
conditional control flow logic. See the **python_scripting.py** ``cmd2``
application and the **script_conditional.py** script in the ``examples`` source
code directory for an example of how to achieve this in your own applications.

Using ``py`` to run scripts directly is considered deprecated. The newer
``run_pyscript`` command is superior for doing this in two primary ways:
Expand Down
60 changes: 60 additions & 0 deletions docs/features/generating_output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,39 @@ how to generate output
- exceptions
- color support

Standard ``cmd`` applications produce their output with
``self.stdout.write('output')`` (or with ``print``, but ``print`` decreases
output flexibility). ``cmd2`` applications can use ``self.poutput('output')``,
``self.pfeedback('message')``, ``self.perror('errmsg')``, and
``self.ppaged('text')`` instead. These methods have these advantages:

- Handle output redirection to file and/or pipe appropriately
- More concise
- ``.pfeedback()`` destination is controlled by ``quiet`` parameter.
- Option to display long output using a pager via ``ppaged()``

.. automethod:: cmd2.cmd2.Cmd.poutput
:noindex:
.. automethod:: cmd2.cmd2.Cmd.perror
:noindex:
.. automethod:: cmd2.cmd2.Cmd.pfeedback
:noindex:
.. automethod:: cmd2.cmd2.Cmd.ppaged
:noindex:


Suppressing non-essential output
--------------------------------

The ``quiet`` setting controls whether ``self.pfeedback()`` actually produces
any output. If ``quiet`` is ``False``, then the output will be produced. If
``quiet`` is ``True``, no output will be produced.

This makes ``self.pfeedback()`` useful for non-essential output like status
messages. Users can control whether they would like to see these messages by
changing the value of the ``quiet`` setting.


Output Redirection
------------------

Expand Down Expand Up @@ -43,3 +76,30 @@ If you need to include any of these redirection characters in your command, you
can enclose them in quotation marks, ``mycommand 'with > in the argument'``.


Colored Output
--------------

The output methods in the previous section all honor the ``allow_ansi``
setting, which has three possible values:

Never
poutput(), pfeedback(), and ppaged() strip all ANSI escape sequences
which instruct the terminal to colorize output

Terminal
(the default value) poutput(), pfeedback(), and ppaged() do not strip any
ANSI escape sequences when the output is a terminal, but if the output is a
pipe or a file the escape sequences are stripped. If you want colorized
output you must add ANSI escape sequences using either cmd2's internal ansi
module or another color library such as `plumbum.colors`, `colorama`, or
`colored`.

Always
poutput(), pfeedback(), and ppaged() never strip ANSI escape sequences,
regardless of the output destination

Colored and otherwise styled output can be generated using the `ansi.style()`
function:

.. automethod:: cmd2.ansi.style

7 changes: 4 additions & 3 deletions docs/features/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ would::
(Cmd) history --edit 2:4

If you want to save the commands to a text file, but not edit and re-run them,
use the ``-o`` or ``--output_file`` option. This is a great way to create
:ref:`scripts`, which can be executed using the ``run_script`` command. To
save the first 5 commands entered in this session to a text file::
use the ``-o`` or ``--output-file`` option. This is a great way to create
:ref:`Scripts <features/scripting:Scripting>`, which can be executed using the
``run_script`` command. To save the first 5 commands entered in this session to
a text file::

(Cmd) history :5 -o history.txt

Expand Down
Loading