package A2B::CLI; use A2B; use File::Path; use GetOpt::OO '?' => 'help', l => 'list', O => 'options', A => 'args', p => 'path', g => 'grep', G => 'nogrep', m => 'type', x => 'extension', n => 'names', c => 'content', C => 'nocontent', i => 'in', o => 'out', f => 'from', t => 'to', d => 'dir', D => 'tempdir', q => 'quiet', Q => 'silent', y => 'force', ; @ISA = "GetOpt::OO"; use strict; sub new { my ($package, $a2b) = @_; ref $a2b or die "usage: A2B::CLI->new(\$a2b)\n"; my $this = bless { path => 0, a2b => $a2b, }, $package; return $this; } # < methods that can be called from the options ... # GetOpt::OO really SUCKS at the moment! I'm sure it was a good idea, just not # done quite right... this "proxy" object should not be here at all... l8r # I was using Pod::Usage, but it's only in perl 5.6 sub help { open HELP, $0 or die "cannot open `$0' to read help!"; my $c == 0; while () { last if /^=head1 OPTIONS/; print if /^=head1 SYNOPSIS/ .. 0 and $c++ >= 2; } exit 0; } sub in { my $self = shift; $self->{in} = [@_]; } sub out { my $self = shift; $self->{out} = shift; @_ and die "usage: --out=foo\n"; } sub path { my $self = shift; $self->{path} = shift; $self->{path} > 0 and !@_ or die "usage: --path=9\n"; } sub dir { my $self = shift; $self->{dir} = shift; defined $self->{dir} and !@_ or die "usage: --dir=workdir\n"; } sub tempdir { my $self = shift; $self->{dir} = shift; defined $self->{dir} and !@_ or die "usage: --tempdir=workdir\n"; $self->{dir_temp} = 1; } sub from { my $self = shift; $self->{from} = shift; defined $self->{from} and !@_ or die "usage: --from=mime/type\n"; } sub to { my $self = shift; @_ or die "usage: --to: mime/type ...\n"; $self->{to} = [@_]; } sub list { my $self = shift; $self->{list} = shift; @_ and die "usage: --list or --list=3\n"; } sub args { my $self = shift; $self->{list} = shift; @_ and die "usage: --args or --args=3\n"; $self->{details} = 2; } sub options { my $self = shift; $self->{list} = shift; @_ and die "usage: --details or --details=3\n"; $self->{details} = 1; } sub type { my $self = shift; $self->{type} = 1; } sub names { my $self = shift; $self->{names} = 1; } sub extension { my $self = shift; $self->{type} = 1; $self->{extension} = 1; } sub content { my $self = shift; $self->{content} = 1; } sub nocontent { my $self = shift; $self->{content} = -1; } sub quiet { my $self = shift; $self->{a2b}->{quiet} = 1; } sub silent { my $self = shift; $self->{a2b}->{quiet} = 2; } sub force { my $self = shift; $self->{a2b}->{force} = 1; } sub grep { my $self = shift; $self->{a2b}->{grep} = [map qr/$_/, @_]; } sub nogrep { my $self = shift; $self->{a2b}->{nogrep} = [map qr/$_/, @_]; } # > end methods that can be called from options sub run { my $self = shift; if ($self->{type}) { $self->do_type(@_); return; } if (@_) { if (@_ == 2 && (!$self->{in} || !@{$self->{in}}) && !$self->{out}) { $self->{in} = [$_[0]]; $self->{out} = $_[1]; } else { die "extra arguments not understood: @_\n"; } } defined $self->{to} or ($self->{out} and $self->{to} = $self->{a2b}->identify_by_extension($self->{out})) or die "a `to' type must be specified\n"; defined $self->{from} or ($self->{in} and @{$self->{in}} >= 1 and $self->{from} = $self->identify($self->{in}[0])) or die "a `from' type must be specified\n"; if (exists $self->{list}) { $self->do_list(); } else { $self->do_convert(); } } sub do_list { my $self = shift; # we output a list of paths my $paths = $self->{a2b}->paths($self->{from}, $self->{to}, $self->{list}); my $i = 1; for my $path (@$paths) { if (!$self->{path} || $i == $self->{path}) { printf "%3d (%5.3f) %s\n", $i, $path->goodness, $path->as_string($self->{details}); } ++$i; } } sub do_convert { my $self = shift; defined $self->{in} or die "an `in' file must be specified"; # we do a conversion $self->{path} ||= 1; my $paths = $self->{a2b}->paths($self->{from}, $self->{to}, $self->{path}); my $path = $paths->[$self->{path}-1] or die "there is no conversion path".($self->{path} != 1 ? "numbered `$self->{path}'" : ""); -e $self->{dir} && $self->{dir_temp} and die "tempdir `$self->{dir}' already exists; delete it, or use --dir\n"; $self->{a2b}->convert($path, $self->{in}, $self->{out}, $self->{dir}); if ($self->{dir_temp} && $self->{dir}) { rmtree $self->{dir} or warn "cannot rmtree `$self->{dir}': $!"; } } sub do_type { my $self = shift; my @files = @_; for my $file (@files) { my $type = $self->identify($file); $type ||= ""; if ($self->{extension}) { $type = $self->{a2b}->type($type)->extension; } if ($self->{names}) { print "$file\t$type\n"; } else { print "$type\n"; } } } sub identify { my $self = shift; my $file = shift; my $type; if ($self->{content} == 1) { $type = $self->{a2b}->identify_by_content($file); } elsif ($self->{content} == -1) { $type = $self->{a2b}->identify_by_extension($file); } else { $type = $self->{a2b}->identify($file); } return $type; } 1