diff options
author | Todd Leonhardt <todd.leonhardt@gmail.com> | 2019-11-02 15:37:44 -0400 |
---|---|---|
committer | Todd Leonhardt <todd.leonhardt@gmail.com> | 2019-11-02 15:37:44 -0400 |
commit | 12ade7ba7b3adde4c225b965cd4a558574c6c304 (patch) | |
tree | d92c70454f890d19d0eef5d053274c633475715e /docs/features | |
parent | a18eef6f6aa89280b5f9b92d4e681f22a438ff8b (diff) | |
download | cmd2-git-12ade7ba7b3adde4c225b965cd4a558574c6c304.tar.gz |
Added documentation for empty sections of the Sphinx docs
Diffstat (limited to 'docs/features')
-rw-r--r-- | docs/features/initialization.rst | 52 | ||||
-rw-r--r-- | docs/features/plugins.rst | 154 | ||||
-rw-r--r-- | docs/features/startup_commands.rst | 11 |
3 files changed, 215 insertions, 2 deletions
diff --git a/docs/features/initialization.rst b/docs/features/initialization.rst index f167a55a..936208f1 100644 --- a/docs/features/initialization.rst +++ b/docs/features/initialization.rst @@ -1,5 +1,53 @@ Initialization ============== -Show how to properly initialize a ``cmd2`` app, showing parameters, sequencing, -etc. +Here is a basic example ``cmd2`` application which demonstrates many +capabilities which you may wish to utilize while initializing the app:: + + #!/usr/bin/env python3 + # coding=utf-8 + """A simple example cmd2 appliction demonstrating the following: + 1) Colorizing/stylizing output + 2) Using multiline commands + 3) Persistent history + 4) How to run an initialization script at startup + 5) How to group and categorize commands when displaying them in help + 6) Opting-in to using the ipy command to run an IPython shell + 7) Allowing access to your application in py and ipy + 8) Displaying an intro banner upon starting your application + 9) Using a custom prompt + """ + 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 cmd2!', fg='red', bg='white', bold=True) + self.prompt = 'myapp> ' + + # 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() diff --git a/docs/features/plugins.rst b/docs/features/plugins.rst index 253666e7..caa46b8c 100644 --- a/docs/features/plugins.rst +++ b/docs/features/plugins.rst @@ -1,3 +1,157 @@ Plugins ======= +``cmd2`` has a built-in plugin framework which allows developers to create a +a ``cmd2`` plugin which can extend basic ``cmd2`` functionality and can be +used by multiple applications. + +Adding functionality +-------------------- + +There are many ways to add functionality to ``cmd2`` using a plugin. Most +plugins will be implemented as a mixin. A mixin is a class that encapsulates +and injects code into another class. Developers who use a plugin in their +``cmd2`` project, will inject the plugin's code into their subclass of +``cmd2.Cmd``. + + +Mixin and Initialization +~~~~~~~~~~~~~~~~~~~~~~~~ + +The following short example shows how to mix in a plugin and how the plugin +gets initialized. + +Here's the plugin:: + + class MyPlugin: + def __init__(self, *args, **kwargs): + # code placed here runs before cmd2.Cmd initializes + super().__init__(*args, **kwargs) + # code placed here runs after cmd2.Cmd initializes + + +and an example app which uses the plugin:: + + import cmd2 + import cmd2_myplugin + + class Example(cmd2_myplugin.MyPlugin, cmd2.Cmd): + """An class to show how to use a plugin""" + def __init__(self, *args, **kwargs): + # code placed here runs before cmd2.Cmd or + # any plugins initialize + super().__init__(*args, **kwargs) + # code placed here runs after cmd2.Cmd and + # all plugins have initialized + +Note how the plugin must be inherited (or mixed in) before ``cmd2.Cmd``. +This is required for two reasons: + +- The ``cmd.Cmd.__init__()`` method in the python standard library does not + call ``super().__init__()``. Because of this oversight, if you don't + inherit from ``MyPlugin`` first, the ``MyPlugin.__init__()`` method will + never be called. +- You may want your plugin to be able to override methods from ``cmd2.Cmd``. + If you mixin the plugin after ``cmd2.Cmd``, the python method resolution + order will call ``cmd2.Cmd`` methods before it calls those in your plugin. + +Add commands +~~~~~~~~~~~~ + +Your plugin can add user visible commands. You do it the same way in a plugin +that you would in a ``cmd2.Cmd`` app:: + + class MyPlugin: + def do_say(self, statement): + """Simple say command""" + self.poutput(statement) + +You have all the same capabilities within the plugin that you do inside a +``cmd2.Cmd`` app, including argument parsing via decorators and custom help +methods. + +Add (or hide) settings +~~~~~~~~~~~~~~~~~~~~~~ + +A plugin may add user controllable settings to the application. Here's an +example:: + + class MyPlugin: + def __init__(self, *args, **kwargs): + # code placed here runs before cmd2.Cmd initializes + super().__init__(*args, **kwargs) + # code placed here runs after cmd2.Cmd initializes + self.mysetting = 'somevalue' + self.settable.update({'mysetting': 'short help message for mysetting'}) + +You can also hide settings from the user by removing them from +``self.settable``. + +Decorators +~~~~~~~~~~ + +Your plugin can provide a decorator which users of your plugin can use to +wrap functionality around their own commands. + +Override methods +~~~~~~~~~~~~~~~~ + +Your plugin can override core ``cmd2.Cmd`` methods, changing their behavior. +This approach should be used sparingly, because it is very brittle. If a +developer chooses to use multiple plugins in their application, and several +of the plugins override the same method, only the first plugin to be mixed in +will have the overridden method called. + +Hooks are a much better approach. + +Hooks +~~~~~ + +Plugins can register hooks, which are called by ``cmd2.Cmd`` during various +points in the application and command processing lifecycle. Plugins should +not override any of the deprecated hook methods, instead they should register +their hooks as described in the :ref:`features/hooks:Hooks` section. + +You should name your hooks so that they begin with the name of your plugin. +Hook methods get mixed into the ``cmd2`` application and this naming +convention helps avoid unintentional method overriding. + +Here's a simple example:: + + class MyPlugin: + def __init__(self, *args, **kwargs): + # code placed here runs before cmd2 initializes + super().__init__(*args, **kwargs) + # code placed here runs after cmd2 initializes + # this is where you register any hook functions + self.register_postparsing_hook(self.cmd2_myplugin_postparsing_hook) + + def cmd2_myplugin_postparsing_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.PostparsingData: + """Method to be called after parsing user input, but before running the command""" + self.poutput('in postparsing_hook') + return data + +Registration allows multiple plugins (or even the application itself) to each +inject code to be called during the application or command processing +lifecycle. + +See the :ref:`features/hooks:Hooks` documentation for full details of the +application and command lifecycle, including all available hooks and the +ways hooks can influence the lifecycle. + + +Classes and Functions +~~~~~~~~~~~~~~~~~~~~~ + +Your plugin can also provide classes and functions which can be used by +developers of ``cmd2`` based applications. Describe these classes and +functions in your documentation so users of your plugin will know what's +available. + + +Examples +-------- + +.. _cmd2_plugin_template: https://github.com/python-cmd2/cmd2-plugin-template + +See cmd2_plugin_template_ for more info. diff --git a/docs/features/startup_commands.rst b/docs/features/startup_commands.rst index 1efcc014..4fb165a5 100644 --- a/docs/features/startup_commands.rst +++ b/docs/features/startup_commands.rst @@ -1,2 +1,13 @@ Startup Commands ================ + +``cmd2`` provides a couple different ways for running commands immediately +after your application starts up: + +1. :ref:`features/misc:Commands At Invocation` +1. :ref:`features/misc:Initialization Script` + +Commands run as part of a startup (initialization) script are always run +immediately after the application finishes initializing so they are +guaranteed to run before any *Commands At Invocation*. + |