diff options
author | Siep Kroonenberg <siepo@cybercomm.nl> | 2011-02-17 12:20:49 +0000 |
---|---|---|
committer | Siep Kroonenberg <siepo@cybercomm.nl> | 2011-02-17 12:20:49 +0000 |
commit | 316ee97c621496b0fe3267f57cce81bee44ca1e6 (patch) | |
tree | cb2cab1192b4f58a7971af19b213e980bceda4b4 /Master/tlpkg/tlperl/lib/File/GlobMapper.pm | |
parent | cd0f87b5d39480d85ad9bd4ee37f520f75bed560 (diff) |
Moving old tlperl prior to committing new one
git-svn-id: svn://tug.org/texlive/trunk@21422 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlperl/lib/File/GlobMapper.pm')
-rwxr-xr-x | Master/tlpkg/tlperl/lib/File/GlobMapper.pm | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/Master/tlpkg/tlperl/lib/File/GlobMapper.pm b/Master/tlpkg/tlperl/lib/File/GlobMapper.pm deleted file mode 100755 index 40a606309e0..00000000000 --- a/Master/tlpkg/tlperl/lib/File/GlobMapper.pm +++ /dev/null @@ -1,679 +0,0 @@ -package File::GlobMapper; - -use strict; -use warnings; -use Carp; - -our ($CSH_GLOB); - -BEGIN -{ - if ($] < 5.006) - { - require File::BSDGlob; import File::BSDGlob qw(:glob) ; - $CSH_GLOB = File::BSDGlob::GLOB_CSH() ; - *globber = \&File::BSDGlob::csh_glob; - } - else - { - require File::Glob; import File::Glob qw(:glob) ; - $CSH_GLOB = File::Glob::GLOB_CSH() ; - #*globber = \&File::Glob::bsd_glob; - *globber = \&File::Glob::csh_glob; - } -} - -our ($Error); - -our ($VERSION, @EXPORT_OK); -$VERSION = '1.000'; -@EXPORT_OK = qw( globmap ); - - -our ($noPreBS, $metachars, $matchMetaRE, %mapping, %wildCount); -$noPreBS = '(?<!\\\)' ; # no preceeding backslash -$metachars = '.*?[](){}'; -$matchMetaRE = '[' . quotemeta($metachars) . ']'; - -%mapping = ( - '*' => '([^/]*)', - '?' => '([^/])', - '.' => '\.', - '[' => '([', - '(' => '(', - ')' => ')', - ); - -%wildCount = map { $_ => 1 } qw/ * ? . { ( [ /; - -sub globmap ($$;) -{ - my $inputGlob = shift ; - my $outputGlob = shift ; - - my $obj = new File::GlobMapper($inputGlob, $outputGlob, @_) - or croak "globmap: $Error" ; - return $obj->getFileMap(); -} - -sub new -{ - my $class = shift ; - my $inputGlob = shift ; - my $outputGlob = shift ; - # TODO -- flags needs to default to whatever File::Glob does - my $flags = shift || $CSH_GLOB ; - #my $flags = shift ; - - $inputGlob =~ s/^\s*\<\s*//; - $inputGlob =~ s/\s*\>\s*$//; - - $outputGlob =~ s/^\s*\<\s*//; - $outputGlob =~ s/\s*\>\s*$//; - - my %object = - ( InputGlob => $inputGlob, - OutputGlob => $outputGlob, - GlobFlags => $flags, - Braces => 0, - WildCount => 0, - Pairs => [], - Sigil => '#', - ); - - my $self = bless \%object, ref($class) || $class ; - - $self->_parseInputGlob() - or return undef ; - - $self->_parseOutputGlob() - or return undef ; - - my @inputFiles = globber($self->{InputGlob}, $flags) ; - - if (GLOB_ERROR) - { - $Error = $!; - return undef ; - } - - #if (whatever) - { - my $missing = grep { ! -e $_ } @inputFiles ; - - if ($missing) - { - $Error = "$missing input files do not exist"; - return undef ; - } - } - - $self->{InputFiles} = \@inputFiles ; - - $self->_getFiles() - or return undef ; - - return $self; -} - -sub _retError -{ - my $string = shift ; - $Error = "$string in input fileglob" ; - return undef ; -} - -sub _unmatched -{ - my $delimeter = shift ; - - _retError("Unmatched $delimeter"); - return undef ; -} - -sub _parseBit -{ - my $self = shift ; - - my $string = shift ; - - my $out = ''; - my $depth = 0 ; - - while ($string =~ s/(.*?)$noPreBS(,|$matchMetaRE)//) - { - $out .= quotemeta($1) ; - $out .= $mapping{$2} if defined $mapping{$2}; - - ++ $self->{WildCount} if $wildCount{$2} ; - - if ($2 eq ',') - { - return _unmatched "(" - if $depth ; - - $out .= '|'; - } - elsif ($2 eq '(') - { - ++ $depth ; - } - elsif ($2 eq ')') - { - return _unmatched ")" - if ! $depth ; - - -- $depth ; - } - elsif ($2 eq '[') - { - # TODO -- quotemeta & check no '/' - # TODO -- check for \] & other \ within the [] - $string =~ s#(.*?\])## - or return _unmatched "[" ; - $out .= "$1)" ; - } - elsif ($2 eq ']') - { - return _unmatched "]" ; - } - elsif ($2 eq '{' || $2 eq '}') - { - return _retError "Nested {} not allowed" ; - } - } - - $out .= quotemeta $string; - - return _unmatched "(" - if $depth ; - - return $out ; -} - -sub _parseInputGlob -{ - my $self = shift ; - - my $string = $self->{InputGlob} ; - my $inGlob = ''; - - # Multiple concatenated *'s don't make sense - #$string =~ s#\*\*+#*# ; - - # TODO -- Allow space to delimit patterns? - #my @strings = split /\s+/, $string ; - #for my $str (@strings) - my $out = ''; - my $depth = 0 ; - - while ($string =~ s/(.*?)$noPreBS($matchMetaRE)//) - { - $out .= quotemeta($1) ; - $out .= $mapping{$2} if defined $mapping{$2}; - ++ $self->{WildCount} if $wildCount{$2} ; - - if ($2 eq '(') - { - ++ $depth ; - } - elsif ($2 eq ')') - { - return _unmatched ")" - if ! $depth ; - - -- $depth ; - } - elsif ($2 eq '[') - { - # TODO -- quotemeta & check no '/' or '(' or ')' - # TODO -- check for \] & other \ within the [] - $string =~ s#(.*?\])## - or return _unmatched "["; - $out .= "$1)" ; - } - elsif ($2 eq ']') - { - return _unmatched "]" ; - } - elsif ($2 eq '}') - { - return _unmatched "}" ; - } - elsif ($2 eq '{') - { - # TODO -- check no '/' within the {} - # TODO -- check for \} & other \ within the {} - - my $tmp ; - unless ( $string =~ s/(.*?)$noPreBS\}//) - { - return _unmatched "{"; - } - #$string =~ s#(.*?)\}##; - - #my $alt = join '|', - # map { quotemeta $_ } - # split "$noPreBS,", $1 ; - my $alt = $self->_parseBit($1); - defined $alt or return 0 ; - $out .= "($alt)" ; - - ++ $self->{Braces} ; - } - } - - return _unmatched "(" - if $depth ; - - $out .= quotemeta $string ; - - - $self->{InputGlob} =~ s/$noPreBS[\(\)]//g; - $self->{InputPattern} = $out ; - - #print "# INPUT '$self->{InputGlob}' => '$out'\n"; - - return 1 ; - -} - -sub _parseOutputGlob -{ - my $self = shift ; - - my $string = $self->{OutputGlob} ; - my $maxwild = $self->{WildCount}; - - if ($self->{GlobFlags} & GLOB_TILDE) - #if (1) - { - $string =~ s{ - ^ ~ # find a leading tilde - ( # save this in $1 - [^/] # a non-slash character - * # repeated 0 or more times (0 means me) - ) - }{ - $1 - ? (getpwnam($1))[7] - : ( $ENV{HOME} || $ENV{LOGDIR} ) - }ex; - - } - - # max #1 must be == to max no of '*' in input - while ( $string =~ m/#(\d)/g ) - { - croak "Max wild is #$maxwild, you tried #$1" - if $1 > $maxwild ; - } - - my $noPreBS = '(?<!\\\)' ; # no preceeding backslash - #warn "noPreBS = '$noPreBS'\n"; - - #$string =~ s/${noPreBS}\$(\d)/\${$1}/g; - $string =~ s/${noPreBS}#(\d)/\${$1}/g; - $string =~ s#${noPreBS}\*#\${inFile}#g; - $string = '"' . $string . '"'; - - #print "OUTPUT '$self->{OutputGlob}' => '$string'\n"; - $self->{OutputPattern} = $string ; - - return 1 ; -} - -sub _getFiles -{ - my $self = shift ; - - my %outInMapping = (); - my %inFiles = () ; - - foreach my $inFile (@{ $self->{InputFiles} }) - { - next if $inFiles{$inFile} ++ ; - - my $outFile = $inFile ; - - if ( $inFile =~ m/$self->{InputPattern}/ ) - { - no warnings 'uninitialized'; - eval "\$outFile = $self->{OutputPattern};" ; - - if (defined $outInMapping{$outFile}) - { - $Error = "multiple input files map to one output file"; - return undef ; - } - $outInMapping{$outFile} = $inFile; - push @{ $self->{Pairs} }, [$inFile, $outFile]; - } - } - - return 1 ; -} - -sub getFileMap -{ - my $self = shift ; - - return $self->{Pairs} ; -} - -sub getHash -{ - my $self = shift ; - - return { map { $_->[0] => $_->[1] } @{ $self->{Pairs} } } ; -} - -1; - -__END__ - -=head1 NAME - -File::GlobMapper - Extend File Glob to Allow Input and Output Files - -=head1 SYNOPSIS - - use File::GlobMapper qw( globmap ); - - my $aref = globmap $input => $output - or die $File::GlobMapper::Error ; - - my $gm = new File::GlobMapper $input => $output - or die $File::GlobMapper::Error ; - - -=head1 DESCRIPTION - -This module needs Perl5.005 or better. - -This module takes the existing C<File::Glob> module as a starting point and -extends it to allow new filenames to be derived from the files matched by -C<File::Glob>. - -This can be useful when carrying out batch operations on multiple files that -have both an input filename and output filename and the output file can be -derived from the input filename. Examples of operations where this can be -useful include, file renaming, file copying and file compression. - - -=head2 Behind The Scenes - -To help explain what C<File::GlobMapper> does, consider what code you -would write if you wanted to rename all files in the current directory -that ended in C<.tar.gz> to C<.tgz>. So say these files are in the -current directory - - alpha.tar.gz - beta.tar.gz - gamma.tar.gz - -and they need renamed to this - - alpha.tgz - beta.tgz - gamma.tgz - -Below is a possible implementation of a script to carry out the rename -(error cases have been omitted) - - foreach my $old ( glob "*.tar.gz" ) - { - my $new = $old; - $new =~ s#(.*)\.tar\.gz$#$1.tgz# ; - - rename $old => $new - or die "Cannot rename '$old' to '$new': $!\n; - } - -Notice that a file glob pattern C<*.tar.gz> was used to match the -C<.tar.gz> files, then a fairly similar regular expression was used in -the substitute to allow the new filename to be created. - -Given that the file glob is just a cut-down regular expression and that it -has already done a lot of the hard work in pattern matching the filenames, -wouldn't it be handy to be able to use the patterns in the fileglob to -drive the new filename? - -Well, that's I<exactly> what C<File::GlobMapper> does. - -Here is same snippet of code rewritten using C<globmap> - - for my $pair (globmap '<*.tar.gz>' => '<#1.tgz>' ) - { - my ($from, $to) = @$pair; - rename $from => $to - or die "Cannot rename '$old' to '$new': $!\n; - } - -So how does it work? - -Behind the scenes the C<globmap> function does a combination of a -file glob to match existing filenames followed by a substitute -to create the new filenames. - -Notice how both parameters to C<globmap> are strings that are delimited by <>. -This is done to make them look more like file globs - it is just syntactic -sugar, but it can be handy when you want the strings to be visually -distinctive. The enclosing <> are optional, so you don't have to use them - in -fact the first thing globmap will do is remove these delimiters if they are -present. - -The first parameter to C<globmap>, C<*.tar.gz>, is an I<Input File Glob>. -Once the enclosing "< ... >" is removed, this is passed (more or -less) unchanged to C<File::Glob> to carry out a file match. - -Next the fileglob C<*.tar.gz> is transformed behind the scenes into a -full Perl regular expression, with the additional step of wrapping each -transformed wildcard metacharacter sequence in parenthesis. - -In this case the input fileglob C<*.tar.gz> will be transformed into -this Perl regular expression - - ([^/]*)\.tar\.gz - -Wrapping with parenthesis allows the wildcard parts of the Input File -Glob to be referenced by the second parameter to C<globmap>, C<#1.tgz>, -the I<Output File Glob>. This parameter operates just like the replacement -part of a substitute command. The difference is that the C<#1> syntax -is used to reference sub-patterns matched in the input fileglob, rather -than the C<$1> syntax that is used with perl regular expressions. In -this case C<#1> is used to refer to the text matched by the C<*> in the -Input File Glob. This makes it easier to use this module where the -parameters to C<globmap> are typed at the command line. - -The final step involves passing each filename matched by the C<*.tar.gz> -file glob through the derived Perl regular expression in turn and -expanding the output fileglob using it. - -The end result of all this is a list of pairs of filenames. By default -that is what is returned by C<globmap>. In this example the data structure -returned will look like this - - ( ['alpha.tar.gz' => 'alpha.tgz'], - ['beta.tar.gz' => 'beta.tgz' ], - ['gamma.tar.gz' => 'gamma.tgz'] - ) - - -Each pair is an array reference with two elements - namely the I<from> -filename, that C<File::Glob> has matched, and a I<to> filename that is -derived from the I<from> filename. - - - -=head2 Limitations - -C<File::GlobMapper> has been kept simple deliberately, so it isn't intended to -solve all filename mapping operations. Under the hood C<File::Glob> (or for -older versions of Perl, C<File::BSDGlob>) is used to match the files, so you -will never have the flexibility of full Perl regular expression. - -=head2 Input File Glob - -The syntax for an Input FileGlob is identical to C<File::Glob>, except -for the following - -=over 5 - -=item 1. - -No nested {} - -=item 2. - -Whitespace does not delimit fileglobs. - -=item 3. - -The use of parenthesis can be used to capture parts of the input filename. - -=item 4. - -If an Input glob matches the same file more than once, only the first -will be used. - -=back - -The syntax - -=over 5 - -=item B<~> - -=item B<~user> - - -=item B<.> - -Matches a literal '.'. -Equivalent to the Perl regular expression - - \. - -=item B<*> - -Matches zero or more characters, except '/'. Equivalent to the Perl -regular expression - - [^/]* - -=item B<?> - -Matches zero or one character, except '/'. Equivalent to the Perl -regular expression - - [^/]? - -=item B<\> - -Backslash is used, as usual, to escape the next character. - -=item B<[]> - -Character class. - -=item B<{,}> - -Alternation - -=item B<()> - -Capturing parenthesis that work just like perl - -=back - -Any other character it taken literally. - -=head2 Output File Glob - -The Output File Glob is a normal string, with 2 glob-like features. - -The first is the '*' metacharacter. This will be replaced by the complete -filename matched by the input file glob. So - - *.c *.Z - -The second is - -Output FileGlobs take the - -=over 5 - -=item "*" - -The "*" character will be replaced with the complete input filename. - -=item #1 - -Patterns of the form /#\d/ will be replaced with the - -=back - -=head2 Returned Data - - -=head1 EXAMPLES - -=head2 A Rename script - -Below is a simple "rename" script that uses C<globmap> to determine the -source and destination filenames. - - use File::GlobMapper qw(globmap) ; - use File::Copy; - - die "rename: Usage rename 'from' 'to'\n" - unless @ARGV == 2 ; - - my $fromGlob = shift @ARGV; - my $toGlob = shift @ARGV; - - my $pairs = globmap($fromGlob, $toGlob) - or die $File::GlobMapper::Error; - - for my $pair (@$pairs) - { - my ($from, $to) = @$pair; - move $from => $to ; - } - - - -Here is an example that renames all c files to cpp. - - $ rename '*.c' '#1.cpp' - -=head2 A few example globmaps - -Below are a few examples of globmaps - -To copy all your .c file to a backup directory - - '</my/home/*.c>' '</my/backup/#1.c>' - -If you want to compress all - - '</my/home/*.[ch]>' '<*.gz>' - -To uncompress - - '</my/home/*.[ch].gz>' '</my/home/#1.#2>' - -=head1 SEE ALSO - -L<File::Glob|File::Glob> - -=head1 AUTHOR - -The I<File::GlobMapper> module was written by Paul Marquess, F<pmqs@cpan.org>. - -=head1 COPYRIGHT AND LICENSE - -Copyright (c) 2005 Paul Marquess. All rights reserved. -This program is free software; you can redistribute it and/or -modify it under the same terms as Perl itself. |