|  | 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 [wiki:TracDev development resources] on the main project site. | 
          
            |  | 39 |  | 
          
            |  | 40 |  | 
          
            |  | 41 | == Implementation == | 
          
            |  | 42 |  | 
          
            |  | 43 | Here are 2 simple examples on how to create a Macro with [wiki:0.11 Trac 0.11] have a look at source:trunk/sample-plugins/Timestamp.py for an example that shows the difference between old style and new style macros and also source:trunk/wiki-macros/README which provides a little more insight about the transition. | 
          
            |  | 44 |  | 
          
            |  | 45 | === Macro without arguments === | 
          
            |  | 46 | It should be saved as `TimeStamp.py` as Trac will use the module name as the Macro name | 
          
            |  | 47 | {{{ | 
          
            |  | 48 | #!python | 
          
            |  | 49 | from datetime import datetime | 
          
            |  | 50 | # Note: since Trac 0.11, datetime objects are used internally | 
          
            |  | 51 |  | 
          
            |  | 52 | from genshi.builder import tag | 
          
            |  | 53 |  | 
          
            |  | 54 | from trac.util.datefmt import format_datetime, utc | 
          
            |  | 55 | from trac.wiki.macros import WikiMacroBase | 
          
            |  | 56 |  | 
          
            |  | 57 | class TimestampMacro(WikiMacroBase): | 
          
            |  | 58 | """Inserts the current time (in seconds) into the wiki page.""" | 
          
            |  | 59 |  | 
          
            |  | 60 | revision = "$Rev$" | 
          
            |  | 61 | url = "$URL$" | 
          
            |  | 62 |  | 
          
            |  | 63 | def expand_macro(self, formatter, name, args): | 
          
            |  | 64 | t = datetime.now(utc) | 
          
            |  | 65 | return tag.b(format_datetime(t, '%c')) | 
          
            |  | 66 | }}} | 
          
            |  | 67 |  | 
          
            |  | 68 | === Macro with arguments === | 
          
            |  | 69 | It should be saved as `HelloWorld.py` (in the plugins/ directory) as Trac will use the module name as the Macro name | 
          
            |  | 70 | {{{ | 
          
            |  | 71 | #!python | 
          
            |  | 72 | from trac.wiki.macros import WikiMacroBase | 
          
            |  | 73 |  | 
          
            |  | 74 | class HelloWorldMacro(WikiMacroBase): | 
          
            |  | 75 | """Simple HelloWorld macro. | 
          
            |  | 76 |  | 
          
            |  | 77 | Note that the name of the class is meaningful: | 
          
            |  | 78 | - it must end with "Macro" | 
          
            |  | 79 | - what comes before "Macro" ends up being the macro name | 
          
            |  | 80 |  | 
          
            |  | 81 | The documentation of the class (i.e. what you're reading) | 
          
            |  | 82 | will become the documentation of the macro, as shown by | 
          
            |  | 83 | the !MacroList macro (usually used in the WikiMacros page). | 
          
            |  | 84 | """ | 
          
            |  | 85 |  | 
          
            |  | 86 | revision = "$Rev$" | 
          
            |  | 87 | url = "$URL$" | 
          
            |  | 88 |  | 
          
            |  | 89 | def expand_macro(self, formatter, name, args): | 
          
            |  | 90 | """Return some output that will be displayed in the Wiki content. | 
          
            |  | 91 |  | 
          
            |  | 92 | `name` is the actual name of the macro (no surprise, here it'll be | 
          
            |  | 93 | `'HelloWorld'`), | 
          
            |  | 94 | `args` is the text enclosed in parenthesis at the call of the macro. | 
          
            |  | 95 | Note that if there are ''no'' parenthesis (like in, e.g. | 
          
            |  | 96 | [[HelloWorld]]), then `args` is `None`. | 
          
            |  | 97 | """ | 
          
            |  | 98 | return 'Hello World, args = ' + unicode(args) | 
          
            |  | 99 |  | 
          
            |  | 100 | # Note that there's no need to HTML escape the returned data, | 
          
            |  | 101 | # as the template engine (Genshi) will do it for us. | 
          
            |  | 102 | }}} | 
          
            |  | 103 |  | 
          
            |  | 104 |  | 
          
            |  | 105 | === {{{expand_macro}}} details === | 
          
            |  | 106 | {{{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}}}. | 
          
            |  | 107 |  | 
          
            |  | 108 | If your macro creates wiki markup instead of HTML, you can convert it to HTML like this: | 
          
            |  | 109 |  | 
          
            |  | 110 | {{{ | 
          
            |  | 111 | #!python | 
          
            |  | 112 | text = "whatever wiki markup you want, even containing other macros" | 
          
            |  | 113 | # Convert Wiki markup to HTML, new style | 
          
            |  | 114 | out = StringIO() | 
          
            |  | 115 | Formatter(self.env, formatter.context).format(text, out) | 
          
            |  | 116 | return Markup(out.getvalue()) | 
          
            |  | 117 | }}} |