I really liked this. However, I usually separate my documents into multiple files, so that single file itch got to be scratched.
#! /usr/bin/perl -w
#
# LaTeX Outline Generator
#
use strict ;
use warnings ;
use vars qw($title $author $date);
use IO::File;
$|++ ;
BEGIN {
# Set some defaults for the page header.
$title = 'LaTeX Document' ;
$author = 'Unknown Author' ;
$date = (localtime)[3] . ' ' .
qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )[(localtime)[
+4]]
. ' ' . ( (localtime)[5] + 1900 ) ;
print '-' x 70 . "\n" ;
}
END {
print '-' x 70 . "\n" ;
}
sub open_file {
my $file = shift;
my $fh = IO::File->new("<$file");
if (defined $fh) {
scan_tex($fh);
} else {
die("Cannot read file '$file'");
}
$fh->close;
}
sub scan_tex {
local $_;
my $file = shift;
my $inside_block = 0;
my $curly_open = 0;
my $curly_close = 0;
while ( <$file> )
{
chomp;
next if m/^%/ or $_ eq '';
if ( m/\\newcommand/ )
{
$inside_block = 1;
}
if ( $inside_block )
{
$curly_open += tr/{//;
$curly_close += tr/}//;
if ( $curly_open eq $curly_close )
{
$inside_block = 0;
}
else
{
next;
}
}
if ( m/\\input{([^}]+)}/ ) {
open_file($1);
next;
}
# Grab doc titles, converting newlines to hyphens.
if ( m/title\{(.*)\}/ )
{
$title = $1 ;
$title =~ s/\\\\/-/g ;
}
# Grab author names, converting \and's to commas.
elsif ( m/author\{(.*)\}/ )
{
$author = $1 ;
$author =~ s/\s*\\and\s*/, /g ;
}
# Grab document dates.
elsif ( m/date\{(.*)\}/ and $1 ne '\today')
{
$date = $1 ;
}
# Once the preamble's been processed, print the page header.
elsif ( m/begin\{document\}/ )
{
print "$title\n$author\n$date\n" . '-' x 70 . "\n" ;
}
# When a section tag is encountered, check it's
# depth and print apprpriately.
elsif ( m/(part|chapter|section)\{(.*)\}/ )
{
my %tree = (
part => 0,
chapter => 1,
section => 2
);
my $level = $tree{$1};
$level++ while s/\\sub/\\/g ;
print_node($2, $level);
}
}
}
sub print_node {
my ($node, $level) = @_;
unless ($node) { return }
# Define the symbols to use to denote organizational levels.
my @symbol_list = ( '*', '-', '+' ) ;
my $symbol = $symbol_list[ $level ] ;
print " " x ( ( $level * 4 ) + 2 ) ;
print "$symbol_list[ $level ] $node\n" ;
}
if ( scalar(@ARGV) > 0 )
{
open_file($_) while $_ = shift;
}
else
{
scan_tex(*STDIN);
}
exit( 0 ) ;
I also tried to add code to skip command definitions, where unrelated section{} commands could get caught and printed.
Last but not least, besides section{} commands, part{} and chapter{} commands are caught and listed now.
As a result it got a little bit puffier (bloat?).
--
Alper Ersoy |