~ubuntu-branches/ubuntu/utopic/texlive-bin/utopic

« back to all changes in this revision

Viewing changes to texk/texlive/linked_scripts/texdef/texdef.pl

  • Committer: Package Import Robot
  • Author(s): Norbert Preining
  • Date: 2012-05-07 10:47:49 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20120507104749-p00ot5sajjbkp1hp
Tags: 2011.20120507-1
* new upstream checkout: uptex 1.10
* drop patches for config file inclusion in (x)dvipdfmx, included upstream
* add man page for etex
* include pmpost patches and build it
* adapt/unfuzzify patches for current sources
* disable mtx building, we have prepmx package in Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env perl
2
2
################################################################################
3
3
#  texdef -- Show definitions of TeX commands
4
 
#  Copyright (c) 2011 Martin Scharrer <martin@scharrer-online.de>
 
4
#  Copyright (c) 2011-2012 Martin Scharrer <martin@scharrer-online.de>
5
5
#
6
6
#  This program is free software: you can redistribute it and/or modify
7
7
#  it under the terms of the GNU General Public License as published by
29
29
if ($scriptname =~ /^(.*)def$/) {
30
30
    $TEX = $1;
31
31
}
 
32
my $TEXOPTIONS = " -interaction nonstopmode ";
32
33
 
 
34
## Variables for options and settings
33
35
my $CLASS      = undef;
34
36
my $USERCLASS  = 0;
35
37
my @PACKAGES   = ();
38
40
my $PRINTVERSION = 0;
39
41
my $TMPDIR     = '';
40
42
my $SHOWVALUE  = 0;
 
43
my $ISENVIRONMENT = 0;
 
44
my $PRINTORIGDEF  = 0;
41
45
my $FINDDEF    = 0;
42
46
my $LISTCMD    = 0;
43
47
my $LISTCMDDEF = 0;
79
83
   @ifdefinable default@ds ds@ @curroptions
80
84
   filename@area filename@base filename@ext
81
85
);
 
86
 
 
87
## Adds arguments to %IGNOREDEF
82
88
sub addignore {
83
89
  my $opt  = shift;
84
90
  my $arg  = shift;
103
109
my $BEGINENVSTR = '%s';
104
110
my $ENDENVSTR   = '%s';
105
111
 
106
 
my $VERSION = 'Version 1.4 -- 2011/07/28';
 
112
my $VERSION = 'Version 1.6 -- 2012/05/02';
107
113
sub usage {
108
114
print << 'EOT';
109
115
texdef -- Show definitions of TeX commands
110
 
Version 1.4 -- 2011/07/28
111
 
Copyright (C) 2011  Martin Scharrer <martin@scharrer-online.de>
 
116
Version 1.6 -- 2012/05/02
 
117
Copyright (C) 2011-2012  Martin Scharrer <martin@scharrer-online.de>
112
118
This program comes with ABSOLUTELY NO WARRANTY;
113
119
This is free software, and you are welcome to redistribute it under certain conditions;
114
120
 
119
125
Other program names are possible. See the 'tex' option.  Command names do not need to start with `\`.
120
126
 
121
127
Options:
122
 
  --tex <flv>, -t <flv>         : Use given flavour of TeX: 'tex', 'latex', 'context'.
 
128
  --tex <format>, -t <format>   : Use given format of TeX: 'tex', 'latex', 'context'.
123
129
                                  Variations of 'tex' and 'latex', like 'luatex', 'lualatex', 'xetex', 'xelatex' are supported.
124
130
                                  The default is given by the used program name: 'texdef' -> 'tex', 'latexdef' -> 'latex', etc.
 
131
  --source, -s                  : Try to show the original source code of the command definition (L).
125
132
  --value, -v                   : Show value of command instead (i.e. \the\command).
 
133
  --Environment, -E             : Every command name is taken as an environment name. This will show the definition of
 
134
                                  both \Macro\foo and \Macro\endfoo if \texttt{foo} is used as command name (L).
126
135
  --preamble, -P                : Show definition of the command inside the preamble.
127
136
  --beforeclass, -B             : Show definition of the command before \documentclass.
128
137
  --package <pkg>, -p <pkg>     : (M) Load given tex-file, package or module depending on whether '*tex', '*latex'
131
140
  --class <class>, -c <class>   : (LaTeX only) Load given class instead of default ('article').
132
141
                                  The <class> can start with `[<classs options>]` and end 
133
142
                                  with `<classname>` or `{<classname>}`.
134
 
  --environment <env>, -p <env> : (M) Show definition inside the given environment <env>.
 
143
  --environment <env>, -e <env> : (M) Show definition inside the given environment <env>.
135
144
  --othercode <code>, -o <code> : (M) Add other code into the preamble before the definition is shown.
136
145
                                  This can be used to e.g. load PGF/TikZ libraries.
137
146
  --before <code>, -b <code>    : (M) Place <code> before definition is shown.
194
203
  push @ENVCODE, [ $opt, $arg ];
195
204
}
196
205
 
197
 
 
 
206
## Define and process options
198
207
Getopt::Long::Configure ("bundling");
199
208
GetOptions (
200
209
   'value|v!' => \$SHOWVALUE,
 
210
   'Environment|E!' => \$ISENVIRONMENT,
201
211
   'version|V!' => \$PRINTVERSION,
202
212
   'tempdir=s' => \$TMPDIR,
203
213
   'find|f!' => sub { $FINDDEF = 1 },
204
214
   'Find|F!' => sub { $FINDDEF = 2 },
 
215
   'source|s!' => \$PRINTORIGDEF,
205
216
   'list|l' => sub { $LISTCMD++ },
206
217
   'list-def|L' => sub { $LISTCMDDEF++ },
207
218
   'list-all' => sub { $LISTCMD=2 },
228
239
 
229
240
# usage() unless @ARGV;
230
241
 
 
242
## Format specific settings
231
243
if ($TEX =~ /latex$/) {
232
244
  $ISLATEX = 1;
233
245
  $BEGINENVSTR = '\begin{%s}' . "\n";
281
293
}
282
294
 
283
295
usage() if not @cmds;
 
296
 
284
297
my $cwd = getcwd();
285
 
$ENV{TEXINPUTS} = '.:' . $cwd . ':' . ($ENV{TEXINPUTS} || '');
 
298
my $OS = $^O;
 
299
my $DIRSEP;
 
300
if ($OS =~ /MSWin/) {
 
301
    $DIRSEP = ';';
 
302
} else {
 
303
    $DIRSEP = ':';
 
304
}
 
305
$ENV{TEXINPUTS} = '.' . $DIRSEP . $cwd . $DIRSEP . ($ENV{TEXINPUTS} || '');
286
306
 
287
307
if (!$TMPDIR) {
288
308
   $TMPDIR = tempdir( 'texdef_XXXXXX', CLEANUP => 1, TMPDIR => 1 );
289
309
}
290
310
chdir $TMPDIR or die "Couldn't change into temporary directory '$TMPDIR'\n";
291
 
my $TMPFILE = 'texdef.tex';
292
 
 
 
311
my $TMPFILE = 'texdeftmp.tex';
293
312
 
294
313
sub testdef {
295
314
    my $cmd = shift;
342
361
    print '\endgroup'."\n";
343
362
}
344
363
 
 
364
#######################################################################################################################
 
365
##  Loop around given commands                                                                                       ##
 
366
#######################################################################################################################
345
367
while (my $cmd = shift @cmds) {
346
368
 
347
369
next if $cmd eq '';
378
400
 
379
401
if ($ISLATEX) {
380
402
    #print "\\nofiles\n";
381
 
    if ($FINDDEF || $LISTCMD) {
 
403
    if ($FINDDEF || $LISTCMD || $PRINTORIGDEF) {
382
404
        # Load the 'filehook' and 'currfile' packages without 'kvoptions' by providing dummy definitions for the 'currfile' options:
383
405
        print '\makeatletter\expandafter\def\csname ver@kvoptions.sty\endcsname{0000/00/00}\let\SetupKeyvalOptions\@gobble\newcommand\DeclareBoolOption[2][]{}\let\DeclareStringOption\DeclareBoolOption';
384
406
        print '\let\DeclareVoidOption\@gobbletwo\def\ProcessKeyvalOptions{\@ifstar{}{}}';
388
410
        print '\makeatletter\expandafter\let\csname ver@kvoptions.sty\endcsname\relax\let\SetupKeyvalOptions\@undefined\let\DeclareBoolOption\@undefined\let\DeclareStringOption\@undefined';
389
411
        print '\let\DeclareVoidOption\@undefined\let\ProcessKeyvalOptions\@undefined\makeatother';
390
412
    }
391
 
    if ($FINDDEF) {
 
413
    if ($FINDDEF || $PRINTORIGDEF) {
392
414
        print '{\expandafter}\expandafter\ifx\csname ' . $cmd . '\expandafter\endcsname\csname @undefined\endcsname' . "\n";
393
415
        print '\AtEndOfFiles{{{\expandafter}\expandafter\ifx\csname ' . $cmd . '\expandafter\endcsname\csname @undefined\endcsname\else' . "\n";
394
416
        print '  \ClearHook\AtEndOfFiles{}\relax';
525
547
 
526
548
select STDOUT;
527
549
 
528
 
open (my $texpipe, '-|', "$TEX '$TMPFILE' ");
 
550
# Removes all '{' and '}' characters which no real braces.
 
551
sub remove_invalid_braces {
 
552
    $_[0] =~ s/\\[\\%]//g; # remove \\ and \%
 
553
    $_[0] =~ s/%.*$//;     # remove line comments
 
554
    $_[0] =~ s/\\[{}]//g;  # remove \{ and \}
 
555
}
 
556
 
 
557
sub env_braces {
 
558
    my $line = shift;
 
559
    remove_invalid_braces $line;
 
560
    my $level = shift || 0;
 
561
    my $count = shift || 0;
 
562
    for my $char (split //, $line) {
 
563
        if ($char eq '{') {
 
564
            $level++;
 
565
        }
 
566
        elsif ($char eq '}') {
 
567
            $level--;
 
568
            if ($level == 0) {
 
569
                $count++;
 
570
            }
 
571
        }
 
572
    }
 
573
    return ($level, $count);
 
574
}
 
575
 
 
576
sub print_orig_def {
 
577
    my $rmacroname = shift;
 
578
    my $file = shift;
 
579
    my $path = shift;
 
580
    my $found = 0;
 
581
    open (my $fh, '<', $path) or return;
 
582
    my $rmacrodef  = qr/
 
583
        ^                                                        # Begin of line (no whitespaces!)
 
584
        (
 
585
        (?:(?:\\global|\\long|\\protected|\\outer)\s*)*       # Prefixes (maybe with whitespace between them)
 
586
        )
 
587
        \\(
 
588
            [gex]?def \s* \\                                   # TeX definitions
 
589
            | (?:new|renew|provide)command\s* \*? \s* {? \s* \\  # LaTeX definitions
 
590
            | (?:new|renew|provide)robustcmd\s* \*? \s* {? \s* \\  # etoolbox definitions
 
591
            | \@namedef{?                                        # Definition by name only
 
592
            | Declare[a-zA-z]+ \s* \*? \s* {? \s* \\             # Declare... definitions
 
593
            | declare[a-zA-z]+ \s* \*? \s* {? \s* \\             # declare... definitions
 
594
        )
 
595
        $rmacroname                                              # Macro name without backslash
 
596
        [^a-zA-Z@]
 
597
        /xms;
 
598
    my $rmacrolet  = qr/
 
599
        ^                                                        # Begin of line (no whitespaces!)
 
600
        \s*
 
601
        (?:
 
602
        (?:(?:\\global)\s*)*       # Prefixes (maybe with whitespace between them)
 
603
        )
 
604
        \\let \s* \\                                             # let
 
605
        $rmacroname                                              # Macro name without backslash
 
606
        \s* =?                                                   # Optional '='
 
607
        \s* \\ ([a-zA-Z@]+)                                      # Second macro
 
608
        /xms;
 
609
    my $renvdef = qr/
 
610
        ^\s*                                                     # Begin of line (no whitespaces!)
 
611
        \\(
 
612
            (?:new|renew|provide)environment\s* { \s*            # LaTeX definitions
 
613
        )
 
614
        ($rmacroname)                                            # Environment names follow same rules as macro names
 
615
        \s* }                                                    # closing brace
 
616
        (.*)                                                     # Rest of line
 
617
        /xms;
 
618
    while (my $line = <$fh>) {
 
619
        if ($line =~ $rmacrodef) {
 
620
            $found = 1;
 
621
            print "% $file, line $.:\n";
 
622
            print $line;
 
623
            remove_invalid_braces $line;
 
624
            my $obrace = $line =~ tr/{/{/;
 
625
            my $cbrace = $line =~ tr/}/}/;
 
626
            while ($obrace != $cbrace) {
 
627
                my $line = <$fh>;
 
628
                print $line;
 
629
                remove_invalid_braces $line;
 
630
                $obrace += $line =~ tr/{/{/;
 
631
                $cbrace += $line =~ tr/}/}/;
 
632
            }
 
633
            print "\n";
 
634
            last;
 
635
        }
 
636
        elsif ($line =~ $rmacrolet) {
 
637
            my $letcmd = $1;
 
638
            $found = 1;
 
639
            print "% $file, line $.:\n";
 
640
            print $line;
 
641
            print "\n";
 
642
            unshift @cmds, $letcmd;
 
643
            last;
 
644
        }
 
645
        elsif ($line =~ $renvdef) {
 
646
            $found = 2;
 
647
            print "% $file, line $.:\n";
 
648
            print $line;
 
649
            my ($level, $count) = env_braces $line;
 
650
            while ($count < 3) {
 
651
                my $line = <$fh>;
 
652
                print $line;
 
653
                ($level, $count) = env_braces $line, $level, $count;
 
654
            }
 
655
            print "\n";
 
656
            last;
 
657
        }
 
658
    }
 
659
    close($fh);
 
660
    return $found;
 
661
}
 
662
 
 
663
open (my $texpipe, '-|', "$TEX $TEXOPTIONS \"$TMPFILE\" ");
529
664
 
530
665
my $name = '';
531
666
my $definition = '';
532
667
my $errormsg = '';
 
668
my $origdeffound = 0;
533
669
 
534
670
while (<$texpipe>) {
535
671
  if (/^::\s*(.*)/) {
541
677
            $line =~ s/$1/$path/;
542
678
        }
543
679
    }
544
 
    print "$line\n";
 
680
    if ($PRINTORIGDEF) {
 
681
        if ($line =~ /first defined in "(.*)"/) {
 
682
            my $file = $1;
 
683
            my $path = `kpsewhich "$file"`;
 
684
            chomp $path;
 
685
            $origdeffound = print_orig_def($cmd, $file, $path);
 
686
        }
 
687
        elsif ($line =~ /is defined by \(La\)TeX./) {
 
688
            my $file = 'latex.ltx';
 
689
            my $path = `kpsewhich "$file"`;
 
690
            chomp $path;
 
691
            $file = $path if $FINDDEF > 1;
 
692
            $origdeffound = print_orig_def($cmd, $file, $path);
 
693
        }
 
694
        if (!$origdeffound) {
 
695
            print "Source code definition of '$cmd' could not be found.\n";
 
696
            print "$line\n";
 
697
        }
 
698
    }
 
699
    else {
 
700
        print "$line\n";
 
701
    }
545
702
    next;
546
703
  }
547
704
  if (/^(:TEXDEF:\s*(.*))/) {
649
806
            print "\n";
650
807
        }
651
808
    }
652
 
} else {
 
809
} elsif (!$PRINTORIGDEF || !$origdeffound) {
653
810
    print "\n(in preamble)" if $inpreamble;
654
811
    print "\n$name:\n$definition\n\n";
655
812
}
656
813
 
657
814
testdef($origcmd,$definition);
 
815
if ($ISENVIRONMENT && $origdeffound < 2 && $cmd !~ /^end/) {
 
816
    unshift @cmds, 'end' . $cmd;
 
817
}
658
818
 
659
819
}
660
820