#!/usr/bin/perl # Filename: make_faq # Author: David Ljung Madison # See License: http://MarginalHacks.com/License # Description: Convert a list of questions/sections to an HTML FAQ-like thingy # # Faq-maker, faq-maker, make me a faq. Ask me an ask. faq me a faq... use strict; umask 022; my $PROGNAME = $0; $PROGNAME =~ s|.*/||; my $CONF = "conf"; my %CONF; ################################################## # Read a configuration file ################################################## sub read_conf { open(CONF,"<$CONF") || die("Couldn't read config file\n"); while() { s/#.*//; # Ignore comments next if (/^\s*$/); # var = "value" <- value can be multiple lines if quotes are used my $var; if (/^\s*(\S+)\s*=\s*(["']?)/) { $var=$1; my ($quote,$line,$read) = ("$2;?",$.,$'); while ($read !~ /(.*)$quote\s*$/) { $CONF{$var}.=$read; die("Runaway quote [$quote] in conf file [$CONF, line $line]\n") unless ($read = ); #print "CONF: $read"; } $read =~ /(.*)$quote\s*$/; # while () doesn't set it first pass :( # Tad kludgy, but simple $CONF{$var}.=$1; $CONF{$var} =~ s/include_file\(([^\)]+)\)/`cat $1`/eg; } else { die("Couldn't understand configuration line $. [$CONF]\n"); } } close(CONF); } sub get_conf { my ($var,$optional,$loop) = @_; my $val = $CONF{$var}; # Expand 'conf(text)' return $val if ($loop>20); # Avoid infinite loops $val =~ s/conf\(([^\)]+)\)/get_conf($1,0,$loop+1)/eg; return $val if defined $val; return undef if ($optional); die("Couldn't find [$var] in configuration file [$CONF]\n"); } ################################################## # HTML stuff ################################################## sub html { return $_[0]; # Unneeded - most of it is in
 anyways..

  $_[0] =~ s/\&/&/g;
  if ($_[0] !~ //>/g;
  }
  $_[0];
}

sub strip_href {
  my ($str) = @_;
  return $str unless ($str =~ /^(.*)]+>(.*)<\/a>(.*)$/);
  return strip_href("$1$2$3");
}

sub space_out {
  my ($a) = @_;
  $a =~ s/(.)/$1 /g;
  $a;
}

# 1 -> one, 2 -> two, 456123400000 -> four hundred fifty six billion one hundred twenty three million four hundred  thousand zero
# A little buggy for the bigger numbers...
sub numify {
  my ($num,$post) = @_;
  return $post if (!$num && $post);
  return (qw(zero one two three four five six seven eight nine))[$num].$post
    if ($num<10);
  return (qw(ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen))[$num-10].$post
    if ($num<20);
  return (qw(twenty thirty forty fifty sixty seventy eighty ninety))[int($num/10)-2]." ".numify($num-int($num/10)*10,$post)
    if ($num<100);
  return numify(int($num/100)," hundred ").numify($num-int($num/100)*100,$post)
    if ($num<1000);
  return numify(int($num/1000)," thousand ").numify($num-int($num/1000)*1000,$post)
    if ($num<1000000);
  return numify(int($num/1000000)," million ").numify($num-int($num/1000000)*1000000,$post)
    if ($num<10000000000);
  return numify(int($num/1000000000)," billion ").numify($num-int($num/1000000000)*1000000000,$post);
}

sub make_section {
  my ($section) = @_;

  my $new_chunk = get_conf("New_Chunk",1) || "q:";

  open(IN,"<$section") || die("Couldn't read [$section]\n");

  my $num=$1 if ($section =~ /(\d+)/);
  die("Need a section number?\n") if (!$num);

  my (@contents,$toc,@text);

  my $out="Section_$num.html";
  open(OUT,">$out") || die("Couldn't write output [$out]\n");
  my $topic=;
  $topic=html($topic);
  $toc .= "
  • $topic\n
      \n"; my $n = 1; while() { if (/^$new_chunk\s+(.*)/) { my $line=$1; $line=html($line); my $name=$line; $name =~ s/[\s\/]/_/g; $name =~ s/<[^>]+>//g; $name =~ s/[\?\!]//g; $name =~ s/^_+//; $name =~ s/_+$//; push(@contents,"
    1. $line
      \n"); $toc .= "
    2. ".(strip_href($line))."\n"; $a=sprintf("%-9s","$n:"); $_="$a$line\n"; $n++; push(@text,$_); } else { push(@text,html($_)); } } close IN; my $header = get_conf("Header"); # Some hardcode variables we replace my $NUMBER = ucfirst(numify($num)); $header =~ s/\$NUMBER/$NUMBER/g; $header =~ s/\$TOPIC/$topic/g; $header =~ s/SPACE_OUT\(([^\)]+)\)/space_out($1)/eg; print OUT $header; print OUT "\n


      \n"; print OUT "Table Of Contents\n"; print OUT "

        @contents


      \n\n"; print OUT "\n

      \n";
        print OUT @text,"\n";
        print OUT "
      \n"; print OUT get_conf("Footer",1); print OUT "
      \n";
        print OUT "\n     ^\n     |\n"x20;
        print OUT "
      \n"; close(OUT); $toc .= "
    \n"; return ($out, $num, $topic, $toc); } ######################### sub main { read_conf(); my (@made,@num,@topics,$toc); # Read and handle all the text sections my $glob=get_conf("Text_Files"); foreach my $txt ( glob($glob) ) { my ($made, $num, $topic, $newtoc) = make_section($txt); push(@made,$made); push(@num,$num); push(@topics,$topic); $toc .= $newtoc; } print "MADE: @made\n"; # Write the short and long indexes my $index = get_conf("Short_Index",1); if ($index) { my $header = get_conf("Short_Header"); $header =~ s/SPACE_OUT\(([^\)]+)\)/space_out($1)/eg; $header =~ s/\$OTHER_HTML/get_conf("Long_Index")/eg; $header =~ s/\$OTHER/Long/g; open(INDEX,">$index") || die("[$PROGNAME] Error: Couldn't write [$index]\n"); print INDEX $header; print INDEX "
      \n"; for(my $i=0; $i<=$#topics; $i++) { print INDEX "
    1. $topics[$i]\n"; } print INDEX "
    \n"; print INDEX get_conf("Short_Footer",1); close(INDEX); } my $index = get_conf("Long_Index",1); if ($index) { my $header = get_conf("Long_Header"); $header =~ s/SPACE_OUT\(([^\)]+)\)/space_out($1)/eg; $header =~ s/\$OTHER_HTML/get_conf("Short_Index")/eg; $header =~ s/\$OTHER/Short/g; open(INDEX,">$index") || die("[$PROGNAME] Error: Couldn't write [$index]\n"); print INDEX $header; print INDEX "
      \n$toc\n
    \n"; print INDEX get_conf("Short_Footer",1); close(INDEX); } } main();