diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/api/cmd.rst | 4 | ||||
-rw-r--r-- | docs/api/index.rst | 4 | ||||
-rw-r--r-- | docs/doc_conventions.rst | 2 | ||||
-rw-r--r-- | docs/examples/example.rst | 301 | ||||
-rw-r--r-- | docs/examples/index.rst | 2 | ||||
-rw-r--r-- | docs/examples/quickstart.rst | 4 | ||||
-rw-r--r-- | docs/features/commands.rst | 4 | ||||
-rw-r--r-- | docs/features/history.rst | 9 | ||||
-rw-r--r-- | docs/features/index.rst | 6 | ||||
-rw-r--r-- | docs/features/initialization.rst | 4 | ||||
-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.rst | 4 | ||||
-rw-r--r-- | docs/overview/index.rst | 3 | ||||
-rw-r--r-- | docs/overview/summary.rst | 10 |
15 files changed, 341 insertions, 21 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`` |