wiki:ProposedPluginArch

Proposed Plugin Architecture

I have a plugin architecture enhancement to suggest. All changes are in WikiPadHooks.py. First, here's the major points:

  • Plugin files are just dropped into user_extensions
  • Plugin files are named plugin_*.py
  • The plugin file has a plugin_init function which merely returns the name of the function to attach to and the function to call

Here's a simple plugin:

from os.path import join
  
def plugin_init():
    # Attach to "openedWikiWord" call.  Function can be named anything.
    return ['openedWikiWord',openedWikiWord_BackReference]

def openedWikiWord_BackReference(wikidPad, wikiWord):
    # Note:  Same parameters as the original function.
    #clean the page code - and insert the harvested todos after placemark = '++ auto-harvested todos:'
    editor = wikidPad.getActiveEditor()
    st = editor.FindText(0, editor.GetLength(), "Back-References:", 0)
    editor.SetSelection(st, editor.GetLength())
    editor.ReplaceSelection("\n")

    editor.AddText("Back-References:\n")
    parents = wikidPad.wikiData.getParentRelationships(wikiWord)
    outText = ",".join("[%s]" % x for x in parents)
    editor.AddText(outText)

This plugin places a Back Reference trail at the bottom of every page (lists all the pages calling it).

Here's the main changes to WikiPadHooks.py (just initialization and first function):

from os.path import *

WIKIDPAD_PLUGIN = (("hooks", 1),)

def startup(wikidPad):
    """
    Called when application starts
    """
    # MWC
    import os
    import sys

    global wikid_plugins
    wikid_plugins = {}

    dir = join(wikidPad.wikiAppDir, u'user_extensions')
    sys.path.append(dir)
    files = [f for f in os.listdir(dir) if f.startswith("plugin")]
    for file in files:
        [fn,ext] = os.path.splitext(file)
        mod = __import__(fn)
        [hook,fun] = mod.plugin_init()
        if hook not in wikid_plugins:
            wikid_plugins[hook] = []
        wikid_plugins[hook].append(fun)

def newWiki(wikidPad, wikiName, wikiDir):
    """
    Called when a new wiki is about to be created.

    wikiName -- name of the wiki (already checked to be a proper CamelCase word)
    wikiDir -- directory to create the wiki in (more precisely the .wiki config
           file). This directory may already exist
    """
    if 'newWiki' in wikid_plugins:
        for plugin in wikid_plugins['newWiki']:
            plugin(wikidPad, wikiName, wikiDir)

So, here's what is happening:

  • The startup imports all files beginning with plugin_*
  • Each plugin is responsible for returning the hook to attach to, and the function to call
  • Each function has this routine:
        if 'newWiki' in wikid_plugins:
            for plugin in wikid_plugins['newWiki']:
                plugin(wikidPad, wikiName, wikiDir)
    
  • wikid_plugins is a dictionary with a key of the function name
  • wikid_plugins returns the function to call
  • If any functions are initialized, they are called.

Advantages

  1. The WikidPadHelp.py file no longer changes
  2. New plugins can be installed just by dropping into user_extensions and restarting WikidPad

Please let me know via the forums what you think Mike

(mike at mikeandkellycrowe dot com)

Attachments:

  • New WikidPadHooks.py. No longer need to be changed
  • My todo plugin. When opening a page named "Todo*", looks for ++ auto-harvested todos: on a page and replaces from there to the end with "harvested" todo's from other pages. Heavily plagarized from other code here.
  • My Back-Reference plugin. It puts a list at the bottom of each page of all the pages referencing this page.

It works already similar

This can be done in a similar way already. You can make a copy of the default "WikidPadHooks.py" file, edit the functions as you like and put it under a new name in "user_extensions". After a restart WikidPad checks all Python scripts in "user_extensions" for hook scripts which are identified by the line

WIKIDPAD_PLUGIN = (("hooks", 1),)

For demonstration I have rewritten your "plugin_BackReference.py" and "plugin_Todo.py" as "std_BackReference.py" and "std_PluginTodo.py" (see attachments, the "std_" prefix is not necessary) which can be put in "user_extensions" without any changes to "WikidPadHooks.py". -- MichaelButscher

Last modified 8 years ago Last modified on Mar 18, 2010 7:28:24 PM

Attachments (5)

Download all attachments as: .zip