#!/usr/bin/perl -w # last modified 12/16/02 # a minimalistic IDE for TeX # This program will spawn an xdvi viewer creating the .dvi file if needed. # it will then watch the .tex file and when it changes, regenerate the # .dvi file and signal xdvi to redisplay it. # .tex is assumed if the filename does not end in .tex # automatically determined if the file is a laTeX or TeX file. # now checks for changes to included files as well. # append parameter landscape to get Xdvi landscape display # assumes files that start with \documentclass[semhelv]{seminar} are landscape # stops and continues Xdvi while TeXing to avoid Xdvi dieing. my $filename; my $interaction = "-interaction=nonstopmode"; my $texcmd = "tex"; my $texerrorcmd = "texerror.tcl"; my $landscape = 0; # set to display in Xdvi using -paper usr my @included_files; if($ARGV[0] ) { $filename = $ARGV[0]; } else { die "usage: $0 filename [landscape]\n"; } if($ARGV[1] and $ARGV[1] =~ m/landscape/i) { $landscape = 1; } if($filename !~ m/\.tex$/ ) { $filename .= '.tex'; $filename =~ s/\.\.tex/.tex/; } if( ! -f $filename ) { die "$filename not found\n"; } open(TEX,$filename) or die "cannot open $filename\n"; my $line = ; while($line =~ m/^\%/ ) { $line = ; } if($line =~ m/^\\document/) { $texcmd = "latex"; } if($line =~ m/^\\documentclass\[semhelv\]\{seminar\}/) { $landscape = 1; } while($line = ) { my $ifile; if(($ifile) = $line =~ m/\\include\{(.+)\}/) { if($ifile !~ m/\.tex$/ ) { $ifile .= '.tex'; } push(@included_files,$ifile); } } close(TEX); my $basename = $filename; $basename =~ s/\.tex//; my $dvi_pid=0; if(! -f $basename.'.dvi') { my @cmd = ($texcmd,$interaction,$filename); system(@cmd) == 0 or die "system @cmd failed: $?"; } $dvi_pid = fork(); if($dvi_pid == 0) { my @cmd; if($landscape) { @cmd = ('xdvi','-paper','usr',$basename.'.dvi'); } else { @cmd = ('xdvi',$basename.'.dvi'); } exec(@cmd) == 0 or die "system @cmd failed: $?"; } my @stat = stat($filename); unless(@stat) { die "stat failed on $filename\n"; } my $old_mod = $stat[9]; my @inc_mods; for(my $i=0;$i <= $#included_files;$i++) { my $f = $included_files[$i]; @stat = stat($f); unless(@stat) { die "stat failed on $f\n"; } $inc_mods[$i] = $stat[9]; } while(1) { $retex = 0; @stat = stat($filename); unless(@stat) { die "stat failed on $filename\n"; } if($stat[9] != $old_mod) { $retex = 1; $old_mod = $stat[9]; } for(my $i=0;$i <= $#included_files;$i++) { my $f = $included_files[$i]; @stat = stat($f); unless(@stat) { die "stat failed on $f\n"; } if($stat[9] != $inc_mods[$i]) { $retex = 1; $inc_mods[$i] = $stat[9]; } } if($retex) { if($dvi_pid) { kill('SIGSTOP',$dvi_pid); } my @cmd = ($texcmd,$interaction,$filename); # system(@cmd) == 0 or die "system @cmd failed: $?"; if(system(@cmd) != 0) { @cmd=($texerrorcmd); system(@cmd); } if($dvi_pid) { kill('SIGCONT',$dvi_pid); kill('SIGUSR1',$dvi_pid); } } select(undef, undef, undef, 0.25); }