#!/usr/bin/perl -w # $LynxId: cfg2html.pl,v 1.21 2014/01/08 22:49:46 tom Exp $ # # This script uses embedded formatting directives in the lynx.cfg file to # guide it in extracting comments and related information to construct a # set of HTML files. Comments begin with '#', and directives with '.'. # Directives implemented: # # h1 {Text} # major heading. You may specify the same major heading in # more than one place. # h2 {Text} # minor heading, i.e. a keyword. # ex [number] # the following line(s) are an example. The [number] defaults # to 1. # nf [number] # turn justification off for the given number of lines, defaulting # to the remainder of the file. # fi # turn justification back on # url text # embed an HREF to external site. # use strict; use Getopt::Std; use vars qw($opt_a $opt_m $opt_s); use vars qw(@cats); use vars qw(%cats); use vars qw(@settings_avail); use vars qw(%settings_avail); # Options: # -a show all options, not only those that are available. # -m mark unavailable options with an '*'. Data for this is read # from standard input. # -s sort entries in body.html &getopts('ams'); if ( defined $opt_m ) { my $l; my @settings_ = ; %settings_avail = (); foreach $l (@settings_) { chop $l; if ( $l =~ /^[[:alpha:]_][[:alnum:]_]*$/ ) { $settings_avail{ uc $l } = 1; } } } else { $opt_a = 1; } # This sub tells whether the support for the given setting was enabled at # compile time. sub ok { my ($name) = @_; my $ret = defined( $settings_avail{ uc $name } ) + 0; $ret; } if ( $#ARGV < 0 ) { &doit("lynx.cfg"); } else { while ( $#ARGV >= 0 ) { &doit( shift @ARGV ); } } exit(0); # process a Lynx configuration-file sub doit { my ($name) = @_; my $n; # Ignore our own backup files if ( $name =~ ".*~" ) { return; } # Read the file into an array in memory. open( FP, $name ) || do { print STDERR "Can't open $name: $!\n"; return; }; my (@input) = ; close(FP); for $n ( 0 .. $#input ) { chop $input[$n]; # trim newlines $input[$n] =~ s/\s*$//; # trim trailing blanks $input[$n] =~ s/^\s*//; # trim leading blanks } &gen_alphatoc(@input); @cats = &gen_cattoc(@input); &gen_body(@input); } sub gen_alphatoc { my (@input) = @_; my @minor; my ( $n, $m, $c, $d, $need_p ); my $output = "alphatoc.html"; open( FP, ">$output" ) || do { print STDERR "Can't open $output: $!\n"; return; }; print FP <<'EOF'; lynx.cfg settings by name EOF $m = 0; for $n ( 0 .. $#input ) { if ( $input[$n] =~ /^\.h2\s*[[:upper:]][[:upper:][:digit:]_]*$/ ) { $minor[$m] = $input[$n]; $minor[$m] =~ s/^.h2\s*//; $m++ if ( ok( $minor[$m] ) || defined $opt_a ); } } @minor = sort @minor; # index by the first character of each keyword $c = ' '; $need_p = 1; for $n ( 0 .. $#minor ) { $d = substr( $minor[$n], 0, 1 ); if ( $d ne $c ) { if ($need_p) { printf FP "

"; $need_p = 0; } printf FP "%s \n", $d, $d; $c = $d; } } # index by the first character of each keyword $c = ' '; for $n ( 0 .. $#minor ) { $d = substr( $minor[$n], 0, 1 ); if ( $d ne $c ) { printf FP "

%s

\n", $d, $d; $need_p = 1; $c = $d; } my $avail = ok( $minor[$n] ); my $mark = ( !$avail && defined $opt_m ) ? "*" : ""; if ( defined $opt_a || $avail ) { if ($need_p) { printf FP "

"; $need_p = 0; } printf FP "%s  \n", $minor[$n], $minor[$n] . $mark; } } my $str = <<'EOF'

To list of settings by category EOF . ( defined $opt_a && defined $opt_m ? "

Support for all settings suffixed with '*' was disabled at compile time.\n" : "" ) . <<'EOF' EOF ; print FP $str; close(FP); } # This uses the associative array $cats{} to store HREF values pointing into # the cattoc file. # # We could generate this file in alphabetic order as well, but choose to use # the order of entries in lynx.cfg, since some people expect that arrangement. sub gen_body { my @input = @_; my ( $n, $c ); my @h2; my $output = "body.html"; open( FP, ">$output" ) || do { print STDERR "Can't open $output: $!\n"; return; }; print FP <<'EOF'; Description of settings in lynx configuration file EOF my $l; my $t; my $d = -1; my $p = 0; my $m = 0; my $h1 = ""; my $sp = ' '; my $ex = 0; my $nf = 0; my $any = 0; my $first = 0; my $next = 0; my $left = 0; my $needp = 0; my %keys; undef %keys; my @optnames; my %optname_to_fname; #this maps optname to fname - will be used #for alphabetical output of the content my $curfilename = "tmp000"; #will be incremented each time my $tmpdir = "./"; #temp files will be created there close(FP); for $n ( 0 .. $#input ) { if ($next) { $next--; next; } $c = $input[$n]; my $count = $#input; my $once = 1; if ( $c =~ /^\.h1\s/ ) { $h1 = 1; $h1 = $c; $h1 =~ s/^.h1\s*//; $m = 0; $first = 1; undef %keys; next; } elsif ( $c =~ /^\.h2\s/ ) { $c =~ s/^.h2\s*//; $h2[$m] = $c; $keys{$c} = 1; $m++; next; } elsif ( $c =~ /^\./ ) { my $s = $c; $s =~ s/^\.[[:lower:]]+\s//; if ( $s =~ /^[[:digit:]]+$/ ) { $count = $s; $once = $s; } } if ( $c =~ /^\.ex/ ) { $ex = $once; printf FP "

Example%s:

\n", $ex > 1 ? "s" : ""; $needp = 1; } elsif ( $c =~ /^\.url/ ) { my $url = $c; $url =~ s/^\.url\s+//; printf FP "

%s

\n", $url, $url; $needp = 1; } elsif ( $c =~ /^\.nf/ ) { $needp = 0; printf FP "
\n";
            $nf = $count;
        }
        elsif ( $c =~ /^\.fi/ ) {
            printf FP "
\n"; $nf = 0; $needp = 1; } elsif ( $c =~ /^$/ ) { if ( $m > 1 ) { my $j; for $j ( 1 .. $#h2 ) { close(FP); ++$curfilename; push @optnames, $h2[$j]; open( FP, ">$tmpdir/$curfilename" ) || do { print STDERR "Can't open tmpfile: $!\n"; return; }; $optname_to_fname{ $h2[$j] } = $curfilename; printf FP "
\n"; printf FP "

%s\n", $h2[$j], $h2[$j]; if ( $h1 ne "" ) { printf FP " – %s", $cats{$h1}, $h1; } printf FP "

\n"; printf FP "

Description

\n"; printf FP "

Please see the description of " . "%s\n", $h2[0], $h2[0]; $needp = 0; } @h2 = ""; } $m = 0; $first = 1; } elsif ( $c =~ /^[#[:alpha:]]/ && $m != 0 ) { if ($first) { close(FP); ++$curfilename; push @optnames, $h2[0]; open( FP, ">$tmpdir/$curfilename" ) || do { print STDERR "Can't open tmpfile: $!\n"; return; }; $optname_to_fname{ $h2[0] } = $curfilename; if ($any) { printf FP "


\n"; } printf FP "

%s\n", $h2[0], $h2[0]; if ( $h1 ne "" ) { printf FP " – %s", $cats{$h1}, $h1; } printf FP "

\n"; printf FP "

Description

\n"; $needp = 1; $any++; $first = 0; } # Convert tabs first, to retain relative alignment $c =~ s#^\t#' 'x8#e; while ( $c =~ /\t/ ) { $c =~ s#(^[^\t]+)\t#$1 . $sp x (9 - (length($1) % 8 ))#e; } # Strip off the comment marker $c =~ s/^#//; # and convert simple expressions: $c =~ s/&/&/g; $c =~ s/>/>/g; $c =~ s/$1<\/strong>"/g; my $k = 0; if ( $c =~ /^[[:alpha:]_][[:alnum:]_]+:/ ) { $t = $c; $t =~ s/:.*//; $k = $keys{$t}; } if ( $c =~ /^$/ ) { if ($nf) { printf FP "\n"; } else { $p = 1; } } elsif ( $ex != 0 ) { printf FP "%s", $needp ? "

" : "
"; $needp = 0; printf FP "%s
\n", $c; $ex--; } elsif ($k) { if ( $d != $n && !$nf ) { printf FP "

Default value

\n"; printf FP "

"; $needp = 0; } $c =~ s/:$/:none<\/em>/; $c =~ s/:/<\/code>:/; $c = "" . $c . ""; if ( !$nf ) { $c .= "
"; } printf FP "%s\n", $c; $d = $n + 1; } else { if ( $p && !$nf ) { printf FP "

\n"; $needp = 0; } $p = 0; if ( $input[ $n + 1 ] =~ /^#\s*==/ ) { $c = "
$c"; if ( !$nf ) { $c .= "
"; } $next++; } printf FP "

" if $needp; $needp = 0; printf FP "%s\n", $c; } if ( $nf != 0 && $nf-- == 0 ) { printf FP "\n"; } } } close(FP); # Here we collect files with description of needed lynx.cfg # options in the proper (natural or sorted) order. open( FP, ">>$output" ) || do { print STDERR "Can't open $output: $!\n"; return; }; { my @ordered = ( defined $opt_s ? ( sort keys(%optname_to_fname) ) : @optnames ); printf FP "

"; if ( defined $opt_s ) { print FP "Options are sorted by name.\n"; } else { print FP "Options are in the same order as lynx.cfg.\n"; } foreach $l (@ordered) { my $fnm = $tmpdir . $optname_to_fname{$l}; open( FP1, "<$fnm" ) || do { print STDERR "Can't open $fnm: $!\n"; return; }; my $avail = ok($l); if ( defined $opt_a || $avail ) { my @lines = ; print FP @lines; if ( !$avail && defined $opt_m ) { print FP <<'EOF';

Support for this setting was disabled at compile-time. EOF } } close(FP1); } foreach $l ( values(%optname_to_fname) ) { unlink $l; } } print FP <<'EOF'; EOF close(FP); } sub gen_cattoc { my @input = @_; my @major; my %descs; my %index; my ( $n, $m, $c, $d, $found, $h1, $nf, $ex, $count, $once ); my $output = "cattoc.html"; open( FP, ">$output" ) || do { print STDERR "Can't open $output: $!\n"; return; }; print FP <<'EOF'; lynx.cfg settings by category

These are the major categories of configuration settings in Lynx:

\n"; for $n ( 0 .. $#major ) { printf FP "\n"; printf FP "

%s

\n", $cats{ $major[$n] }, $major[$n]; if ( $descs{ $major[$n] } !~ /^$/ ) { printf FP "

Description

\n

%s\n", $descs{ $major[$n] }; } $c = $index{ $major[$n] }; if ( $c ne "" ) { my @c = split( /\n/, $c ); @c = sort @c; printf FP "

Here is a list of settings that belong to this category\n"; printf FP "

    \n"; for $m ( 0 .. $#c ) { my $avail = ok( $c[$m] ); my $mark = ( !$avail && defined $opt_m ) ? "*" : ""; printf FP "
  • %s\n", $c[$m], $c[$m] . $mark; } printf FP "
\n"; } } my $str = <<'EOF'

To list of settings by name EOF . ( defined $opt_a && defined $opt_m ? "

Support for all settings suffixed with '*' was disabled at compile time." : "" ) . <<'EOF' EOF ; print FP $str; close(FP); return @cats; }