DocMacros

Introduction [edit section]

TBWiki supports two kinds of extension mechanisms: "macros" and "processors".

There are a few builtin macros, but add-on macros and processors can be created and are "run" when a page is parsed and sent by TBWiki.

The function of both of these extension mechanisms (or plugins) is to allow for dynamic creation of page content at the time a page is read by a user. Thus, these act like a kind of embedded CGI-script inside of the TBWiki framework.

Name and Location [edit section]

By convention, the name of a macro is in CamelCase (words strung together with the first letter of each word capitalized).

Plugin macros are placed in the data/plugin directory. They are python files and must have a filename starting with the "Macro", then the macro name, and ending in the extension ".py". For example the "Foo" macro would have the path and filename

<data_dir_for_this_wiki>/plugin/MacroFoo.py

Often, the plugin directory will merely be a symlink to the main plugin directory offered by the tbwiki engine (e.g. at <tbwiki_dir>/cgi-bin/plugins)

Declaration in a TBWiki Page [edit section]

A macro is declared on a tbwiki page on a single line with the syntax:
{{Foo}}

The macro name in the declaration must match the name part of the filename for the macro python module in the plugin directory. Thus, the macro "Foo" above would invoke code in the plugins/MacroFoo.py module.

Macro arguments (if any) can be specified in the macro declaration, using parenthesis, like so:

{{Foo(arg1, arg2, etc.)}}

TBwiki delivers the arguments as a single string, consisting of exactly the characters inside the parens. Parsing this string into separate arguments (e.g. splitting it on comma, and eliminating white space) are performed by the macro itself.

Note that macros can be declared on a line by themselves, or embedded inline along with other markup, like so:

   This is a line with an embedded {{Foo(arg1)}} macro

Interface from TBWiki to the macro [edit section]

A macro must be an importable python module, with some specifically-named function definitions. The TBWiki calls functions in the macro to perform actions, usually resulting in the transformation or creation of new content that will be returned to the user as part of the page where the macro is declared.

main() function [edit section]

A macro must define a function named "main". As a page is rendered by TBWiki, when the macro declaration is encountered in the wiki page, TBWiki calls the 'main' function to invoke the macro functionality.

This main function takes two arguments, which are the request object and the args string.

The macro performs its operation, possibly using the information and functions provided in the request object and its argument string, and returns a string of HTML data, for output as part of the returned page.

Example main() [edit section]

Here is an example definition of main() for a hypothetical macro called MacroError.py:

def main(req, args=""):
    # do something with args
    msg = "Error: " + args
    req.debug_log(msg)
    html = req.html_error(msg)
    return html

In this case, the macro creates an error message by prepending the string "Error:" to the macro argument. Then it logs the error to the debug log, and calls html_error() function to color the indicated text red, and returns the transformed string to TBWiki for inclusion on the page.

Example declaration (of Error macro) [edit section]

The example Error macro might be invoked like so:

  The following text should be red: {{Error(what happened!!)}}  Back to normal.

The text of the macro declaration on a page is replaced with the result of executing the macro code, when the page is rendered.

This might result in the following line appearing on the page:

The following text should be red: Error: what happened!! Back to normal.


If no arguments are provided in the macro declaration, like this:

 {{Error}}

then the value of the "args" argument to main() will be the empty string.

help() and help_oneline() actions [edit section]

If a macro defines the special functions "help" and "help_oneline", then the system can provide online help for the processor, from a page displaying the SystemInfo. This function is accessed via a URL with the name: <page_url>?action=<macro_name>.help

The 'help' function should return text in html format with helpful information about the macro. The 'help_oneline' function should return a single-line description of the processor.

macro side effects or operations [edit section]

Often, a macro is used to place newly-created or transformed content onto a page, during rendering. But it may also be used to perform some operation, such as logging, counting items, or performing some processing on the wiki or the site where it resides.

For more complicated processing, consider using a "processor" instead of a macro. See DocProcessors.

Interface from the macro to TBWiki [edit section]

request object [edit section]

The request object has all the data available to tbwiki about the request for this page. This includes the page_name, the entire tbwiki config, and other stuff.

Here are some functions and fields that a macro might use:

req functions [edit section]

Some useful functions of the request object are:

tbwiki functions [edit section]

You can also import the tbwiki_engine module, to access other helper functions for use by the macro plugin. Here are some that are helpful:

return value [edit section]

The 'main function should return a single string consisting of HTML to be output as part of the returned page HTML.

If you want tbwiki to process markup text for you into HTML, you can call req.block_to_html(content), and return the result of that.

Basic Sample - 'Include' macro [edit section]

Here is sample code for a very simple macro which includes the content of another wiki page in the rendered output for the page with the macro.

macro code [edit section]

This would be in the file MacroInclude.py
import tbwiki_engine

def main(req, args=""):
    page_name = args[0]
    page_data = req.read_page(page_name)

    html = tbwiki_engine.block_to_html(req, page_data)
    html += tbwiki_engine.html_close(req.state)
    return html

processor invocation [edit section]

To use this processor, a user would place the following on a page:

{{Include(other_page)}}

Assuming the entire page containing the macro looked like this:

And assuming 'other_page' had this content:

macro result [edit section]

Here is what the resulting output would look like on the page: