开发者

How do I find a comment with PPI and then insert code before it?

开发者 https://www.devze.com 2023-01-08 21:20 出处:网络
I\'m trying to find the comment # VERSION in a perl source file. I then want to insert the version before the comment (or in place of doesn\'t matter). Could anyone tell me the right way to do this wi

I'm trying to find the comment # VERSION in a perl source file. I then want to insert the version before the comment (or in place of doesn't matter). Could anyone tell me the right way to do this with PPI?

before

use strict;
use warnings;
package My::Package;
# VERSION
...

after

use strict;
use warnings;
package My::Package;
our $VERSION = 0.1;# VERSION
...

maintaining the # VERSION in the end result is optional

I actually have a couple of ideas on how to find # VERSION but one is a regex of a serialized ppi doc which doesn't seem right, and the other is using find_first on a Comment but if it's not the first I'm not sure what开发者_如何学C to do.

Updated code This seems closer to a correct solution since it only looks at the comments. but I'm not sure how to use or really how to create a new variable.

#!/usr/bin/env perl
use 5.012;
use strict;
use warnings;

use PPI;

my $ppi = PPI::Document->new('test.pm');

my $comments = $ppi->find('PPI::Token::Comment');

my $version = PPI::Statement::Variable->new;

foreach ( @{$comments} ) {
    if ( /^\s*#\s+VERSION\b$/ ) {
        $_->replace($version);
    }
}

UPDATE

The answer to this question became the foundation for DZP::OurPkgVersion


Here's some code that does something like what you describe - It'll get you started anyway. It's edited from Catalyst::Helper::AuthDBIC (source), which is a full example of working with PPI (although bits of it may not be best practices):

sub make_model {
    ### snip some stuff
    my $module = "lib/$user_schema_path.pm";
    my $doc = PPI::Document->new($module);
    my $digest_code = # some code
    my $comments = $doc->find(
        sub { $_[1]->isa('PPI::Token::Comment')}
    );
    my $last_comment = $comments->[$#{$comments}];
    $last_comment->set_content($digest_code);
    $doc->save($module);
}

I suppose in your case you grab the $comments arrayref and modify the first item that matches /VERSION/ with the replacement content.

And here's the final code courtesy of the poster:

#!/usr/bin/env perl
use 5.012;
use warnings;

use PPI;

my $ppi = PPI::Document->new('test.pm');

my $comments = $ppi->find('PPI::Token::Comment');

my $version = 0.01;

my $_;
foreach ( @{$comments} ) {
    if ( /^(\s*)(#\s+VERSION\b)$/ ) {
        my $code = "$1" . 'our $VERSION = ' . "$version;$2\n";
        $_->set_content("$code");
    }
}
$ppi->save('test1.pm');
0

精彩评论

暂无评论...
验证码 换一张
取 消