Data-Show

 view release on metacpan or  search on metacpan

lib/Data/Show.pm  view on Meta::CPAN

}

# Locate and process config file(s) and/or environment variable, if any...
sub _load_defaults {
    my ($file, $line) = @_;

    # Build up defaults, starting with the built-in defaults...
    my %defaults = @ARGUMENT_DEFAULTS;

    # Overwrite previous defaults with any readable global or local config file(s)...
    for my $config_file (grep {-r} "$ENV{HOME}/$RC_FILE_NAME", "./$RC_FILE_NAME") {
        %defaults = ( %defaults, _load_config($config_file) );
    }

    return \%defaults;
}

sub _load_config {
    my ($filename) = @_;

    # Grab contents of file...
    open my $fh, '<:utf8', $filename or return;
    local $/;
    my $config = readline($fh) // return;

    # Remove empty lines (including comment lines)...
    $config =~ s{ ^ \s* (?: \# [^\n]* )? (?:\n|\z) }{}gxms;

    # Extract keys and values of each option...
    my %opt = $config =~ m{ ^ \h* ([^:=]*?) \h* [:=] \h* ([^\n]*) (?:\n|\z) }gxms;

    # Convert a "*NAME" string to the corresponding named filehandle...
    if (exists $opt{to} && $opt{to} =~ m{ \A \* (.*) }x) {
        no strict 'refs';
        no warnings 'once';
        $opt{to} = \*{$1};
    }

    # Validate config...
    _validate_args(\%opt, "in $filename", "configuration option");

    return %opt;
}

# The whole point of the module...
sub show {
    # Find the various contexts of this call...
    my ($package, $file, $line, $hints_ref) = _get_context();
    my $call_context = wantarray();

    # Skip almost everything if "no Data::Show"...
    if (!$hints_ref->{'Data::Show/noshow'}) {

        # Identify current lexically-scoped config (should already have been loaded by import())...
        my $plugin_class = $hints_ref->{'Data::Show/with'} // $FINAL_CANDIDATE_PLUGIN;
        my %style        = %{ $STYLE[ $hints_ref->{'Data::Show/style'} ] };
        my $termwidth    = $hints_ref->{'Data::Show/termwidth'};

        # Warn about side-effects of multi-arg calls to show() in scalar context...
        if (defined $call_context && !$call_context && @_ > 1) {
            warn "Call to show() may not be not transparent at $file line $line\n";
        }

        # Serialize Contextual::Return objects (can break some dumpers in the Data::Dump family)...
        my @data = map { ref() =~ m{\AContextual::Return::Value}
                    ? do {my $v = $_->Contextual::Return::DUMP(); $v =~ s[\}\n][\},\n]gxms; eval $v; }
                    : $_
                    } @_;

        # Extract the originating source line(s)...
        my ($pre_source, $source, $post_source, $startline)
            = _get_source($file, $line, $hints_ref->{'Data::Show/as'});

        # What kind of data is it???
        my $is_single_hash = _data_is_single_hash($source, \@data, $hints_ref->{'Data::Show/as'});
        my $is_single_arg  = @data == 1;

        # Stringify the data...
        my $data = $plugin_class->stringify( $is_single_hash ? {@data}
                                           : $is_single_arg  ? $data[0]
                                           :                   \@data
                                           );

        # Some stringifiers add an (unwanted) empty first line, so remove it...
        $data =~ s{ \A \h* \n }{}xms;

        # Change delimters of any stringified arguments that were passed to the stringifier via refs...
        if    ($is_single_hash)  { $data =~ s{ \A (\s*) \{ (.*) \} (\s*) \z }{$1($2)$3}xms; }
        elsif (!$is_single_arg)  { $data =~ s{ \A (\s*) \[ (.*) \] (\s*) \z }{$1($2)$3}xms; }

        # Where are we printing to???
        my $fh = exists $hints_ref->{'Data::Show/to'} ? $OUTPUT_FH[$hints_ref->{'Data::Show/to'}]
                                                      : $DEFAULT_TARGET;

        # Disable styling if not outputting to a terminal or if styling is unavailable...
        if (!-t $fh || $style{mode} eq 'auto' && !$CAN_ANSICOLOR) {
            $style{mode} = 'off'
        }

        # Show the data with its context header (with style!)...
        no warnings 'utf8';
        print {$fh}
            $plugin_class->format(
                $file, $startline, $pre_source, $source, $post_source, $data, \%style, $termwidth,
            );
    }

    # Return the entire argument list if possible, otherwise simulate scalar context...
    return @_ if $call_context;
    return $_[0];
}

# Return the source code at a given file and line...
sub _get_source {
    my ($file, $line, $subname) = @_;

    # Optimize look-up via a cache...
    state %source_cache;

    # Load the entire source of requested file...
    if (!$source_cache{$file}) {

lib/Data/Show.pm  view on Meta::CPAN


=item C<< Named 'to' argument is not a writeable target >>

You specified a filehandle as an alternative output target,
but the filehandle was not writeable.

Check whether the filehandle you passed is actually open,
and then whether it is open for output.


=item C<< <PLUGIN> requires <MODULE>, which could not be loaded >>

You requested a built-in plugin, but that plugin requires a module
that could not be loaded.

Either install the required support module, or load Data::Show with:

    use Data::Show warnings => 'off';

...to silence this warning and quietly use a fallback module instead.


=item C<< Could not load <PLUGIN> >>

You requested a non-built-in plugin, but that plugin
could not be loaded.

Check that the name of the requested plugin is correctly spelled,
and that the plugin is actually installed somewhere in the current
C<@INC> path.

If you can't install the module, you can silence this warning
and default to a fallback dumper with:

    use Data::Show warnings => 'off';


=item C<< Requested plugin class does not provide the following essential methods >>

You specified a non-builtin plugin, which was found and loaded, but which did
not provide both of the two required methods for dumping information:
C<stringify()> and C<format()>.

See L<"Plugins"> for an explanation of why these two methods are required,
and how they work.

To ignore this warning and proceed to a fallback dumper module instead:

    use Data::Show warnings => 'off';

=item C<< Used <FALLBACK> in place of <PLUGIN> >>

You requested a plugin that could not be loaded,
so the best available fallback was used instead.

You would have also received one or more of the three preceding
diagnostics. Consult their entries for suggestions on silencing
this warning.


=item C<< Call to show() may not be not transparent >>

The call to C<show()> has been inserted into a scalar context,
but was passed two or more arguments to dump. This can change
the behaviour of the surrounding code. For example, consider
the following statements:

    my @list = (
        abs  $x,
        exp  $y,
        sqrt $z,
    );

    sub foo ($angle) {
        return cos $angle,
               sin $angle;
    }

If we add interstitial C<show()> calls, as follows:

    my @list = (
        abs  show $x,
        exp  show $y,
        sqrt show $z,
    );

    sub foo ($angle) {
        return cos show $angle,
               sin show $angle;
    }

...then the addition of the C<show()> calls actually changes
the final contents of C<@list>, and also changes the return
value of C<foo()> in scalar contexts.

This issue (and warning) never occurs in list or void contexts,
and can generally be avoided in scalar contexts, by explicitly
parenthesizing each call to C<show()>, as follows:

    my @list = (
        abs  show($x),
        exp  show($y),
        sqrt show($z),
    );

    sub foo ($angle) {
        return cos show($angle),
               sin show($angle);
    }

Note that this approach also ensures that the various intermediate
calls to C<show()> occur in a more predictable sequence.


=item C<< <MODULE> cannot show a <TYPE> reference >>

The stringification module used by your selected plugin
was unable to stringify the particular data passed to C<show()>.

This may be due to a bug or limitation in the stringification module itself,
or it may be because the target output format does not support rendering



( run in 1.594 second using v1.01-cache-2.11-cpan-39bf76dae61 )