#!/usr/bin/perl

=head1 NAME
   abcincips - Generate ABC "incipits" file from ABC tunes

=head1 SYNOPSIS
   abcincips "title" [file]...  >foo.abc

=head1 DESCRIPTION
   This  program reads through the input file(s), or stdin if no files
   are named, looking for abc tunes. When it finds one, it outputs the
   first  two bars of the tune, with the tune name in the place of the
   first "guitar chord".  Other chords are deleted.

   The resulting file can be fed to abc2ps or  abcmtex  to  produce  a
   page of musical reminders of how the tunes start.

   Tunes will be in the same order they are in the files. Alphabetical
   order is recommended, but any organization that makes sense to  you
   may be used.

   The  output  contains  abc2ps commands that will produce very small
   music and names.

=head1 BUGS
   If a tune contains no L:  line, there will be none in  the  output,
   and  the L:  line from the preceding tune will be used.  This isn't
   always what you want. Fix: Include L: lines in all your tunes, even
   when they aren't needed.

   The  T:,  L:   and  K:   lines must be at the start of a line to be
   recognized.

=head1 AUTHOR
   <a href="mailto:jc@trillian.mit.edu">John Chambers</a>
=cut
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

$| = 1;
($P = $0) =~ s".*/"";	# Our name, minus directories
$V = $ENV{"V_$P"} || 1;	# Verbose/trace/debug level
$exitstat = 0;			# Set to nonzero for failure
$fmts = 0;				# Whether to generate default formatting info

$title = shift || "Tunes";
if ($fmts) {
	print "%%scale 0.4\n";
	print "%%maxshrink 1\n";
	print "%%staffwidth    16.0cm\n";
	print "%%leftmargin    2.0cm\n";
	print "%%topmargin     0.2cm\n";
	print "%%topspace      0.2cm\n";
	print "%%titlespace    0.0cm\n";
	print "%%composerspace 0.0cm\n";
	print "%%musicspace    0.0cm\n";
	print "%%gchordfont    Helvetica 14\n";
	print "%%staffsep      40\n";
	print "%%maxshrink 1\n";
	print "%%maxshrink 1\n";
	print "%%maxshrink 1\n";
}

$min   =  15;	# Min number of notes required.
$page  =   0;	# Page counter, for titles.
$tunes =   0;	# Tune counter, for page eject.
$tpl   =   2;   # Tunes per line.
$tpp   =  84;	# Max tunes per page.
#$tpk  =  50;	# Max tunes per kludge.

sub ttl {
	++ $page;
	print "\n%%page\n\n";
	print "X: $page\n";
	print "T: $title p.$page\n";
	print "K: C\n";
}

$| = 1;
$t = 0;
$s = 0;	# State

for $f (@ARGV) {
	if (!open(F,$f)) {
		print STDERR "$0: Can't read \"$f\" [$!]\n";
		next;
	}
    print "\n% File: $f\n" if $V>1;
	while ($l = <F>) {
		$l =~ s/\s+$//;
		if ($l =~ /^T:\s*(.*)/) {
            $tt = $1;
            $tt =~ s/\\[`'"]//g; # Strip out some diacriticals
			$T[$t++] = $tt;
			$s = 1;		# State: in header.
		} elsif ($l =~ /^X:\s*\d+/) {
			$s = 1;		# State: in header.
			$t = 0;		# Start over with new title.
		} elsif ($l =~ /^L:\s*([\d\/]+)/) {
			$L = $1;
		} elsif ($l =~ /^K:\s*([\w\^_=]+)/) {
			if ($s == 1) {
				$K = $1;
				$s = 2;	# State: in music.
			}
		} elsif ($l =~ /^[A-Z]:/) {
		} elsif ($l =~ /^%/) {
		} elsif ($s == 2) {
			if ($m = &strip($l)) {	# Do we have a line of music?
				if (($tunes % $tpp) == 0) {
					&ttl();
#				} elsif (($tunes % $tpk) == 0) {
#					print "P:\n";;
				} 
				$tunes ++;
                $eol = $tunes % $tpl ? "\\\n" : "\n";
				$ttl = $T[0];
			#	print "[K:$K]\\\n";
			#	print "[L:$L]\\\n";
				print "[K:$K][L:$L] [| \"$ttl\" $m |]$eol";
				$s = 3;	# State: Done with this tune.
				$t = 0;	# Start over with new title.
			} 
		}
	}
}

while ($tunes % $tpl) {print ' y3' x $min; ++$tunes;}
print "\n\n";   # Make sure there's a final blank line and a newline.
exit 0;

sub strip {
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local($l) = @_;
	local($bars,$music,$notes) = (1,'',0);
	while ($l =~ m"\\+\s*$") {		# Continued?
		$l =~ s"\s*\\+\s*$" ";
		$l .= <F>;
	}
	while ($l) {
		if ($l =~ s'^\s+'') {		# White space?
			$music = $music . ' ' if $music;	# Convert to single space.
		} elsif ($l =~ s'^"([^"]*)"'') {	# Discard a chord.
            print "%strip: Chord \"$1\"\n" if $V>1;
		} elsif ($l =~ s'^([A-Ga-gZz][\/\^_=\',0-9]*)'') {	# Notes?
            print "%strip: Note: \"$1\"\n" if $V>1;
			$music = $music . $1;
            ++$notes;
		} elsif ($l =~ s/^\[([^]|]+)\]//) {	# Written-out chord?
            print "%strip: chord \"$1\"\n" if $V>1;
			$music = $music . "[$1]";       # Accumulate the music
            ++$notes;           # Count the accumulated notes
#		} elsif ($l =~ s/^(\[\||\|\]|:*\|+:*)//) {	# Bar line?
		} elsif ($l =~ s/^(\[\|\]?|\|\]|:*\|+:*)//) {	# Bar line?
            print "%strip: BarLn \"$1\" bars=$bars notes=$notes.\n" if $V>1;
			return $music if ($bars >= 2 && $notes >= $min);
			if ($notes) {$music = $music . $1; ++$bars}
		} elsif ($l =~ s/^(.)//) {	# Anything else
            print "%strip: misc: \"$1\"\n" if $V>1;
			$music = $music . $1;
		}
	}
	return $music;
}
