#!/usr/bin/env perl
#PODNAME: transerialize

package File::Serialize::transerialize;
our $AUTHORITY = 'cpan:YANICK';
#ABSTRACT: transerialize files from a format to a different one
$File::Serialize::transerialize::VERSION = '1.5.0';

use strict;
use warnings;

my %args;

BEGIN {
    while( $ARGV[0] =~ /=/ ) {
        my ($k,$v) = split '=', shift @ARGV;
        $args{$k} = $v;
    }

    if ( $ARGV[0] =~ s/(?<=^-)\.(?<format>\w+)$// ) {
        $args{format} = $+{format};
    }
}

use File::Serialize \%args;

my $codish = qr/
    ^(?:
         [ \[\{ ]    # [ .. ] or { ... }
       | sub \s* \{  # or a sub
    )
/x;

@ARGV = map {
    s/^\@// ? deserialize_file($_)->@* : $_
} @ARGV;

for ( grep { $_ =~ $codish }  @ARGV ) {
    $_ = eval $_ or die $@;
}

for( grep { /^-\.\w+$/ } @ARGV ) {
    $_ = { split '\.', $_, 2 };
}

my $source = shift;
my $destination = pop;

{ no warnings;
$File::Serialize::SOURCE = $source;
$File::Serialize::DESTINATION = $destination;
}

for ( grep { !ref } @ARGV ) {
    $_ = do $_;
}

transerialize_file $source, @ARGV, $destination;

__END__

=pod

=encoding UTF-8

=head1 NAME

transerialize - transerialize files from a format to a different one

=head1 VERSION

version 1.5.0

=head1 SYNOPSIS

    # simple
    $ transerialize foo.yaml bar.json

    # with options
    $ transerialize pretty=1 foo.yaml bar.json

    # reading from STDIN
    $ cat foo.yaml | transerialize -.yaml bar.json

    # printing to STDOUT
    $ transerialize foo.yaml -.json

=head1 DESCRIPTION

C<transerialize> is a command-line interface to the
L<File::Serialize> function of the same name.

The command behaves pretty much like its underlying function, except
for the details below.

=head2 Default options

All leading arguments containing an '='
will be considered default options. In other words,

    $ transerialize pretty=1 format=json foo bar

is equivalent to the script

    use File::Serialize { pretty => 1, format => 'json' };

    transerialize_file 'foo' => 'bar';

=head2 Code arguments

Any argument that begin with a '{', '[' or 'sub {' will be
eval'ed (as opposed as being considered filenames).

=head2 Intermediary steps

Any intermediary step that doesn't look like code (as specified
in the previous section) is doing to be interpreted as a Perl
script returning a transformation function.

For example, you could grab the title of a blog entry and put it
in the frontmatter via:

    $ transerialize ./README.md ./set_front_title.pl -.json

with F<./set_front_title.pl> looking like:

    sub {
        return $_ if $_->{title};

        $_->{title} = $1 if $_->{_content} =~ /^# (.*)/m;

        return $_;
    }

=head2 Loading intermediary steps from file

Any of the argument passed to C<transerialize> that has a leading
C<@> is considered a serialized file containing a list of files
and will be expanded. Useful if you do have a lot of intermediary steps and the command line is getting ungainly long.

For example, you could have

    # file ./process_blog.yml
    - set_front_title.pl
    - gather_tags.pl

    $ transerialize README.md @./process_blog.pl -.json

=head2 STDIN and STDOUT

An input filename which main part is a dash will be
taken to be STDIN. For example

    $ transerialize_file -.yaml foo.json

will read STDIN, consider it to be YAML, and then
convert it to JSON.

Likewise, an output file which main part is a dash
will be printed on STDOUT. For example

    $ transerialize_file foo.yaml -.json

will print out the data of F<foo.yaml> as JSON.

=head2 Accessing source and destination files

The original source and destination files are available to
transformation scripts via the global variables
C<$File::Serialize::SOURCE> and C<$File::Serialize::DESTINATION>.

=head1 AUTHOR

Yanick Champoux <yanick@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2021, 2019, 2017, 2016, 2015 by Yanick Champoux.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
