perlmethodsdocumentationdist-zilla

How to define multiple subsections for methods with Pod::Weaver?


I have some Moose classes that define several small groups of related methods. I would like to make these groups obvious in the package POD.

I use Dist::Zilla and Pod::Weaver with the =method command. Is it possible to insert some =head2-like commands between my =method commands to achieve the desired effect?


Solution

  • I wrote a post on how I did it for Redis::Client here: Falling in Love with Pod::Weaver.

    The simplest thing to do is add custom Collect directives to your weaver.ini and organize your methods by giving each type a different custom POD command, like so:

    [Collect / FOO METHODS]
    command = foo_method
    
    [Collect / BAR METHODS]
    command = bar_method
    
    [Collect / BAZ METHODS]
    command = baz_method
    

    Then write your POD like this

    =foo_method blah blah
    

    and Weaver will automatically collect them under their own =head1.

    If you want to do something more complicated than that, you can write your own Pod::Weaver plugin. The gist is to search through the parsed POD for a custom command name and transform them by returning Pod::Elemental objects. Here's the plugin I wrote:

    package Pod::Weaver::Plugin::RedisLinks;
    
    # ABSTRACT: Add links to Redis documentation
    
    use Moose;
    with 'Pod::Weaver::Role::Transformer';
    
    use Data::Dumper;
    use Scalar::Util 'blessed';
    use aliased 'Pod::Elemental::Element::Pod5::Ordinary';
    
    sub transform_document {
        my ( $self, $doc ) = @_;
    
        my @children = $doc->children;
    
        my @new_children;
        foreach my $child( @{ $children[0] } ) {
            if ( $child->can( 'command' )
                 && $child->command =~ /^(?:key|str|list|hash|set|zset|conn|serv)_method/ ) {
                my $meth_name = $child->content;
                $meth_name =~ s/^\s*?(\S+)\s*$/$1/;
    
                my $cmd_name = uc $meth_name;
                $cmd_name =~ tr/_/ /;
    
                my $link_name = $meth_name;
                $link_name =~ tr/_/-/;
    
                my $new_para = Ordinary->new(
                    content => sprintf 'Redis L<%s|%s> command.',
                               $cmd_name, 'http://redis.io/commands/' . $link_name );
    
                push @new_children, $child, $new_para;
                next;
            }
    
            push @new_children, $child;
        }
    
        $doc->children( \@new_children );
    }
    
    __PACKAGE__->meta->make_immutable;
    
    1;
    

    The transform_document method gets passed the parsed document as a parameter. It then goes through the top-level commands looking for elements labeled /^(?:key|str|list|hash|set|zset|conn|serv)_method/, munges the name a bit, and then builds a new POD paragraph containing the formatted POD content that I want.