#!/bin/bash # AutoTeX -- a utility which will compile a LaTeX file everytime it changes # Enable extended glob support (i.e. better expansion) shopt -s extglob # The command which will compile the file TeXCOMMAND="pdflatex" # The file to be compiled TeXFILE="" ################################################################################ # Print an error onto the screen function error { echo -e "$LIGHTRED$1$NC" } # function error ################################################################################ # Wait for the argument-supplied files to change in some way using the most # appropriate method available on this system function waitUntilChanged { # Watch the state of the files until it changes watchList=$(fileWatchList) # If the files have changed since last run... if filesNotChanged $watchList; then ## Use inotify if possible #if which inotifywait &>/dev/null; then # inotifywait $watchList &>/dev/null #else while filesNotChanged $watchList &>/dev/null; do command="" if read -s -n 1 -t 0.1 command; then break fi done #fi fi # Wait for the files to come back if ! ls $watchList &>/dev/null; then if [ "$compileCount" -gt 1 ]; then compileMessage=" (Compiled $compileCount times)" else compileMessage="" fi echo -n "Waiting for files to be written..." timeout=1 # Timeout after 10 attempts while [ "$timeout" -lt 10 ] && ! ls $watchList &>/dev/null; do echo -n "." # Cancel wait if read -t 0.$timeout; then break fi let timeout+=1 done echo if [ "$timeout" == "10" ]; then error "Some files are missing..." return 1 fi fi # Update the file info for next time filesNotChanged $watchList &>/dev/null } ################################################################################ # Takes a snapshot of the relevent files and returns sucess if they've changed function filesNotChanged { oldSnapshot="$snapshot" snapshot="$(ls --full-time "$@")" [[ $oldSnapshot == $snapshot ]] return $? } # function filesNotChanged ################################################################################ # Takes a snapshot of the TeX file's tempoary/system files and returns # faliure if they've changed since the function was last called. function tocChanged { oldTOC="$TOC" if [ -z "$(tocWatchList)" ]; then # If no TOCs exist TOC="" else TOC="$(md5sum $(tocWatchList))" fi [[ $oldTOC != $TOC ]] return $? } # function tocChanged ################################################################################ # List the files which if changed would require a recompile function fileWatchList { echo *.@(tex|sty|png|gif|jpg|bmp$(echo "$watchTypes")) } # function fileWatchList ################################################################################ # List of extensions to scan when reading through a tex document to look for # files to watch function tocWatchList { echo *.@(toc) } # function tocWatchList ################################################################################ function runLaTeX { $(echo $TeXCOMMAND) -shell-escape -halt-on-error "$TeXFILE" $TeXARGS return $? } # function runLaTeX ################################################################################ function texOutputHighlight { while read line; do case "$line" in "["*|"("*) echo -e "$LIGHTGRAY$line$NC" ;; *"Warning:"*) echo -e "$RED$line$NC" ;; "!"*) echo -e "$LIGHTRED$line$NC" ;; "Output written on"*) echo -e "$LIGHTGREEN$line$NC" ;; *) echo -e "$line" ;; esac done } # function texOutputHighlight ################################################################################ function compile { # Count how many times the file has been compiled compileCount=0 while true; do # Compile the file but die if this fails if ! runLaTeX | texOutputHighlight; then return 1 fi # Count compile passes let compileCount+=1 # Until the TOC stabalises, recompile the file if tocChanged; then echo echo "*****************************" echo "TOC Changed! Compiling again!" echo "*****************************" echo else break fi done # The file is done! return 0 } # function compile ################################################################################ function center { text="$*" for i in `seq 1 $COLUMNS`; do text="${text} " done echo "${text:0:$COLUMNS}" } # function center ################################################################################ function compileSuccess { echo if [ "$compileCount" -gt 1 ]; then compileMessage=" (Compiled $compileCount times)" else compileMessage="" fi echo -e "${LIGHTGREENBG}$(center "Success!${compileMessage}")${NC}" } # function compileSuccess ################################################################################ function compileFail { echo echo -e "${LIGHTREDBG}$(center "Compile Error!")${NC}" } # function compileFail ################################################################################ function printDoc { echo "Waiting for source files to change..." [ "$TeXCOMMAND" == "pdflatex" ] && which evince &>/dev/null &&\ echo "[p] Open PDF with evince" echo "[q] Quit" echo "[l] View compile output with pager" echo "[t] Delete TOC file" echo "[other] Recompile" } # function printDoc ################################################################################ function handleOption { case $command in p) evince "${TeXFILE/%tex/pdf}" & echo "Starting PDF Viewer" echo " $ evince \"${TeXFILE/%tex/pdf}\" &" return 1 ;; q) exit 0 ;; l) echo "Opening log file..." pager "${TeXFILE/%tex/log}" return 1 ;; t) rm -f "${TeXFILE/%tex/toc}" &>/dev/null \ && echo "Deleted TOC file."\ || echo "Couldn't delete TOC file!" return 1 ;; esac } # function handleOption ################################################################################ ################################################################################ # Parse the commandline (a hack to avoid another hack: getopts) while true; do # The name of the tex file case "$1" in "--no-pdf"|"--no-pdflatex"|"-P") TeXCOMMAND="latex" shift ;; "--no-colour"|"-C") disableColour="true" shift ;; "--update-on-type"|"-t") watchTypes="|${2/,/|}" shift shift ;; "") echo "You must specify a filename!" 1>&2 exit 1 ;; *) if [ -f "$1" ]; then cd "$(dirname "$1")" TeXFILE="$(basename "$1")" shift break else echo "Specified file '$1' does not exist!" 1>&2 exit 2 fi ;; esac done TeXARGS="$*" if [ -z "$disableColour" ]; then # Colours RED="\033[0;31m" LIGHTGRAY="\033[0;37m" LIGHTRED="\033[1;31m" LIGHTGREEN="\033[1;32m" LIGHTGREENBG="\033[1;33;42m" LIGHTREDBG="\033[1;33;41m" NC="\033[0m" #No colour fi while true; do echo printDoc while true; do waitUntilChanged if handleOption; then break fi done clear compile && compileSuccess || compileFail done