|  | 1 | = Trac Macros = | 
                          |  | 2 |  | 
                          |  | 3 | [[PageOutline]] | 
                          |  | 4 |  | 
                          |  | 5 | Trac macros are plugins to extend the Trac engine with custom 'functions' written in Python. A macro inserts dynamic HTML data in any context supporting WikiFormatting. | 
                          |  | 6 |  | 
                          |  | 7 | Another kind of macros are WikiProcessors. They typically deal with alternate markup formats and representation of larger blocks of information (like source code highlighting). | 
                          |  | 8 |  | 
                          |  | 9 | == Using Macros == | 
                          |  | 10 | Macro calls are enclosed in two ''square brackets''. Like Python functions, macros can also have arguments, a comma separated list within parentheses. | 
                          |  | 11 |  | 
                          |  | 12 | Trac macros can also be written as TracPlugins. This gives them some capabilities that macros do not have, such as being able to directly access the HTTP request. | 
                          |  | 13 |  | 
                          |  | 14 | === Example === | 
                          |  | 15 |  | 
                          |  | 16 | A list of 3 most recently changed wiki pages starting with 'Trac': | 
                          |  | 17 |  | 
                          |  | 18 | {{{ | 
                          |  | 19 | [[RecentChanges(Trac,3)]] | 
                          |  | 20 | }}} | 
                          |  | 21 |  | 
                          |  | 22 | Display: | 
                          |  | 23 | [[RecentChanges(Trac,3)]] | 
                          |  | 24 |  | 
                          |  | 25 | == Available Macros == | 
                          |  | 26 |  | 
                          |  | 27 | ''Note that the following list will only contain the macro documentation if you've not enabled `-OO` optimizations, or not set the `PythonOptimize` option for [wiki:TracModPython mod_python].'' | 
                          |  | 28 |  | 
                          |  | 29 | [[MacroList]] | 
                          |  | 30 |  | 
                          |  | 31 | == Macros from around the world == | 
                          |  | 32 |  | 
                          |  | 33 | The [http://trac-hacks.org/ Trac Hacks] site provides a wide collection of macros and other Trac [TracPlugins plugins] contributed by the Trac community. If you're looking for new macros, or have written one that you'd like to share with the world, please don't hesitate to visit that site. | 
                          |  | 34 |  | 
                          |  | 35 | == Developing Custom Macros == | 
                          |  | 36 | Macros, like Trac itself, are written in the [http://python.org/ Python programming language]. | 
                          |  | 37 |  | 
                          |  | 38 | For more information about developing macros, see the [trac:TracDev development resources] on the main project site. | 
                          |  | 39 |  | 
                          |  | 40 |  | 
                          |  | 41 | == Implementation == | 
                          |  | 42 |  | 
                          |  | 43 | Here are 2 simple examples showing how to create a Macro with Trac 0.11. | 
                          |  | 44 |  | 
                          |  | 45 | Also, have a look at [trac:source:tags/trac-0.11/sample-plugins/Timestamp.py Timestamp.py] for an example that shows the difference between old style and new style macros and at the [trac:source:tags/trac-0.11/wiki-macros/README macros/README] which provides a little more insight about the transition. | 
                          |  | 46 |  | 
                          |  | 47 | === Macro without arguments === | 
                          |  | 48 | It should be saved as `TimeStamp.py` (in the TracEnvironment's `plugins/` directory) as Trac will use the module name as the Macro name. | 
                          |  | 49 | {{{ | 
                          |  | 50 | #!python | 
                          |  | 51 | from datetime import datetime | 
                          |  | 52 | # Note: since Trac 0.11, datetime objects are used internally | 
                          |  | 53 |  | 
                          |  | 54 | from genshi.builder import tag | 
                          |  | 55 |  | 
                          |  | 56 | from trac.util.datefmt import format_datetime, utc | 
                          |  | 57 | from trac.wiki.macros import WikiMacroBase | 
                          |  | 58 |  | 
                          |  | 59 | class TimeStampMacro(WikiMacroBase): | 
                          |  | 60 | """Inserts the current time (in seconds) into the wiki page.""" | 
                          |  | 61 |  | 
                          |  | 62 | revision = "$Rev$" | 
                          |  | 63 | url = "$URL$" | 
                          |  | 64 |  | 
                          |  | 65 | def expand_macro(self, formatter, name, args): | 
                          |  | 66 | t = datetime.now(utc) | 
                          |  | 67 | return tag.b(format_datetime(t, '%c')) | 
                          |  | 68 | }}} | 
                          |  | 69 |  | 
                          |  | 70 | === Macro with arguments === | 
                          |  | 71 | It should be saved as `HelloWorld.py` (in the TracEnvironment's `plugins/` directory) as Trac will use the module name as the Macro name. | 
                          |  | 72 | {{{ | 
                          |  | 73 | #!python | 
                          |  | 74 | from trac.wiki.macros import WikiMacroBase | 
                          |  | 75 |  | 
                          |  | 76 | class HelloWorldMacro(WikiMacroBase): | 
                          |  | 77 | """Simple HelloWorld macro. | 
                          |  | 78 |  | 
                          |  | 79 | Note that the name of the class is meaningful: | 
                          |  | 80 | - it must end with "Macro" | 
                          |  | 81 | - what comes before "Macro" ends up being the macro name | 
                          |  | 82 |  | 
                          |  | 83 | The documentation of the class (i.e. what you're reading) | 
                          |  | 84 | will become the documentation of the macro, as shown by | 
                          |  | 85 | the !MacroList macro (usually used in the WikiMacros page). | 
                          |  | 86 | """ | 
                          |  | 87 |  | 
                          |  | 88 | revision = "$Rev$" | 
                          |  | 89 | url = "$URL$" | 
                          |  | 90 |  | 
                          |  | 91 | def expand_macro(self, formatter, name, args): | 
                          |  | 92 | """Return some output that will be displayed in the Wiki content. | 
                          |  | 93 |  | 
                          |  | 94 | `name` is the actual name of the macro (no surprise, here it'll be | 
                          |  | 95 | `'HelloWorld'`), | 
                          |  | 96 | `args` is the text enclosed in parenthesis at the call of the macro. | 
                          |  | 97 | Note that if there are ''no'' parenthesis (like in, e.g. | 
                          |  | 98 | [[HelloWorld]]), then `args` is `None`. | 
                          |  | 99 | """ | 
                          |  | 100 | return 'Hello World, args = ' + unicode(args) | 
                          |  | 101 |  | 
                          |  | 102 | # Note that there's no need to HTML escape the returned data, | 
                          |  | 103 | # as the template engine (Genshi) will do it for us. | 
                          |  | 104 | }}} | 
                          |  | 105 |  | 
                          |  | 106 |  | 
                          |  | 107 | === {{{expand_macro}}} details === | 
                          |  | 108 | {{{expand_macro}}} should return either a simple Python string which will be interpreted as HTML, or preferably a Markup object (use {{{from trac.util.html import Markup}}}).  {{{Markup(string)}}} just annotates the string so the renderer will render the HTML string as-is with no escaping. You will also need to import Formatter using {{{from trac.wiki import Formatter}}}. | 
                          |  | 109 |  | 
                          |  | 110 | If your macro creates wiki markup instead of HTML, you can convert it to HTML like this: | 
                          |  | 111 |  | 
                          |  | 112 | {{{ | 
                          |  | 113 | #!python | 
                          |  | 114 | text = "whatever wiki markup you want, even containing other macros" | 
                          |  | 115 | # Convert Wiki markup to HTML, new style | 
                          |  | 116 | out = StringIO() | 
                          |  | 117 | Formatter(self.env, formatter.context).format(text, out) | 
                          |  | 118 | return Markup(out.getvalue()) | 
                          |  | 119 | }}} |