Как я могу использовать Smart :: Comments в загружаемом модуле без изменения его источника? - PullRequest
7 голосов
/ 28 января 2010

Как я могу указать, что Smart :: Comments будет загружаться для моего исходного скрипта, а также для любого из модулей, которые он загружает напрямую. Тем не менее, поскольку он является исходным фильтром, он, вероятно, разрушит хаос, если применить его к каждому модулю, загруженному каждым другим загруженным модулем.

Например, мой скрипт включает

use Neu::Image;

Я также хотел бы загрузить Smart::Comments для Neu::Image, но указав

$ perl -MSmart::Comments script.pl

не загружается Smart::Comments для Neu::Image.

Это поведение описано в документации Smart :: Comments :

Если вы отлаживаете приложение, также может вызвать его с помощью модуля из командной строки:

perl -MSmart::Comments $application.pl

Конечно, это включает только умный комментарии в файле заявки сам по себе, а не в каких-либо модулях, которые приложение загружает.

Несколько других вещей, на которые я уже смотрел:

* 1041 Временное решение * Как упоминает gbacon, Smart :: Comments предоставляет параметр переменной среды, который позволяет включать или выключать его. Тем не менее, я хотел бы иметь возможность включить его, не изменяя исходный источник, если это возможно.

Ответы [ 2 ]

10 голосов
/ 28 января 2010

Вы почти наверняка захотите добавить use Smart::Comments к модулям, которые содержат такие, а затем переключить переключатель в вашей среде , установив $Smart_Comments соответствующим образом.

Погоня, import угон обезьян - это безумие.

Но, может быть, вам нравятся такие вещи. Скажем, у вас есть Foo.pm:

package Foo;

use Exporter 'import';
our @EXPORT = qw/ foo /;

#use Smart::Comments;

sub foo {
  my @result;
  for (my $i = 0; $i < 5; $i++) {
    ### $i
    push @result => $i if $i % 2 == 0;
  }
  wantarray ? @result : \@result;
}

1;

Обычное использование:

$ perl -MFoo -e 'print foo, "\n"'
024

Обычный, конечно, скучный и скучный. С run-foo мы делаем смелые, стремительные шаги!

#! /usr/bin/perl

use warnings;
use strict;

BEGIN {
  unshift @INC => \&inject_smart_comments;

  my %direct;
  open my $fh, "<", $0 or die "$0: open: $!";
  while (<$fh>) {
    ++$direct{$1} if /^\s*use\s+([A-Z][:\w]*)/;
  }
  close $fh;

  sub inject_smart_comments {
    my(undef,$path) = @_;
    s/[\/\\]/::/g, s/\.pm$// for my $mod = $path;
    if ($direct{$mod}) {
      open my $fh, "<", $path or die "$0: open $path: $!";
      return sub {
        return 0 unless defined($_ = <$fh>);
        s{^(\s*package\s+[A-Z][:\w]*\s*;\s*)$}
         {$1 use Smart::Comments;\n};
        return 1;
      };
    }
  }
}

use Foo;

print foo, "\n";

(Прошу прощения за компактность: я сжал ее, чтобы она поместилась в блоке без прокрутки.)

Выход:

$ ./run-foo

### $i: 0

### $i: 1

### $i: 2

### $i: 3

### $i: 4
024

& iexcl;! Viva

С помощью @INC крючков мы можем заменить наши собственные или измененные источники. Код следит за попытками require модулей, непосредственно используемых программой. При попадании inject_smart_comments возвращает итератор, который возвращает по одной строке за раз. Когда этот хитрый, хитрый итератор видит объявление пакета, он добавляет к чанку невинно выглядящий use Smart::Comments, создавая впечатление, что он все время находился в источнике модуля.

При попытке проанализировать код Perl с помощью регулярных выражений код будет нарушен, если, например, объявление пакета не находится в отдельной строке. Сезон по вкусу.

2 голосов
/ 29 января 2010

Не похоже, что эта идея имеет какой-то смысл. Если вы используете Smart::Comments в модуле, почему бы вам не захотеть use Smart::Comments в источнике этого модуля? Даже если бы вы могли заставить Smart::Comments применить ко всем модулям, загруженным в скрипт через -M, это, вероятно, не было бы хорошей идеей, потому что:

  • Вы скрываете тот факт, что ваши модули используют умные комментарии , а не , включая строку use в их источнике.
  • Вы можете потенциально ввести странное поведение из модулей, которые вы use в своем скрипте, которые имеют то, что похоже на умные комментарии, но на самом деле это не так. Если модуль не содержит умных комментариев, вам не следует заставлять их глотать.

Как сказал gbacon , правильный способ сделать это - use модуль в каждом из ваших модулей, которые его используют, а затем подавить их с помощью переменной среды, если вы этого не сделаете хочу вывод.

Также, как он сказал, возможно, все еще возможно сделать это с каким-то безумием "копить шкатулку, угонять импорт обезьян", но это много работы. Я не думаю, что кто-то собирается приложить усилия к тому, чтобы дать вам решение в том же духе, когда это не очень хорошая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...