summaryrefslogtreecommitdiff
path: root/docs/features/plugins.rst
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2019-11-08 19:17:53 -0500
committerGitHub <noreply@github.com>2019-11-08 19:17:53 -0500
commitd5916797620225391379ea40ae466bd7f496ff52 (patch)
tree6452dc4a3f1f45e31cfae16c8acccf3dd7746f14 /docs/features/plugins.rst
parenta18eef6f6aa89280b5f9b92d4e681f22a438ff8b (diff)
parent36796c2c6be67085f3d9000086de7052f08f433c (diff)
downloadcmd2-git-d5916797620225391379ea40ae466bd7f496ff52.tar.gz
Merge pull request #799 from python-cmd2/doc_updates
Doc updates
Diffstat (limited to 'docs/features/plugins.rst')
-rw-r--r--docs/features/plugins.rst154
1 files changed, 154 insertions, 0 deletions
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.