App-diff_spreadsheets

 view release on metacpan or  search on metacpan

bin/diff_spreadsheets  view on Meta::CPAN

   (map { ((/=/ ? $_ : "$_=s") => \&diffopt_withval) }
      qw/C|c|context=i D F GTYPE-group-format horizon-lines I ifdef
         ignore-matching-lines label line-format LTYPE-group-format
         show-function-line tabsize=i
        /),
   (map { ($_ => \&diffopt_noval) }
        qw/a B b brief d E e ed expand-tabs i ignore-blank-lines ignore-case
           ignore-space-change ignore-tab-expansion initial-tab l minimal n
           p paginate q rcs report-identical-files s show-c-function
           speed-large-files strip-trailing-cr T t text/),
    # valid only for 'git diff':
   (map { ((/[:=]/ ? $_ : "$_=s") => \&diffopt_comboptstr) }
        qw/color/),
   (map { ((/[:=]/ ? $_ : oops) => \&diffopt_comboptnum) }
        qw/u|U|unified:i/),
   (map { ((/=/ ? $_ : "$_=s") => \&diffopt_comboptstr) }
        qw/word-diff-regex word-diff ws-error-highlight/),
   (map { ($_ => \&diffopt_noval) }
        qw/w|ignore-all-space y|side-by-side/),
   "W|width=i" => sub{ $maxwidth = $_[1]; diffopt_comboptnum(@_); },

   # our options:
   "always-show-columns=s"   => sub{ push @{$opts{always_show_columns}}, $_[1]},
   "columns=s"               => sub{ push @{$opts{columns}}, $_[1] },
   "debug"                   => sub{ $opts{debug} = $_[1] },
   "encoding=s"              => sub{ $opts{encoding} = $_[1] },
   "first-data-row=i"        => sub{ $opts{first_data_row} = $_[1] },
   "hash-func=s"             => sub{ $opts{hash_func} = $_[1] },
   "hashid-func=s"           => sub{ $opts{hashid_func} = $_[1] },
   "h|help"                  => \$help,
   "id-columns=s"            => sub{ push @{$opts{id_columns}}, $_[1] },
   "keep-temps!"             => sub{ $opts{keep_temps} = $_[1] },
   "m|method=s"              => \$method,
   "output-encoding=s"       => sub{ $opts{output_encoding} = $_[1] },
   "quiet|silent"            => sub{ $opts{silent} = $_[1] },
   "quote-char=s"            => sub{ $opts{quote_char} = $_[1] },
   "sep-char=s"              => sub{ $opts{sep_char} = $_[1] },
   "setup-code=s"            => sub{ $opts{setup_code} = $_[1] },
   "sheets=s"                => sub{ push @{$opts{sheet_names}}, $_[1] },
   "show-empties"            => sub{ $opts{show_empties} = $_[1] },
   "sort-rows!"              => sub{ $opts{sort_rows} = $_[1] }, # allow --no-sort
   "suppress-common-lines"   => sub{ $opts{suppress_common_lines} = 1; push @diff_opts, "-$_[0]"; },
   "title-row=i"             => sub{ $opts{title_row} = $_[1] },
   "v|verbose"               => sub{ $opts{verbose} = $_[1] },
   "Z|ignore-trailing-space" => sub{ $opts{ign_trailing_spaces} = 1; push @diff_opts, "-$_[0]"; },
) or badargs_exit(-msg => "$Script -h for help");

call_pod2usage(-verbose => 2, -output => \*STDOUT) if $help;

foreach (@diff_opts) { s/^-(\w\w+)/--$1/ }  # change -longopt to --longopt

foreach my $key (qw/columns id_columns always_show_columns sheet_names/) {
  next unless $opts{$key};
  @{$opts{$key}} = map{ split/(?<!\\),/ } @{$opts{$key}}
}
$opts{verbose} //= $opts{debug};

if ($opts{output_encoding}) {
  my $crlf = grep(/crlf/, PerlIO::get_layers(*STDOUT)) ? ":crlf" : "";
  my $arg = ":raw${crlf}:encoding($opts{output_encoding})";
  warn ">binmode STDOUT/ERR '$arg'\n" if $opts{debug};
  binmode(\*STDOUT, $arg) or die "binmode $arg : $!";
  binmode(\*STDERR, $arg) or die "binmode $arg : $!";
}
($stdout_encoding) = map{ /encoding\((.+)\)/ ? ($1) : () }
                     PerlIO::get_layers(*STDOUT);

($visible_space, $RArrow) =
    ($stdout_encoding =~ /utf/i)
      ? ("\N{MIDDLE DOT}", "\N{RIGHTWARDS ARROW}\N{HAIR SPACE}")
      : (".",              "-->") ;

our ($hash_func_code, $hashid_func_code, $setup_code_code);
foreach my $argname (qw(hashid-func hash-func setup-code)) {
  (my $optskey = $argname) =~ s/-/_/g;
  next unless defined $opts{$optskey};
  my $source = "package Usercode;" . $opts{$optskey};
  no strict 'refs';
  ${"${optskey}_code"} = eval $source;
  die "Syntax error in Perl code for --$argname option:\n$@" if $@;
  die "--$argname did not produce a sub ref (got ",u(${"${optskey}_code"}),"\n"
    unless ref(${"${optskey}_code"}) eq "CODE";
}
$hashid_func_code //= sub{ Carp::cluck "bug" if grep{! defined} @{$_[0]}; join ",", @{$_[0]} };
$hash_func_code   //= sub{ Carp::cluck "bug" if grep{! defined} @{$_[0]}; join ",", @{$_[0]} };
$setup_code_code  //= sub{};

badargs_exit(-msg => "Two files must be specified") if @ARGV != 2;
$opts{origpath1} = $ARGV[0];
$opts{origpath2} = $ARGV[1];

if ($opts{keep_temps}) {
  my $dir = path( catfile(tmpdir(), "dstmp") );  # /tmp/dstmp
  $dir->remove_tree;
  mkdir $dir->canonpath or die "mkdir $dir : $!";
  warn "> Created ",qsh($dir),"\n";
  $opts{tempdir} = $dir;
} else {
  $opts{tempdir} = Path::Tiny->tempdir("diffspread_XXXXX", CLEANUP=>1);
}

# Extract the possibly-multiple "sheets" from each spreadsheet into
# separate .csv files and process the corresponding pairs.
# If a specific sheet was specified, then only that sheet will be extracted.
foreach my $N (1,2) {
  my $origpath = $opts{"origpath$N"};
  my $sheet_from_path = sheetname_from_spec($origpath);
  if (defined $sheet_from_path) {
    die "--sheets argument not allowed because filename specifies a sheet:\n",
        "  ", qsh($origpath), "\n"
      if $opts{sheet_names};
  }
  my $dir = $opts{tempdir}->child("--INFILE$N--")->mkdir;
  my $h = convert_spreadsheet($origpath, cvt_to=>"csv",
                                         allsheets => !$sheet_from_path,
                                         outpath => $dir->canonpath,
                                         silent  => $opts{silent},
                                         verbose => $opts{debug},
                                         debug   => $opts{debug},
                             );
  $opts{cvt_from} = $h->{cvt_from};
  if ($h->{cvt_from} =~ /csv/i && !openhandle($origpath)) {
    # Input was already a CSV (possibly detected by peeking at actual content).



( run in 0.439 second using v1.01-cache-2.11-cpan-e1769b4cff6 )