UNB/ CS/ David Bremner/ blog/ files/ hl-beamer.pl
#!/usr/bin/perl
use Text::Tabs;
use Getopt::Std;
use strict;


my $default_ov_env='visibleenv';
my %options;

getopts('c:k:s:S',\%options);

my $strip_spaces=$options{s} || 0;

my $commentstr=$options{c};
if (!defined($commentstr)){
  print STDERR "usage: $0 -c commentstr [options]\n";
  exit 1;
}

my $keep_all = 1;

my %keep=();
my %current=();

$keep{comment}=0;
$keep{omit}=0;

my $keep_list=$options{k};

if (defined($keep_list)){
  my @sections=split(",", $keep_list);
  map { $keep{$_} =1; $current{$_}=0; } @sections;
  $keep_all=0;
}

sub maybe_print{
  my $string=shift;
  my $skip=0;
  my $match=$keep_all;
  if (!$match){
    map { $match += ( $current{$_} && $keep{$_} ); } keys %keep;
  }
  map { $skip += ( $current{$_} && !$keep{$_} ); } keys %keep;
  if (!$skip && $match){
    $string = expand $string;
    $string =~ s/^[ ]{$strip_spaces}//;
    print $string;
  }
}

my %overlayenv = (
		  'u' => 'uncoverenv',
		  'v' => 'visibleenv',
		  's' => 'version'
		 );

my $regex=qr{
	      ^ \s* \Q$commentstr\E \s* \@ ([<>()\:]) \s* ([a-zA-Z_]*)(.*)$
	    }x;

my @ov_stack=();
my @sec_stack=();

LINE: 
while(<>){
  if (m/$regex/){
    if (!defined($options{S})){
      my $op = $1;
      my @args = ($2,$3);
      my ($env,$envarg);

      if ($op eq ':') {
	maybe_print($commentstr.'@highlight \hspace*{2em}$\vdots$\\\\'."\n");
      } elsif ($op eq '<') {

        $env =  $args[0] ? $overlayenv{$args[0]} : $default_ov_env;
        $envarg =  $args[1] ? '<'.$args[1].'>' : '<+->';

        maybe_print(sprintf $commentstr.'@highlight\\\\begin{%s}%s'."\n",$env,$envarg);
	push (@ov_stack,$env);
	
      } elsif ($op eq '('){

	$env =  $2;
	$current{$env}=1;

	push(@sec_stack,$env)
	  
      } elsif ($op eq '>') {

	maybe_print(sprintf $commentstr.'@highlight\\\\end{%s}'."\n",pop(@ov_stack));

      } elsif ($op eq ')') {

	$current{pop(@sec_stack)}=0;

      } 
    }
  } else {
    maybe_print($_);
  }
};


=head1 NAME

hl-beamer - Preprocessor for hightlight to generate beamer overlays.

=head1 SYNOPSIS

=over 

=item B<hl-beamer> -c // InstructiveExample.java | highlight -S java -O latex > figure1.tex

=back

=head1 DESCRIPTION

B<hl-beamer> looks for single line comments (with syntax specified by
B<-c>) These comments can start with B<@> followed by some codes to
specify beamer overlays or sections (just chunks of text which can be
selectively included).

=head1 OPTIONS

=over

=item B<-c> F<commentstring> Start of single line comments

=item B<-k> F<section1,section2> List of sections to keep (see B<@(> below).

=item B<-s> F<number>  strip F<number> spaces from the front of every line
      (tabs are first converted to spaces using Text::Tabs::expand)

=item B<-S> strip all directive comments.

=back

=head1 CODES

=over

=item B<@(> F<section> named section. Can be nested. Pass -k
      F<section> to include in output. The same name can (usefully) be
      re-used. Sections B<omit> and B<comment> are omitted by default.

=item B<@)> close most recent section.

=item B<@<> [F<overlaytype>] [F<overlayspec>] define a beamer
overlay. F<overlaytype> defaults to visibleenv if not specified.
F<overlayspec> defaults to B<+-> if not specified.

=item B<@>> close most recent overlay

=back

=head1 EXAMPLE

Example input follows. I would probably process this with

=over

=item hl-beamer -s 4 -k encodeInner

=back

=head2 Sample Input

 // @( omit
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.Serializable;
 import java.util.Scanner;
 // @)

     // @( encoderInner
     private int findRun(int inRow, int startCol){
	 // @<
	 int value=bits[inRow][startCol];
	 int cursor=startCol;
	 // @>

	 // @<
	 while(cursor<columns && 
	       bits[inRow][cursor] == value) 
	     //@<
	     cursor++;
	     //@>
	 // @>

	 // @<
	 return cursor-1;
	 // @>
     }
     // @)

=head1 BUGS AND LIMITATIONS

Currently F<overlaytype> and F<section> must consist of upper and
lower case letters and or underscores. This is basically pure sloth on
the part of the author.

=head1 SEE ALSO


B<highlight>, B<pdflatex>

=head1 LICENSE

Copyright (C) 2011 by David Bremner

This script is free software; you can redistribute it and/or modify it
under the terms of either:

=over

=item a) the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version, or

=item b) the "Artistic License", version 2 or later.

=back