summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/api/cmd.rst4
-rw-r--r--docs/api/index.rst4
-rw-r--r--docs/doc_conventions.rst2
-rw-r--r--docs/examples/example.rst301
-rw-r--r--docs/examples/index.rst2
-rw-r--r--docs/examples/quickstart.rst4
-rw-r--r--docs/features/commands.rst4
-rw-r--r--docs/features/history.rst9
-rw-r--r--docs/features/index.rst6
-rw-r--r--docs/features/initialization.rst4
-rw-r--r--docs/features/multiline_commands.rst (renamed from docs/features/multiline.rst)0
-rw-r--r--docs/features/transcripts.rst (renamed from docs/features/transcript.rst)5
-rw-r--r--docs/freefeatures.rst4
-rw-r--r--docs/overview/index.rst3
-rw-r--r--docs/overview/summary.rst10
-rwxr-xr-xexamples/example.py7
16 files changed, 344 insertions, 25 deletions
diff --git a/docs/api/cmd.rst b/docs/api/cmd.rst
index f9eefab2..35e9ae69 100644
--- a/docs/api/cmd.rst
+++ b/docs/api/cmd.rst
@@ -1,2 +1,2 @@
-cmd object
-==========
+cmd2.Cmd
+========
diff --git a/docs/api/index.rst b/docs/api/index.rst
index fd8cec36..15138cc1 100644
--- a/docs/api/index.rst
+++ b/docs/api/index.rst
@@ -1,5 +1,5 @@
-API
-===
+API Reference
+=============
.. toctree::
:maxdepth: 1
diff --git a/docs/doc_conventions.rst b/docs/doc_conventions.rst
index 504c930d..7e2eba1a 100644
--- a/docs/doc_conventions.rst
+++ b/docs/doc_conventions.rst
@@ -79,6 +79,8 @@ and
See :ref:`custom title<features/argument_processing:Help Messages>`
+[TODO what's the right way to link to source code? Can we make it link to the tag that the
+documentation is rendered from?]
Autolinking
diff --git a/docs/examples/example.rst b/docs/examples/example.rst
new file mode 100644
index 00000000..58ae9cdb
--- /dev/null
+++ b/docs/examples/example.rst
@@ -0,0 +1,301 @@
+Simple Application
+==================
+
+.. _cmd: https://docs.python.org/3/library/cmd.html
+
+Here's a quick walkthrough of a simple application which demonstrates 8 features of
+``cmd2``:
+
+* Settings
+* Commands
+* Argument Parsing
+* Generating Output
+* Help
+* Shortcuts
+* Multiline Commands
+* History
+
+If you don't want to type as we go, you can download the complete source for
+this example app.
+
+
+Basic Application
+-----------------
+
+First we need to create a new ``cmd2`` application. Create a new file ``example.py`` with the following contents::
+
+ #!/usr/bin/env python
+ """
+ A sample application for cmd2.
+ """
+ import cmd2
+
+
+ class CmdLineApp(cmd2.Cmd):
+ """Example cmd2 application. """
+
+
+ if __name__ == '__main__':
+ import sys
+ c = CmdLineApp()
+ sys.exit(c.cmdloop())
+
+We have a new class ``CmdLineApp`` which is a subclass of
+:ref:`api/cmd:cmd2.Cmd`. When we tell python to run our file like this:
+
+.. code-block:: shell
+
+ $ python example.py
+
+it creates an instance of our class, and calls the ``cmdloop()`` method. This
+method accepts user input and runs commands based on that input. Because we
+subclassed ``cmd2.Cmd``, our new app already has a bunch of features built in.
+
+Congratulations, you have a working ``cmd2`` app. You can run it, and then type
+``quit`` to exit.
+
+
+Create a New Setting
+--------------------
+
+Before we create our first command, we are going to add a setting to this app.
+``cmd2`` includes robust support for :ref:`features/settings:Settings`. You
+configure settings during object initialization, so we need to add an
+initializer to our class::
+
+ def __init__(self):
+ super().__init__()
+
+ # Make maxrepeats settable at runtime
+ self.maxrepeats = 3
+ self.settable['maxrepeats'] = 'max repetitions for speak command'
+
+In that initializer, the first thing to do is to make sure we initialize
+``cmd2``. That's what the ``super().__init__()`` line does. Then we create an
+attribute to hold our setting, and then add a description of our setting to the
+``settable`` dictionary. If our attribute name isn't in ``settable``, then it
+won't be treated as a setting. Now if you run the script, and enter the ``set``
+command to see the settings, like this:
+
+.. code-block:: shell
+
+ $ python example.py
+ (Cmd) set
+
+you will see our ``maxrepeats`` setting show up with it's default value of ``3``.
+
+
+Create A Command
+----------------
+
+Now we will create our first command, called ``speak`` which will echo back
+whatever we tell it to say. We are going to use an :ref:`argument processor
+<features/argument_processing:Argument Processing>` so the ``speak`` command can
+shout and talk piglatin. We will also use some built in methods for
+:ref:`generating output <features/generating_output:Generating Output>`. Add
+this code to ``example.py``, so that the ``speak_parser`` attribute and the
+``do_speak()`` method are part of the ``CmdLineApp()`` class::
+
+ speak_parser = argparse.ArgumentParser()
+ speak_parser.add_argument('-p', '--piglatin', action='store_true', help='atinLay')
+ speak_parser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE')
+ speak_parser.add_argument('-r', '--repeat', type=int, help='output [n] times')
+ speak_parser.add_argument('words', nargs='+', help='words to say')
+
+ @cmd2.with_argparser(speak_parser)
+ def do_speak(self, args):
+ """Repeats what you tell me to."""
+ words = []
+ for word in args.words:
+ if args.piglatin:
+ word = '%s%say' % (word[1:], word[0])
+ if args.shout:
+ word = word.upper()
+ words.append(word)
+ repetitions = args.repeat or 1
+ for _ in range(min(repetitions, self.maxrepeats)):
+ # .poutput handles newlines, and accommodates output redirection too
+ self.poutput(' '.join(words))
+
+Up at the top of the script, you'll also need to add::
+
+ import argparse
+
+There's a bit to unpack here, so let's walk through it. We created
+``speak_parser``, which uses the `argparse
+<https://docs.python.org/3/library/argparse.html>`_ module from the Python
+standard library to parse command line input from a user. There is nothing thus far
+that is specific to ``cmd2``.
+
+There is also a new method called ``do_speak()``. In both cmd_ and ``cmd2``,
+methods that start with ``do_`` become new commands, so by defining this method
+we have created a command called ``speak``.
+
+Note the ``@cmd2.with_argparser`` decorator on the ``do_speak()`` method. This
+decorator does 3 useful things for us:
+
+1. It tells ``cmd2`` to process all input for the ``speak`` command using the
+ argparser we defined. If the user input doesn't meet the requirements defined by
+ the argparser, then an error will be displayed for the user.
+2. It alters our ``do_speak`` method so that instead of receiving the raw user
+ input as a parameter, we receive the namespace from the argparser.
+3. It creates a help message for us based on the argparser.
+
+You can see in the body of the method how we use the namespace from the
+argparser (passed in as the variable ``args``). We build an array of words which
+we will output, honoring both the ``--piglatin`` and ``--shout`` options.
+
+At the end of the method, we use our ``maxrepeats`` setting as an upper limit to
+the number of times we will print the output.
+
+The last thing you'll notice is that we used the ``self.poutput()`` method to
+display our output. ``poutput()`` is a method provided by ``cmd2``, which I
+strongly recommend you use anytime you want to :ref:`generate output <features/generating_output:Generating Output>`. It provides the following benefits:
+
+1. Allows the user to redirect output to a text file or pipe it to a shell process
+2. Gracefully handles ``BrokenPipeWarning`` exceptions for redirected output
+3. Makes the output show up in a :ref:`transcript <features/transcripts:Transcripts>`
+4. Honors the setting to strip embedded ansi sequences (typically used for background and foreground colors)
+
+Go run the script again, and try out the ``speak`` command. Try typing ``help speak``, and you
+will see a lovely usage message describing the various options for the command.
+
+With those few lines of code, we created a :ref:`command
+<features/commands:Commands>`, used an :ref:`Argument Processor <features/argument_processing:Argument Processing>`, added a nice :ref:`help message <features/help:Help>` for our users, and :ref:`generated some output <features/generating_output:Generating Output>`.
+
+
+Shortcuts
+---------
+
+``cmd2`` has several capabilities to simplify repetitive user input: :ref:`Shortcuts, Aliases, and Macros <features/shortcuts_aliases_macros:Shortcuts, Aliases, and Macros>`. Let's add a shortcut to our application. Shortcuts are character strings that can be used instead of a command name. For example, ``cmd2`` has support for a shortcut ``!`` which runs the ``shell`` command. So instead of typing this:
+
+.. code-block:: shell
+
+ (Cmd) shell ls -al
+
+you can type this:
+
+.. code-block:: shell
+
+ (Cmd) !ls -al
+
+Let's add a shortcut for our ``speak`` command. Change the ``__init__()`` method so it looks like this::
+
+ def __init__(self):
+ shortcuts = cmd2.DEFAULT_SHORTCUTS
+ shortcuts.update({'&': 'speak'})
+ super().__init__(shortcuts=shortcuts)
+
+ # Make maxrepeats settable at runtime
+ self.maxrepeats = 3
+ self.settable['maxrepeats'] = 'max repetitions for speak command'
+
+Shortcuts are passed to the ``cmd2`` initializer, and if you want the built-in
+shortcuts of ``cmd2`` you have to pass them. These shortcuts are defined as a
+dictionary, with the key being the shortcut, and the value containing the
+command. When using the default shortcuts and also adding your own, it's a good
+idea to use the ``.update()`` method to modify the dictionary. This way if you
+add a shortcut that happens to already be in the default set, yours will
+override, and you won't get any errors at runtime.
+
+Run your app again, and type:
+
+.. code-block:: shell
+
+ (Cmd) shortcuts
+
+to see the list of all of the shortcuts, including the one for speak that we just created.
+
+
+Multiline Commands
+------------------
+
+Some use cases benefit from the ability to have commands that span more than one
+line. For example, you might want the ability for your user to type in a SQL
+command, which can often span lines and which are terminated with a semicolon.
+Let's add a :ref:`multiline command <features/multiline_commands:Multiline
+Commands>` to our application. First we'll create a new command called
+``orate``. This code shows both the definition of our ``speak`` command, and the
+``orate`` command::
+
+ @cmd2.with_argparser(speak_parser)
+ def do_speak(self, args):
+ """Repeats what you tell me to."""
+ words = []
+ for word in args.words:
+ if args.piglatin:
+ word = '%s%say' % (word[1:], word[0])
+ if args.shout:
+ word = word.upper()
+ words.append(word)
+ repetitions = args.repeat or 1
+ for _ in range(min(repetitions, self.maxrepeats)):
+ # .poutput handles newlines, and accommodates output redirection too
+ self.poutput(' '.join(words))
+
+ # orate is a synonym for speak which takes multiline input
+ do_orate = do_speak
+
+With the new command created, we need to tell ``cmd2`` to treat that command as
+a multi-line command. Modify the super initialization line to look like this::
+
+ super().__init__(multiline_commands=['orate'], shortcuts=shortcuts)
+
+Now when you run the example, you can type something like this:
+
+.. code-block:: shell
+
+ (Cmd) orate O for a Muse of fire, that would ascend
+ > The brightest heaven of invention,
+ > A kingdom for a stage, princes to act
+ > And monarchs to behold the swelling scene! ;
+
+Notice the prompt changes to indicate that input is still ongoing. ``cmd2`` will
+continue prompting for input until it sees an unquoted semicolon (the default
+multi-line command termination character).
+
+
+History
+-------
+
+``cmd2`` tracks the history of the commands that users enter. As a developer,
+you don't need to do anything to enable this functionality, you get it for free.
+If you want the history of commands to persist between invocations of your
+application, you'll need to do a little work. The
+:ref:`features/history:Command History` page has all the details.
+
+Users can access command history using two methods:
+
+- the `readline <https://docs.python.org/3/library/readline.html>`_ library which provides a python interface to the `GNU readline library <https://tiswww.case.edu/php/chet/readline/rltop.html>`_.
+- the ``history`` command which is built-in to ``cmd2``
+
+From the prompt in a ``cmd2``-based application, you can press ``<CNTL>-p`` to
+move to the previously entered command, and ``<CNTL>-n`` to move to the next
+command. You can also search through the command history usint ``<CNTL>-r``. The
+`GNU Readline User Manual
+<https://tiswww.case.edu/php/chet/readline/rluserman.html>`_ has all the
+details, including all the available commands, and instructions for customizing
+the key bindings.
+
+The ``history`` command allows a user to view the command history, and select
+commands from history by number, range, string search, or regular expression.
+With the selected commands, users can:
+
+- re-run the commands
+- edit the selected commands in a text editor, and run them after the text editor exits
+- save the commands to a file
+- run the commands, saving both the commands and their output to a file
+
+Learn more about the ``history`` command by typing ``history -h`` at any ``cmd2`` input prompt, or by exploring :ref:`Command History For Users <features/history:For Users>`.
+
+
+Conclusion
+----------
+
+You've just created a simple, but functional command line application. With minimal work
+on your part, the application leverages many robust features of ``cmd2``. To learn more
+you can:
+
+- Dive into all of the :doc:`../features/index` that ``cmd2`` provides
+- Look at more :doc:`../examples/index`
+- Browse the :doc:`../api/index`
diff --git a/docs/examples/index.rst b/docs/examples/index.rst
index f068f6ca..c5fbae3e 100644
--- a/docs/examples/index.rst
+++ b/docs/examples/index.rst
@@ -4,4 +4,4 @@ Examples
.. toctree::
:maxdepth: 1
- quickstart
+ example
diff --git a/docs/examples/quickstart.rst b/docs/examples/quickstart.rst
deleted file mode 100644
index 778cdbee..00000000
--- a/docs/examples/quickstart.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Building Your First cmd2 Application
-====================================
-
-Quickly show how to build a simple `cmd2` application.
diff --git a/docs/features/commands.rst b/docs/features/commands.rst
new file mode 100644
index 00000000..3eec2373
--- /dev/null
+++ b/docs/features/commands.rst
@@ -0,0 +1,4 @@
+Commands
+========
+
+How to create a command with a ``do_command`` method,
diff --git a/docs/features/history.rst b/docs/features/history.rst
index cbd3f3e6..9fd881d4 100644
--- a/docs/features/history.rst
+++ b/docs/features/history.rst
@@ -1,8 +1,15 @@
Command History
===============
+For Developers
+--------------
+
- Describe how cmd2 tracks history
-- describe the uses of the built in history command
- how persistent history works
- differences in history and bash shell history (we only store valid commands in history)
- reference the public code structures we use to store history
+
+For Users
+---------
+
+- describe the uses of the built in history command
diff --git a/docs/features/index.rst b/docs/features/index.rst
index ae2933e2..b8ee6b20 100644
--- a/docs/features/index.rst
+++ b/docs/features/index.rst
@@ -4,6 +4,7 @@ Features
.. toctree::
:maxdepth: 1
+ commands
generating_output
argument_processing
prompt
@@ -14,10 +15,11 @@ Features
settings
completion
os
- multiline
+ multiline_commands
disable_commands
clipboard
- transcript
+ transcripts
+ initialization
hooks
plugins
scripting
diff --git a/docs/features/initialization.rst b/docs/features/initialization.rst
new file mode 100644
index 00000000..b13d5bc8
--- /dev/null
+++ b/docs/features/initialization.rst
@@ -0,0 +1,4 @@
+Initialization
+==============
+
+Show how to properly initialize a ``cmd2`` app, showing parameters, sequencing, etc.
diff --git a/docs/features/multiline.rst b/docs/features/multiline_commands.rst
index 85a92bb2..85a92bb2 100644
--- a/docs/features/multiline.rst
+++ b/docs/features/multiline_commands.rst
diff --git a/docs/features/transcript.rst b/docs/features/transcripts.rst
index 089ab704..eeb51534 100644
--- a/docs/features/transcript.rst
+++ b/docs/features/transcripts.rst
@@ -1,6 +1,5 @@
-========================
-Transcript based testing
-========================
+Transcripts
+===========
A transcript is both the input and output of a successful session of a
``cmd2``-based app which is saved to a text file. With no extra work on your
diff --git a/docs/freefeatures.rst b/docs/freefeatures.rst
index fda3ee15..bf5e8934 100644
--- a/docs/freefeatures.rst
+++ b/docs/freefeatures.rst
@@ -373,7 +373,7 @@ save the first 5 commands entered in this session to a text file::
(Cmd) history :5 -o history.txt
The ``history`` command can also save both the commands and their output to a
-text file. This is called a transcript. See :doc:`features/transcript` for more
+text file. This is called a transcript. See :doc:`features/transcripts` for more
information on how transcripts work, and what you can use them for. To create a
transcript use the ``-t`` or ``--transcription`` option::
@@ -480,7 +480,7 @@ back into the app as a unit test.
OK
-See :doc:`features/transcript` for more details.
+See :doc:`features/transcripts` for more details.
Tab-Completion
diff --git a/docs/overview/index.rst b/docs/overview/index.rst
index 54415a33..831e9bf0 100644
--- a/docs/overview/index.rst
+++ b/docs/overview/index.rst
@@ -6,10 +6,11 @@ Getting Started
:hidden:
featuretour
+ ../examples/example
installation
integrating
alternatives
resources
- ../examples/quickstart
+
.. include:: summary.rst
diff --git a/docs/overview/summary.rst b/docs/overview/summary.rst
index 4145d124..d6d7abb6 100644
--- a/docs/overview/summary.rst
+++ b/docs/overview/summary.rst
@@ -3,13 +3,17 @@
Building a new `REPL <https://en.wikipedia.org/wiki/Read–eval–print_loop>`_ or
`Command Line Interface <https://en.wikipedia.org/wiki/Command-line_interface>`_
-application? ``cmd2`` is a powerful python library to help you get the job done.
+application?
+
Already built an application that uses cmd_ from the python standard library and
-want to add more functionality with very little work? Begin here to find out if
-``cmd2`` is a good fit for your needs.
+want to add more functionality with very little work?
+
+``cmd2`` is a powerful python library for built command line applications. Start
+here to find out if this library is a good fit for your needs.
* :ref:`overview/featuretour:Feature Highlights` - a quick tour of a few of the
features in ``cmd2``, for both developers and users
+* :ref:`examples/example:Simple Application` - a sample application showing 5 key features of ``cmd2``
* :ref:`overview/installation:Installation Instructions` - how to install
``cmd2`` and associated optional dependencies
* :ref:`overview/integrating:Integrate cmd2 Into Your Project` - adding ``cmd2``
diff --git a/examples/example.py b/examples/example.py
index 24be5d5d..a62c258b 100755
--- a/examples/example.py
+++ b/examples/example.py
@@ -26,10 +26,9 @@ class CmdLineApp(cmd2.Cmd):
MUMBLE_LAST = ['right?']
def __init__(self):
- shortcuts = dict(cmd2.DEFAULT_SHORTCUTS)
+ shortcuts = cmd2.DEFAULT_SHORTCUTS
shortcuts.update({'&': 'speak'})
- # Set use_ipython to True to enable the "ipy" command which embeds and interactive IPython shell
- super().__init__(use_ipython=False, multiline_commands=['orate'], shortcuts=shortcuts)
+ super().__init__(multiline_commands=['orate'], shortcuts=shortcuts)
# Make maxrepeats settable at runtime
self.maxrepeats = 3
@@ -52,7 +51,7 @@ class CmdLineApp(cmd2.Cmd):
word = word.upper()
words.append(word)
repetitions = args.repeat or 1
- for i in range(min(repetitions, self.maxrepeats)):
+ for _ in range(min(repetitions, self.maxrepeats)):
# .poutput handles newlines, and accommodates output redirection too
self.poutput(' '.join(words))