| t | | t | |
| <table align="right"><tr><td><div class="toc"> | | |
| Contents: | | |
| <ul> | | |
| <li><a href="#Introduction">Introduction</a></li> | | |
| <li><a href="#Name_and_Location">Name and Location</a></li> | | |
| <li><a href="#Declaration_in_a_TBWiki_Page">Declaration in a TBWiki Page</a></li> | | |
| <li><a href="#Interface_from_TBWiki_to_the_macro">Interface from TBWiki to the macro</a></li> | | |
| <ul> | | |
| <li><a href="#main()_function">main() function</a></li> | | |
| <ul> | | |
| <li><a href="#Example_main()">Example main()</a></li> | | |
| <li><a href="#Example_declaration_(of_Error_macro)">Example declaration (of Error macro)</a></li> | | |
| </ul> | | |
| <li><a href="#help()_and_help_oneline()_actions">help() and help_oneline() actions</a></li> | | |
| <li><a href="#macro_side_effects_or_operations">macro side effects or operations</a></li> | | |
| </ul> | | |
| <li><a href="#Interface_from_the_macro_to_TBWiki">Interface from the macro to TBWiki</a></li> | | |
| <ul> | | |
| <li><a href="#request_object">request object</a></li> | | |
| <li><a href="#req_functions">req functions</a></li> | | |
| <li><a href="#tbwiki_functions">tbwiki functions</a></li> | | |
| <li><a href="#return_value">return value</a></li> | | |
| </ul> | | |
| <li><a href="#Basic_Sample_-_'Include'_macro">Basic Sample - 'Include' macro</a></li> | | |
| <ul> | | |
| <li><a href="#macro_code">macro code</a></li> | | |
| <li><a href="#processor_invocation">processor invocation</a></li> | | |
| <li><a href="#macro_result">macro result</a></li> | | |
| </ul> | | |
| </ul> | | |
| </div></td></tr></table> | | |
| <h1><a name="Introduction">Introduction</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Introduction">edit section</a>]</font></span> | | |
| </h1> | | |
| TBWiki supports two kinds of extension mechanisms: "macros" and "processors". | | |
| <p> | | |
| 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. | | |
| <p> | | |
| 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. | | |
| <p> | | |
| <h1><a name="Name_and_Location">Name and Location</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Name_and_Location">edit section</a>]</font></span> | | |
| </h1> | | |
| By convention, the name of a macro is in CamelCase (words strung | | |
| together with the first letter of each word capitalized). | | |
| <p> | | |
| 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 | | |
| <p> | | |
| <code><data_dir_for_this_wiki>/plugin/MacroFoo.py</code> | | |
| <p> | | |
| Often, the plugin directory will merely be a symlink to the main plugin | | |
| directory offered by the tbwiki engine (e.g. at <code><tbwiki_dir>/cgi-bin/plugins</code>) | | |
| <p> | | |
| <h1><a name="Declaration_in_a_TBWiki_Page">Declaration in a TBWiki Page</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Declaration_in_a_TBWiki_Page">edit section</a>]</font></span> | | |
| </h1> | | |
| A macro is declared on a tbwiki page on a single line with the syntax: | | |
| <pre> | | |
| {{Foo}} | | |
| </pre> | | |
| <p> | | |
| 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 <code>plugins/MacroFoo.py</code> module. | | |
| <p> | | |
| Macro arguments (if any) can be specified in the macro declaration, using | | |
| parenthesis, like so: | | |
| <pre> | | |
| {{Foo(arg1, arg2, etc.)}} | | |
| </pre> | | |
| <p> | | |
| 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. | | |
| <p> | | |
| Note that macros can be declared on a line by themselves, or embedded | | |
| inline along with other markup, like so: | | |
| <pre> | | |
| This is a line with an embedded {{Foo(arg1)}} macro | | |
| </pre> | | |
| <p> | | |
| <h1><a name="Interface_from_TBWiki_to_the_macro">Interface from TBWiki to the macro</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Interface_from_TBWiki_to_the_macro">edit section</a>]</font></span> | | |
| </h1> | | |
| 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. | | |
| <p> | | |
| <h2><a name="main()_function">main() function</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=main()_function">edit section</a>]</font></span> | | |
| </h2> | | |
| 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. | | |
| <p> | | |
| This <code>main</code> function takes two arguments, which are | | |
| the request object and the args string. | | |
| <p> | | |
| 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. | | |
| <p> | | |
| <h3><a name="Example_main()">Example main()</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Example_main()">edit section</a>]</font></span> | | |
| </h3> | | |
| Here is an example definition of <code>main()</code> for a hypothetical macro called <code>MacroError.py</code>: | | |
| <p> | | |
| <pre> | | |
| def main(req, args=""): | | |
| # do something with args | | |
| msg = "Error: " + args | | |
| req.debug_log(msg) | | |
| html = req.html_error(msg) | | |
| return html | | |
| </pre> | | |
| <p> | | |
| 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 <code>html_error()</code> function to color the indicated text | | |
| red, and returns the transformed string to TBWiki for inclusion | | |
| on the page. | | |
| <p> | | |
| <h3><a name="Example_declaration_(of_Error_macro)">Example declaration (of Error macro)</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Example_declaration_(of_Error_macro)">edit section</a>]</font></span> | | |
| </h3> | | |
| The example <code>Error</code> macro might be invoked like so: | | |
| <p> | | |
| <pre> | | |
| The following text should be red: {{Error(what happened!!)}} Back to normal. | | |
| </pre> | | |
| <p> | | |
| The text of the macro declaration on a page is replaced | | |
| with the result of executing the macro code, when the page is rendered. | | |
| <p> | | |
| This might result in the following line appearing on the page: | | |
| <p> | | |
| The following text should be red: <font color="red">Error: what happened!! </font> Back to normal. | | |
| <p> | | |
| <hr size=2> | | |
| <p> | | |
| If no arguments are provided in the macro declaration, like this: | | |
| <pre> | | |
| {{Error}} | | |
| </pre> | | |
| <p> | | |
| then the value of the "args" argument to <code>main()</code> will be the empty string. | | |
| <p> | | |
| <h2><a name="help()_and_help_oneline()_actions">help() and help_oneline() actions</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=help()_and_help_oneline()_actions">edit section</a>]</font></span> | | |
| </h2> | | |
| 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 | | |
| <p> | | |
| 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. | | |
| <p> | | |
| <h2><a name="macro_side_effects_or_operations">macro side effects or operations</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=macro_side_effects_or_operations">edit section</a>]</font></span> | | |
| </h2> | | |
| 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. | | |
| <p> | | |
| For more complicated processing, consider using a "processor" | | |
| instead of a macro. See <a href="/tbwiki/DocProcessors">DocProcessors</a>. | | |
| <p> | | |
| <h1><a name="Interface_from_the_macro_to_TBWiki">Interface from the macro to TBWiki</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Interface_from_the_macro_to_TBWiki">edit section</a>]</font></span> | | |
| </h1> | | |
| <h2><a name="request_object">request object</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=request_object">edit section</a>]</font></span> | | |
| </h2> | | |
| 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. | | |
| <p> | | |
| Here are some functions and fields that a macro might use: | | |
| <p> | | |
| <h2><a name="req_functions">req functions</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=req_functions">edit section</a>]</font></span> | | |
| </h2> | | |
| Some useful functions of the request object are: | | |
| <ul><li>req.read_page(page_name) - read a page of the wiki | | |
| </ul> | | |
| <p> | | |
| <ul><li>req.form = the CGI form data for the request (in the format provided by the python cgi module) | | |
| <li>req.add_to_message = a function to add to the status message for the page. | | |
| This is often used for debugging purposes, since it appears separately from the | | |
| page content | | |
| <li>req.page_filename = filename (including full path) of the requested page | | |
| <li>req.page_name = name of the requested page | | |
| <li>req.config.data_dir = location in the local file system where the data | | |
| pages are located. | | |
| <li>req.config = configuration settings for this wiki | | |
| <li>req.data = data values (and data value functions) for this wiki | | |
| <ul><li>req.data.version - version of the tbwiki engine | | |
| <li>req.data.asctime - current time in ascii (human readable) format | | |
| </ul><li>req.block_to_html - convert a block of text from tbwiki markup to HTML | | |
| </ul> | | |
| <p> | | |
| <h2><a name="tbwiki_functions">tbwiki functions</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=tbwiki_functions">edit section</a>]</font></span> | | |
| </h2> | | |
| 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: | | |
| <ul><li>tbwiki_engine.make_url() | | |
| <li>tbiki_engine.html_error() | | |
| <li>tbiki_engine.parse_state = state used for processing lines during page parsing | | |
| <li>tbiki_engine.show_line() = function used to parse a line of TBWIKI-format text and | | |
| convert it into HTML output (which is printed by show_line) | | |
| </ul> | | |
| <p> | | |
| <h2><a name="return_value">return value</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=return_value">edit section</a>]</font></span> | | |
| </h2> | | |
| The 'main function should return a single string consisting of HTML | | |
| to be output as part of the returned page HTML. | | |
| <p> | | |
| If you want tbwiki to process markup text for you into HTML, | | |
| you can call <code>req.block_to_html(content)</code>, and return the | | |
| result of that. | | |
| <p> | | |
| <h1><a name="Basic_Sample_-_'Include'_macro">Basic Sample - 'Include' macro</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=Basic_Sample_-_'Include'_macro">edit section</a>]</font></span> | | |
| </h1> | | |
| 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. | | |
| <p> | | |
| <h2><a name="macro_code">macro code</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=macro_code">edit section</a>]</font></span> | | |
| </h2> | | |
| This would be in the file MacroInclude.py | | |
| <pre> | | |
| 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 | | |
| </pre> | | |
| <p> | | |
| <h2><a name="processor_invocation">processor invocation</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=processor_invocation">edit section</a>]</font></span> | | |
| </h2> | | |
| To use this processor, a user would place the following on a page: | | |
| <p> | | |
| <pre> | | |
| {{Include(other_page)}} | | |
| </pre> | | |
| <p> | | |
| Assuming the entire page containing the macro looked like this: | | |
| <p> | | |
| <ul><div style="background-color:#ffffe0; padding:5px; border-style: solid solid solid solid; border-width: 1px 1px 1px 1px;"> | | |
| <pre>This is data from the page. | | |
| | | |
| {{Include(other_page)}} | | |
| | | |
| This is more data from the first page.</pre></div></ul> | | |
| | | |
| <p> | | |
| And assuming 'other_page' had this content: | | |
| <p> | | |
| <ul><div style="background-color:#ffffe0; padding:5px; border-style: solid solid solid solid; border-width: 1px 1px 1px 1px;"> | | |
| <pre>This is content from other_page.</pre></div></ul> | | |
| | | |
| <p> | | |
| <h2><a name="macro_result">macro result</a> | | |
| <span align=right class="section_edit_link">[<a href="/tbwiki/DocMacros?action=edit§ion=macro_result">edit section</a>]</font></span> | | |
| </h2> | | |
| Here is what the resulting output would look like on the page: | | |
| <p> | | |
| <ul><div style="background-color:#ffffe0; padding:5px; border-style: solid solid solid solid; border-width: 1px 1px 1px 1px;"> | | |
| <pre>This is data from the page. | | |
| | | |
| This is content from other_page. | | |
| | | |
| This is more data from the first page.</pre></div></ul> | | |
| | | |
| <p> | | |