perl - 如何使用现代 perl 和 utf8 默认值制作 "use My::defaults"?

标签 perl utf-8 cpan

我想为我自己的“默认使用”制作一个模块,例如:

use My::perldefs;

具有以下内容(主要基于 tchrist's 帖子。)
use 5.014;
use strict;
use features qw(switch say state);

no warnings;
use warnings qw(FATAL closed threads internal debugging pack substr malloc
                unopened portable prototype inplace io pipe unpack regexp
                deprecated exiting glob digit printf utf8 layer
                reserved parenthesis taint closure semicolon);
no warnings qw(exec newline);

use utf8;
use open qw(:std :utf8);
use charnames qw(:full);
use feature qw(unicode_strings);
use Encode qw(encode decode);
use Unicode::Normalize qw(NFD NFC);
use Carp qw(carp croak confess cluck);
use autodie;

简单来说,想实现一个use My::perldefs为了达到
  • 完整且正确的 utf8 支持,并带有
  • 所有现代 perl 功能都打开了。

  • 基于 recent question好的起点是 uni::perl。它几乎可以做我想做的所有事情,只需要添加:
    use feature qw(unicode_strings);
    use charnames qw(:full);
    use Encode qw(encode decode);
    use Unicode::Normalize qw(NFD NFC);
    use autodie;
    

    我将奖励使用有效且正确的方式用上述 5 行扩展 uni::perl(下面插入)的人。

    请帮助为 utf8 和现代 perl 使用制作一个很好的样板。谢谢。

    Bellow 是 uni::perl 的副本。
    package My::perldefs;
    
    use 5.014;
    BEGIN {
        ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "\xfc\x3f\xf3\x00\x0f\xf3\xcf\xc0\xf3\xfc\x33\x03";
        $^H |= 0x00000602;
    }
    m{
    use strict;
    use warnings;
    }x;
    use mro ();
    
    BEGIN {
        for my $sub (qw(carp croak confess)) {
            no strict 'refs';
            *$sub = sub {
                my $caller = caller;
                local *__ANON__ = $caller .'::'. $sub;
                require Carp;
                *{ $caller.'::'.$sub } = \&{ 'Carp::'.$sub };
                goto &{ 'Carp::'.$sub };
            };
        }
    }
    
    sub import {
        my $me = shift;
        my $caller = caller;
        ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "\xfc\x3f\xf3\x00\x0f\xf3\xcf\xc0\xf3\xfc\x33\x03";
    
        $^H |=
              0x00000602 # strict
            | 0x00800000 # utf8
        ;
    
        # use feature
        $^H{feature_switch} =
        $^H{feature_say}    =
        $^H{feature_state}  = 1;
    
        # use mro 'c3';
        mro::set_mro($caller, 'c3');
    
        #use open (:utf8 :std);
        ${^OPEN} = ":utf8\0:utf8";
        binmode(STDIN,   ":utf8");
        binmode(STDOUT,  ":utf8");
        binmode(STDERR,  ":utf8");
    
        for my $sub (qw(carp croak confess)) {
            no strict 'refs';
            *{ $caller .'::'. $sub } = \&$sub;
        }
        while (@_) {
            my $feature = shift;
            if ($feature =~ s/^://) {
                my $package = $me. '::'. $feature;
                eval "require $package; 1" or croak( "$@" );
                $package->load( $caller );
            }
        }
    }
    
    1;
    

    附言:
    All of the above is (C): Mons Anderson, C<< <mons at cpan.org> >>
    

    最佳答案

    use feature qw(unicode_strings)很容易,$^H{feature_unicode}只需要设置。其他模块也不太难,只需要使用require并显式调用必要的模块函数(例如 EncodeUnicode::Normalize 通过 export 定义一个 Exporter 方法,将调用包作为参数)。棘手的是autodie , 它确实严格按照 caller 的值进行并且通常会将其函数注入(inject) My::perldefs包裹。我认为这里唯一好的解决方案(没有在 My::perldefs 中重新实现模块)是使用 goto - 这允许在不更改 caller 的情况下调用所需的方法,因此这些方法被注入(inject)到正确的命名空间中。这是我最后得到的:

    package My::perldefs;
    
    use 5.014;
    BEGIN {
        ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "\xfc\x3f\xf3\x00\x0f\xf3\xcf\xc0\xf3\xfc\x33\x03";
        $^H |= 0x00000602;
    }
    m{
    use strict;
    use warnings;
    }x;
    use mro ();
    
    BEGIN {
        for my $sub (qw(carp croak confess)) {
            no strict 'refs';
            *$sub = sub {
                my $caller = caller;
                local *__ANON__ = $caller .'::'. $sub;
                require Carp;
                *{ $caller.'::'.$sub } = \&{ 'Carp::'.$sub };
                goto &{ 'Carp::'.$sub };
            };
        }
    }
    
    sub import {
        my $me = shift;
        my $caller = caller;
        ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "\xfc\x3f\xf3\x00\x0f\xf3\xcf\xc0\xf3\xfc\x33\x03";
    
        $^H |=
              0x00000602 # strict
            | 0x00800000 # utf8
        ;
    
        # use feature
        $^H{feature_switch} =
        $^H{feature_say}    =
        $^H{feature_state}  =
        $^H{feature_unicode}= 1;
    
        # use mro 'c3';
        mro::set_mro($caller, 'c3');
    
        #use open (:utf8 :std);
        ${^OPEN} = ":utf8\0:utf8";
        binmode(STDIN,   ":utf8");
        binmode(STDOUT,  ":utf8");
        binmode(STDERR,  ":utf8");
    
        #use charnames qw(:full)
        require charnames;
        charnames->import(":full");
    
        #use Encode qw(encode decode)
        require Encode;
        Encode->export($caller, "encode", "decode");
    
        #use Unicode::Normalize qw(NFC NFD)
        require Unicode::Normalize;
        Unicode::Normalize->export($caller, "NFC", "NFD");
    
        for my $sub (qw(carp croak confess)) {
            no strict 'refs';
            *{ $caller .'::'. $sub } = \&$sub;
        }
        while (@_) {
            my $feature = shift;
            if ($feature =~ s/^://) {
                my $package = $me. '::'. $feature;
                eval "require $package; 1" or croak( "$@" );
                $package->load( $caller );
            }
        }
    
        #use autodie qw(:default)
        #goto needs to be used here to make sure that caller doesn't change
        require autodie;
        @_ = ("autodie", ":default");
        goto &autodie::import;
    }
    
    1;
    

    关于perl - 如何使用现代 perl 和 utf8 默认值制作 "use My::defaults"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6412799/

    相关文章:

    c++ - 如何安全便携地输入和检查重音字符

    perl - 为什么不安装DBI?

    perl - 在 perl 归档 tar 中将 CHOWN 设置为 0

    perl - Perl 中的 Fork 无法在从文件读取的 while 循环内工作

    regex - perl 解析格式错误的括号文本

    c++ - 将 C++ std::string 转换为 UTF-16-LE 编码的字符串

    c# - RestSharp 不对请求进行 UTF-8 编码

    xml - 用于 Perl 的 XSLT2.0 处理器?

    string - 如何通过perl中的每个字符比较2个字符串

    html - 如何使 perl 打印 HTML 而不是原始代码