Skip Menu |

This queue is for tickets about the Text-Trac CPAN distribution.

Report information
The Basics
Id: 22635
Status: resolved
Priority: 0/
Queue: Text-Trac

People
Owner: Nobody in particular
Requestors: GTERMARS [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Feature request: Macro support
To go along with my previous feature request for TracLinks, it'd also be nice to have the ability to create WikiMacros to plug in to Text::Trac. Here's my initial thoughts... --- Using the list of Wiki Macros provided by Trac as an example, I could see the classes structure themselves like: Text::Trac::Macro::Timestamp Text::Trac::Macro::HelloWorld Text::Trac::Macro::TicketQuery Text::Trac::Macro::TitleIndex ... Each macro package would contain a single function in it, "execute()", which would accept all of the args that were parsed out of the macro call in the Wiki text. E.g. package Text::Trac::Macro::Timestamp; sub execute { return scalar localtime(); } or package Text::Trac::Macro::HelloWorld; sub execute { return 'Hello World, args = ' . @_; } --- Thoughts??
I see that you've added some preliminary macro support in SVN Gosuke, and had an initial patchset and some comments to provide you with... 1) I've attached a test suite (t/02-macros.t, t/lib/TestMacro.pm) and patch (macros.diff) to this message which provide the following changes: - uses Text::ParseWords to split apart the arguments, which allows for them to be quoted and contain embedded commas. Text::ParseWords is part of Perl core, so there shouldn't be any issue with using this as an added dependency - updated pattern regex which allows for the ")" character to be included in one of the arguments (e.g. [[HelloWorld("func(arg)")]]) - allows for macros to live outside of the "Text::Trac::Macro::" namespace, by letting the name of the macro be the name of the Perl package. Looks under "Text::Trac::Macro::*" first, but if we don't find the macro there we look for it elsewhere in the Perl namespace. 2) I'm not sure that "exec()" is going to be the best name for the function; its the same name as a function in Perl core (which we probably don't want to invoke accidentally). Perhaps renaming the function to "execute()" or "trac_macro()"?? 3) Now that I've played with this a bit, I'm also thinking that it might be worthwhile to pass the context in to the macro when its invoked. Although the "Timestamp" and "HelloWorld" macros wouldn't need any of this information, I could see that other macros might want access to this information (e.g. for base URLs to generate)
Index: lib/Text/Trac/Macro.pm =================================================================== --- lib/Text/Trac/Macro.pm (revision 325) +++ lib/Text/Trac/Macro.pm (working copy) @@ -2,10 +2,11 @@ use strict; use base qw(Text::Trac::InlineNode); use UNIVERSAL::require; +use Text::ParseWords qw(quotewords); sub init { my $self = shift; - $self->pattern(qr/\[\[(\w+)\(?([^)]*)\)?\]\]/); + $self->pattern(qr/\[\[(\w+) (?:\((.+?)\))? \]\]/x); return $self; } @@ -15,18 +16,18 @@ my $pattern = $self->pattern; $l =~ $pattern or return $l; - my @args = split ',', $2 if $2; - for ( @args ) { - $_ =~ s/^\s+//; - $_ =~ s/\s+$//; + my $macro = $1; + my @args = quotewords( ',\s*', 0, $2 ) if $2; + map { s/^\s+|\s+$//g } @args; + + foreach my $class ("Text::Trac::Macro::$macro", $macro) { + if ($class->require) { + my $result = $class->exec(@args) || ''; + $l =~ s{$pattern}{$result}xmsg; + last; + } } - my $class = "Text::Trac::Macro::$1"; - $class->require; - my $result = $class->exec(@args) || ''; - - $l =~ s{$pattern}{$result}xmsg; - return $l; }
use strict; use warnings; use lib 't/lib'; use Test::Base; use Text::Trac; delimiters('###'); plan tests => 1 * blocks; my $trac = Text::Trac->new(); sub parse { $trac->parse(@_); $trac->html; } filters { input => 'parse', expected => 'chomp' }; run_is 'input' => 'expected'; __DATA__ ### macro with no arguments --- input [[HelloWorld]] --- expected <p> Hello World, args = </p> ### macro with quoted arguments --- input [[HelloWorld( "one, one", "two, two", 'three, three' )]] --- expected <p> Hello World, args = one, one, two, two, three, three </p> ### macro with embedded terminators --- input [[HelloWorld( func(arg), ]] )]] --- expected <p> Hello World, args = func(arg), ]] </p> ### macros with extra ws aren't valid --- input [[ HelloWorld(foo) ]] --- expected <p> [[ HelloWorld(foo) ]] </p> ### unknown macro doesn't die --- input [[TheUnknownMacro]] --- expected <p> [[TheUnknownMacro]] </p> ### macros outside of Text::Trac::Macro:: are ok too --- input [[TestMacro]] --- expected <p> testing, testing, one, two, three... </p>
package TestMacro; sub exec { return 'testing, testing, one, two, three...'; } 1;
Thanks for your patches and comments. I've applied your patches and comments to the module on my svn repos. Please check it. Thanks a lot. -- Gosuke Miyashita