#!/usr/bin/env tclsh
# cleanlatex : Resolve inputs and remove commented lines from LaTeX source
# Written April-May 2005 by Peter Shawhan

# Copyright 2005, 2006, 2012 Peter Shawhan

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#=============================================================================
proc Main {} {
    global argc argv

    #-- Check arguments
    if { $argc != 1 } {
	puts "Wrong number of arguments"
	ShowUsage
	exit 1
    }

    set texfile [lindex $argv 0]
    #-- If file does not exist, try adding '.tex'
    if { ! [file exists $texfile] && [file exists "$texfile.tex"] } {
	set texfile "$texfile.tex"
    }

    #-- Construct name of output file, and open it
    if [regexp {^(.+)\.tex} $texfile - basename] {
	set outfile "${basename}_clean.tex"
    } else {
	set outfile "${texfile}_clean"
    }
    if [catch {
	set outfid [open $outfile w]
    } errmsg] {
	puts "Error opening $outfile for writing:\n$errmsg"
	exit 1
    }

    #-- Open the main input file
    set flevel 1
    if [catch {
	set fid($flevel) [open $texfile]
    } errmsg] {
	puts "Error opening $texfile for reading:\n$errmsg"
	close $outfid
	catch {file delete $outfile}
	exit 1
    }

    #-- Report this filename
    puts -nonewline [string repeat " " [expr {2*($flevel-1)}]]
    puts $texfile

    #-- Loop over lines in the file
    while { $flevel > 0 } {
	#-- Read a line from the current level
	while { [gets $fid($flevel) line] >= 0 } {

	    #-- Completely ignore lines which consist only of a comment
	    if { [regexp {^\s*%} $line] } {
		#-- Ignore this line entirely
		continue
	    }

	    #-- Protect escaped backslashes by replacing them temporarily
	    regsub -all {\\\\} $line {__DblBackSlashProxy__} line

	    #-- Remove any comment at the end of a line
	    regsub {([^\\])%.*} $line {\1} line

	    #-- Restore any escaped backslashes
	    regsub -all {__DblBackSlashProxy__} $line {\\\\} line

	    #-- See if the line contains an '\input{}' or '\bibliography'
	    if { [regexp {^(.*)\\input{([^\}]+)}(.*)$} $line \
		      - firstpart inputfile remainder($flevel) ] } {

		#-- Write out the first part immediately
		puts -nonewline $outfid $firstpart

		#-- Open the new file; if file doesn't exist, try adding '.tex'
		if { ! [file exists $inputfile] && \
			 [file exists "$inputfile.tex"] } {
		    set inputfile "$inputfile.tex"
		}
		incr flevel
		if [catch {
		    set fid($flevel) [open $inputfile]
		} errmsg] {
		    puts "Error opening $inputfile for reading:\n$errmsg"
		    close $outfid
		    catch {file delete $outfile}
		    exit 1
		}

		puts -nonewline [string repeat " " [expr {2*($flevel-1)}]]
		puts $inputfile

		#-- Now we read from the new file until we reach the end...

	    } elseif { [regexp {^(.*)\\bibliography{([^\}]+)}(.*)$} $line \
		      - firstpart bibdb remainder($flevel) ] } {
		#-- We assume that BibTeX has been run for the original paper

		#-- Write out the first part immediately
		puts -nonewline $outfid $firstpart

		#-- Run bibtex to make sure the *.bbl file is up to date
		puts -nonewline [string repeat " " [expr {2*($flevel-1)}]]
		set texbase [file rootname [file tail $texfile]]
		puts "  ** Running bibtex to make sure $texbase.bbl is up to date..."
		exec bibtex $texbase

		#-- Open the new file
		incr flevel
		set newfile "$texbase.bbl"
		if [catch {
		    set fid($flevel) [open $newfile]
		} errmsg] {
		    puts "Error opening $newfile for reading:\n$errmsg"
		    close $outfid
		    catch {file delete $outfile}
		    exit 1
		}

		puts -nonewline [string repeat " " [expr {2*($flevel-1)}]]
		puts $newfile

		#-- Now we read from the new file until we reach the end...
		
	    } else {
		#-- Just echo the line to the output file
		puts $outfid $line
	    }

	}
	#-- End of this file
	close $fid($flevel)
	incr flevel -1
	#-- If there is a remainder from the line in the previous file,
	#-- write it out now
	if { $flevel > 0 && [string length $remainder($flevel)] } {
	    puts $outfid $remainder($flevel)
	}

	#-- If $flevel>0, go back and read from this file
    }

    #-- Close the output file
    close $outfid

    puts "Created $outfile"
}

#=============================================================================
proc ShowUsage {} {
    set script [info script]
    puts "\nUsage: $script <file>"
    puts "<file> must be a LaTeX source file.  The extension '.tex' may be omitted."
    puts ""
    puts "This script 'cleans' the source of a LaTeX document, removing comments and"
    puts "following \\input{} commands to produce a single LaTeX source file containing"
    puts "everything except the figures.  This script also handles the \\bibliography{}"
    puts "command (if any) by running bibtex and replacing it with the contents of the"
    puts "bbl file.  The name of the ouput file is based on the name of the input file,"
    puts "but with '_clean' inserted.  For instance, if the original input file is"
    puts "'mypaper.tex', then this script produces a clean version called"
    puts "'mypaper_clean.tex'."
    puts ""
}

#=============================================================================
#-- Now run the program
Main
