Macro-Micro

 view release on metacpan or  search on metacpan

lib/Macro/Micro.pm  view on Meta::CPAN

use strict;
use warnings;
package Macro::Micro 0.055;
# ABSTRACT: really simple templating for really simple templates

use Carp ();

#pod =head1 SYNOPSIS
#pod
#pod   use Macro::Micro;
#pod
#pod   my $expander = Macro::Micro->new;
#pod
#pod   $expander->register_macros(
#pod     ALIGNMENT => "Lawful Good",
#pod     HEIGHT    => sub {
#pod       my ($macro, $object, $stash) = @_;
#pod       $stash->{race}->avg_height;
#pod     },
#pod   );
#pod
#pod   $expander->expand_macros_in($character, { race => $human_obj });
#pod
#pod   # character is now a Lawful Good, 5' 6" human
#pod
#pod =head1 DESCRIPTION
#pod
#pod This module performs very basic expansion of macros in text, with a very basic
#pod concept of context and lazy evaluation.
#pod
#pod =method new
#pod
#pod   my $mm = Macro::Micro->new(%arg);
#pod
#pod This method creates a new Macro::Micro object.
#pod
#pod There is only one valid argument:
#pod
#pod   macro_format - this is the format for macros; see the macro_format method
#pod
#pod =cut

my $DEFAULT_MACRO_FORMAT = qr/(?<!\\)([\[<] (\w+) [>\]])/x;

sub new {
  my ($class, %arg) = @_;

  my $self = bless { } => $class;

  $arg{macro_format} = $DEFAULT_MACRO_FORMAT unless $arg{macro_format};

  $self->macro_format($arg{macro_format});

  return $self;
}

#pod =method macro_format
#pod
#pod   $mm->macro_format( qr/.../ );
#pod
#pod This method gets or sets the macro format regexp for the expander.
#pod
#pod The format must be a reference to a regular expression, and should have two
#pod capture groups.  The first should return the entire string to be replaced in
#pod the text, and the second the name of the macro found.
#pod
#pod The default macro format is:  C<< qr/([\[<] (\w+) [>\]])/x >>
#pod
#pod In other words: a probably-valid-identiifer inside angled or square backets.
#pod
#pod =cut

sub macro_format {
  my $self = shift;

  return $self->{macro_format} unless @_;

  my $macro_format = shift;
  Carp::croak "macro format must be a regexp reference"
    unless ref $macro_format eq 'Regexp';

  $self->{macro_format} = $macro_format;
}

#pod =method register_macros
#pod
#pod   $mm->register_macros($name => $value, ... );
#pod
#pod This method register one or more macros for later expansion.  The macro names
#pod must be either strings or a references to regular expression.  The values may
#pod be either strings or references to code.
#pod
#pod These macros may later be used for expansion by C<L</expand_macros>>.
#pod
#pod =cut

sub register_macros {
  my ($self, @macros) = @_;

  for (my $i = 0; $i < @macros; $i += 2) {
    my ($name, $value) = @macros[ $i, $i+1 ];
    Carp::croak "macro value must be a string or code reference"
      if (ref $value) and (ref $value ne 'CODE');

    if (not ref $name) {
      $self->{macro}{$name} = $value;
    } elsif (ref $name eq 'Regexp') {
      $self->{macro_regexp}{$name} = [ $name, $value ];

lib/Macro/Micro.pm  view on Meta::CPAN

      return $cached{ $_[0] } if defined $cached{ $_[0] };

      my $macro = $self->get_macro($_[1]);

      $cached{ $_[0] } = defined $macro
                       ? ref $macro
                         ? $macro->($_[1], $_[2], $stash)||'' : $macro
                       : $_[0];

      return $cached{ $_[0] };
    };
  } else {
    return sub {
      return $cached{ $_[0] } if defined $cached{ $_[0] };

      my $macro = $self->{macro}{ $_[1] };

      $cached{ $_[0] } = defined $macro
                       ? ref $macro
                         ? $macro->($_[1], $_[2], $stash)||'' : $macro
                       : $_[0];

      return $cached{ $_[0] };
    };
  }
}


#pod =method study
#pod
#pod   my $template = $expander->study($text);
#pod
#pod Given a string, this returns an object which can be used as an argument to
#pod C<expand_macros>.  Macro::Micro will find and mark the locations of macros in
#pod the text so that calls to expand the macros will not need to search the text.
#pod
#pod =cut

sub study {
  my ($self, $text) = @_;

  my $macro_format = $self->macro_format;

  my @total;

  my $pos;
  while ($text =~ m/\G(.*?)$macro_format/gsm) {
    my ($snippet, $whole, $name) = ($1, $2, $3);
    push @total, (length $snippet ? $snippet : ()),
                 ($whole ? [ $whole, $name ] : ());
    $pos = pos $text;
  }

  push @total, substr $text, $pos if defined $pos;

  return Macro::Micro::Template->_new(\$text, \@total);
}

{
  package Macro::Micro::Template 0.055;
  sub _new   { bless [ $_[1], $_[2] ] => $_[0] }
  sub _parts { @{ $_[0][1] } }
  sub _text  {    $_[0][0]   }
}

"[MAGIC_TRUE_VALUE]";

__END__

=pod

=encoding UTF-8

=head1 NAME

Macro::Micro - really simple templating for really simple templates

=head1 VERSION

version 0.055

=head1 SYNOPSIS

  use Macro::Micro;

  my $expander = Macro::Micro->new;

  $expander->register_macros(
    ALIGNMENT => "Lawful Good",
    HEIGHT    => sub {
      my ($macro, $object, $stash) = @_;
      $stash->{race}->avg_height;
    },
  );

  $expander->expand_macros_in($character, { race => $human_obj });

  # character is now a Lawful Good, 5' 6" human

=head1 DESCRIPTION

This module performs very basic expansion of macros in text, with a very basic
concept of context and lazy evaluation.

=head1 PERL VERSION

This library should run on perls released even a long time ago.  It should work
on any version of perl released in the last five years.

Although it may work on older versions of perl, no guarantee is made that the
minimum required version will not be increased.  The version may be increased
for any reason, and there is no promise that patches will be accepted to lower
the minimum required perl.

=head1 METHODS

=head2 new

  my $mm = Macro::Micro->new(%arg);

This method creates a new Macro::Micro object.



( run in 0.238 second using v1.01-cache-2.11-cpan-4505f990765 )