All,

The format() filter accepts sprintf() style format strings.

Almost. It doesn't accept format strings where the minimum width is calculated, and provided as a separate argument. I.e., you can't do the equivalent of this Perl:

  $out = sprintf("<%*s>\n", 6, "foo");
  print $out;   # Prints '<   foo>'

The TT equivalent:

  [% "foo" | format("<%*s>", 6) %]

Gives:

  Argument "foo" isn't numeric in sprintf at
     .../Template/Filters.pm line 418.
  Use of uninitialized value in sprintf at
     .../Template/Filters.pm line 418.

I'm aware of the

  [% USE padleft  = format('%-*s') %]
  [% USE padright = format('%*s')  %]
  [% padleft(10, a) %]-[% padright(10, b) %]

trick, but it's a bit of a hack.

Attached are two patches (against 2.15) -- one that adds this functionality to format(), along with associated documentation, the other that adds a test for the functionality.

N
--- Filters.pm.org      Wed Feb  7 17:32:59 2007
+++ Filters.pm  Wed Feb  7 17:32:08 2007
@@ -409,17 +409,30 @@
 #------------------------------------------------------------------------
 
 sub format_filter_factory {
-    my ($context, $format) = @_;
-    $format = '%s' unless defined $format;
+    my ($context, @format) = @_;
+    $format[0] = '%s' unless @format;
 
     return sub {
         my $text = shift;
         $text = '' unless defined $text;
-        return join("\n", map{ sprintf($format, $_) } split(/\n/, $text));
+
+        # If the format string contains args (e.g., to specify the width
+        # with %*s) then we need to pass the args explicitly as separate
+        # arguments.  This is because sprintf() is prototyped as '$@',
+        # so passing an array of format args as the first parameter will
+        # simply convert the array to a scalar (giving the size of the
+        # array), rather than using the array contents.
+
+        if(@format > 1) {
+            return join("\n", map{ sprintf($format[0], @format[1 .. $#format],
+                                           $_) } split(/\n/, $text));
+        } else {
+            return join("\n", map{ sprintf($format[0], $_) } split(/\n/, 
$text))
+;
+        }
     }
 }
 
-
 #------------------------------------------------------------------------
 # repeat_filter_factory($n)                        [% FILTER repeat(n) %]
 #
@@ -980,6 +993,15 @@
 
     <!-- This is a block of text filtered        -->
     <!-- through the above format.               -->
+
+If the printf() format expects extra parameters (e.g., C<%*s>) provide
+them in the argument list.
+
+    [% "foo" FILTER format('<%*s>', 6) %]
+
+output:
+
+    <   foo>
 
 =head2 upper
 
--- format.t.org        Wed Feb  7 17:34:31 2007
+++ format.t    Wed Feb  7 17:35:01 2007
@@ -84,4 +84,7 @@
 
 -- expect --
 alpha     -     bravo
-
+-- test --
+[% "foo" | format('<%*s>', 6) %]
+-- expect --
+<   foo>

Reply via email to