How do I find a comment with PPI and then insert code before it?
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');
精彩评论