Как найти комментарий с помощью PPI, а затем вставить код перед ним? - PullRequest
4 голосов
/ 27 июля 2010

Я пытаюсь найти комментарий # VERSION в исходном файле perl. Затем я хочу вставить версию перед комментарием (или вместо того, чтобы иметь значение). Может кто-нибудь сказать мне правильный способ сделать это с PPI ?

до

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

после

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

сохранение # VERSION в конечном результате необязательно

На самом деле у меня есть пара идей о том, как найти # VERSION, но одно из них является регулярным выражением сериализованного документа ppi, которое кажется неправильным, а другое использует find_first для Комментария, но если это не первое, то я ' Я не уверен, что делать.

Обновленный код Кажется, это ближе к правильному решению, так как он смотрит только на комментарии. но я не уверен, как использовать или создать новую переменную.

#!/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

Ответ на этот вопрос стал основой для DZP :: OurPkgVersion

1 Ответ

4 голосов
/ 28 июля 2010

Вот некоторый код, который делает что-то похожее на то, что вы описываете.Он отредактирован из Catalyst :: Helper :: AuthDBIC ( source ), который является полным примером работы с PPI (хотя некоторые его фрагменты могут быть не лучшими практиками):

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);
}

Я полагаю, что в вашем случае вы берете массив $ comments arrayref и изменяете первый элемент, который соответствует / VERSION /, с содержимым замены.

И вот заключительный код любезности автора:

#!/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');
...