#!/usr/bin/env ruby =begin rdoc == mk - a LaTeX maker === Synopsis mk - a LaTeX maker Usage: mk [options] [file] mk-specific options: -C, --Clean Remove all unnecessary files generated by latex and bibtex -c, --clean Same, except for the pdf or postscript files --ps Generate postscript version of document (default: pdf) --edit=STRING use STRING as the file to be edited -w, --[no-]warn After a successful run, print warnings found in the log file vpp-related options: -b, --batch=STRING run in batch using STRING for print command -p, --printer=STRING print to printer named STRING -d, --doublesided printer is doublesided --[no-]view do [not] view the document --[no-]print do [not] offer printing interaction General options: -r, --rc=STRING use STRING as an rc file -V, --version print version and exit -v, --[no-]verbose be [not] verbose (quiet is the default) --[no-]check do [not] check the availability of executables -h, --help print this help and exit Defaults: --no-warn --print --view --no-verbose --no-check main Required gems (gem install -r): rubygems readline rio session term-ansicolor Required from the url where you found mk: http://www.servalys.nl/scripts/scriptingutils.rb Required other programs: CTAN: make latex pdflatex http://www.servalys.nl/scripts/vpp http://ctan.osmirror.nl/macros/texinfo/texinfo/util/texi2dvi === Copyright Copyright (C) 2009 Wybo Dekker (wybo@servalys.nl) 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. === Introduction _mk_ is a Ruby script that, in close collaboration with _vpp_, is helpful in the cyclic process of editing, viewing, and printing a _latex_ document. Having an existing _latex_ document, say main.tex (see the section 'Locating the source' for the creation of new documents and for other extensions than .tex), you run _mk_ by typing: mk main or, since main happens to be _mk_'s default filename: mk Now, if main.tex is a valid _latex_ source, _mk_ compiles it, including any table of contents, indices, bibliography references, included files, and so on and _vpp_ takes over and displays the resulting _PostScript_ or _PDF_ output. When you leave the viewer you will see a prompt: vpp command (h for help): If you are satisfied with the displayed _PostScript_ or _PDF_ output, you can now decide to print all or part of your document (see the section 'Page selection'), or you can simply quit by typing 'q'. On the other hand, if you decide that you want to change the source and have another try, you can edit the source by typing 'e' to get back to _mk_ and (re)edit your source. After saving your work and leaving your editor, another compilation and display will be performed, based on the new source. Essentially, _mk_ uses the _make_ utility for the management of file dependencies, texi2dvi for compilation, _gv_ (or any other viewer you like) for viewing, and _latex_'s _pdfselect_ package for page selection and printing in various formats. Currently, _mk_ is only available for _unix_, but adaptation for _msdos_/_windows_ should not be too complicated, as all software needed, including _make_, is available on those operating systems. === How it works When working on a _latex_ document, the main activities---apart from thinking---consist of editing the sources, compiling with (_pdf_)_latex_, viewing the result (either a _PostScript_ or _PDF_ file or _latex_'s error messages) and, perhaps, printing the document or parts of it. A _latex_ document, as well as any other TeX document, may need several passes of compilation in order to fulfill all cross references and bibliography references, fix longtable calculations, and build the indices. When you compile manually, you'll have to keep track of the often abundant messages of _latex_ to see if another compilation is needed. Most of that work can be taken out of your hands by using texi2dvi. That is exactly what _mk_ does. However, although texi2dvi does look in the current directory for \included and \inputed files, it does not keep track of other files that you may have edited, such as style files, bibliography files, fontfiles, and so on, either in the current or in other directories. For that purpose, a contribution to _ctan_ by Tong Sun and Chris Beggy comes in handy: a makefile for _make_ that takes care of all of this, in cooperation with texi2dvi. However, this makefile needs to be told on what files your sources depend (apart from included files in the current directory.) This problem is solved by the recent appearance of a new option for TeX: the --recorder option. This option tells TeX to maintain a .fls file that logs all file dependencies that TeX finds in the sources. This is how the start of the current document's .fls file, main.fls, looks like: PWD /home/wybo/CVSWORK/mk INPUT /tex/texmf/web2c/pdflatex.fmt INPUT /tex/texmf/pdftex/config/pdftex.cfg INPUT /home/wybo/CVSWORK/mk/main.tex OUTPUT main.log INPUT /texlive/texmf/tex/latex/base/article.cls [ many similar lines follow... ] Now here is how _mk_ works (supposing main.tex to be the source): 1. if there is no file main.fls or if it is older than the source, _latex_ is run to generate it. 2. main.fls is scanned for lines starting with INPUT and the files on those lines are saved for _make_. 3. _make_ is executed. 4. if an error occurred, the log file is displayed, starting at the error location, skipping irrelevant lines, and stopping at most 20 lines later. The error message and its line number in the source are highlighted in color. The line number is remembered for the editor to start at. The user is finally asked whether he wants to quit, or to edit the source and recycle from 1. on. 5. if no error occurred, the _PDF_ or _PostScript_ output is displayed, using _vpp_. 6. after the user has left the viewer (normally with 'q' or 'control-q') the user is asked (still running _vpp_) whether he wants to quit, or (re-)edit the source, or to print (parts of) the document. === Page selection As said in the introduction, after a successful compilation and display of the resulting _PDF_ or _PostScript_ output, the user is prompted with: vpp command (h for help): upon typing 'h' _vpp_ displays examples of possible commands: Examples of print commands: 5 to print page 5 5- to print pages 5 through the end 5-7 to print pages 5, 6 and 7 -7 to print the first 7 pages 5-7,19- to print pages 5, 6, 7 and 19 through the end a to print the whole document - to print the whole document a x3 to print 3 copies of the document x3 the same 5 x3 to print 3 copies of page 5 t print the whole document twosided t 2- print twosided starting at page 2 b to print the whole document as an a5 size booklet b -12 to print the first 12 pages as an a5 size booklet Other commands: e (if called by mk) edit the tex source and rerun mk c (if called by mk) rerun mk v (re)view the ps/pdf file oxyz send pdf output to file xyz.pdf instead of printer h display this help ? display this help q quit With these examples, no further explanation should be necessary, except that, when twosided ('t') or booklet ('b') printing is selected, printing will be performed in two shifts, one for the front side and one for the backside. Between the shifts, another prompt appears: printer ready? then turn stack and type return You will have to arrange your printer such that, with the printed sides up, the first page printed will be at the bottom of the stack, and the last page printed will be on top. Normally you will then have your output come out the back of your printer. 'Turn the stack' then means: rotate it over the long side of the paper and feed it back into the printer for the other side to be printed. For further information on _vpp_, look in its manpage by typing vpp -h or read the article on _vpp_ elsewhere in this issue. === Locating the source _mk_ locates the _latex_ source in several steps: (here the source extension .tex is supposed, but .ltx, .drv and .dtx will also be tried) 1. If you supply no arguments, the file main.tex in the current directory is assumed. 2. If you supply an argument (say myfile), _mk_ adds a .tex extension if it isn't there and looks for myfile.tex in the current directory. 3. if myfile.tex is not found in the current directory, _mk_ looks in the 'alternate directory' (say /Documents) if you have defined one (see the section 'RC files'). 4. if the source was not found in /Documents, _mk_ thinks that you may have a subdirectory myfile in /Documents where the source may live under the name main.tex 5. if that file is not there, _mk_ now concludes that the source does not yet exist and reports this, telling at the saem time which files have been tried. 6. finally, if all the above did not lead to a source file, _mk_ dies. === Options _mk_ comes with several options. Before evaluating any options, _mk_ will try to read a system rc file, a user rc file, and, finally an rc file in the current directory. The default values for most options can be set in these files. See the section 'RC files' for more information. You can also set option defaults in an alias. For example: alias mk='mk -no-verbose' --help:: Prints help information and lets you type 'm' to display the complete man page or anything else to quit. --version:: Prints name and (CVS-)version and then quits. --quiet:: Suppresses messages about the progress _mk_ is making. This is the default. --rc=file:: execute the specified file before processing. The contents of the file may override options specified before the --rc option, therefore it is a good idea to have the habit of specifying the --rc option first. --batch=string:: Prevents the --print option to interrogate the user about pages to be printed. Instead the document is printed according to the mandatory string. Also sets viewing off. Thus the command mk --batch '2-3 x3' test prints 3 copies of pages 2 and 3 of test.tex, without viewing. --clean:: Clean up (remove) all unnecessary files generated by _latex_ and _bibtex_ except for the _PDF_ or _PostScript_ files. --Clean:: Clean up (remove) all unnecessary files generated by _latex_ and _bibtex_ including the _PDF_ or _PostScript_ files. --print:: Present the print prompt. This is the default. This option is normally used to suppress the print prompt, for example when using _mk_ from other scripts that generate _latex_ documents that have only to be displayed or stored without even being displayed. --ps:: Generate _PostScript_ version of document. The default is to generate a _PDF_ document. --view:: Run the file viewer. This is the default. This option is normally used to suppress starting the viewer, for example when using _mk_ from other scripts that generate _latex_ documents that have only to be printed. --edit=file:: Normally, _mk_ lets you edit the main source file, but here you can specify another file to be edited instead. This is useful, for example, if you are are fixing a style file or another input file. --warn:: After a successful run, scan the log file for warnings and repeat those. The array @warnings_to_skip, which can be set in the rc files (see below) can be filled with regexp's that match warnings you don't want to see. === RC files and customization Unless the environment variable NORC has been set, three rc files are executed, if they exist, before reading the command line options, in the following order: /etc/mkrc:: the system rc file $HOME/.mkrc:: the user rc file ./.mkrc:: the local rc file You can use these rc files to set the default values for the options, by setting the global Ruby Perl variable named after the long version of the options. For example: @verbose = true # run in verbose mode So if you usually like _mk_ to work in verbose mode, you can indicate so in your rc file and change your mind in some cases by using the --no-verbose option. Other variables, not having a corresponding command line option, that can be set in the rc files, and their default values, are: @latex='latex':: is the name of the latex executable. You use this as a trick to have _mk_ compile plain TeX sources with TeX for you by setting: @latex='tex' @pdflatex='latex':: which sets the the name of the pdflatex executable. You use this as a trick to have _mk_ compile plain TeX sources with pdfTeX for you by setting: @pdflatex='pdftex' @skip_pattern='':: can be set to a file wildcard pattern. Files matching this pattern on which the (La)TeX sourcefile may depend will not be checked for changes. For example, if you use a write-protected TeX-tree in the directory texlive it makes sense to set $skip_pattern='/^\/texlive/'; @altdir='':: If @altdir is non-empty and a file to be compiled does not exist in the current directory, it will be given another try after prefixing it with the contents of @altdir. So if you like to have your _latex_ file in /Documents/myfile.tex you can set @altdir to /Documents and run _mk_ from any directory with: mk myfile However, a directory like /Documents does not make much sense if many of your _latex_ documents do not consist of a single file, but are constituted of an ensemble of a main _latex_ source and one or more \included and \inputed files such as graphics. You will then probably prefer to have s subdirectory in /Documents for every _latex_ document. Therefore, if _mk_ does not find myfile.tex in the alternate directory, it will assume that myfile is a subdirectory with a main _latex_ source in it, called main.tex. @default='main':: This is the default for the basename of your _latex_ document. @warning_to_skip=[]:: When the --warn option is used, warnings appearing in the log file will be reported after a successful run. Warnings matching any of the rexgexp's in this array will be skipped, however. For example, one could enter here: @warnings_to_skip=[ 'Package hyperref Warning: Token not allowed in a PDFDocEncoded string', 'Package array Warning: Column [XY] is already defined on ' ] The first message appears when the _hyperref_ package is used and section titles contain \LaTeX-commands, the second message appears when the _ctable_ package is used, because it intentionally changes the X and Y column specifiers. =end begin require 'scriptingutils' rescue LoadError raise LoadError,< e(dit) q(uit) ") ) !~ /^(q|e)$/ puts "you must type e or q" end return true if x == 'q' end linenum ||= 1 edfile = file || edit File.exist?(edfile.chomp) or quit("Could not edit #{edfile}; vanished?",1) sys("#{ENV['EDITOR']} +#{linenum} #{edfile}",true) return false end init(:needs,:handle_options) vppoptions = @verbose ? "--verbose" : "--no-verbose" vppoptions << ' --doublesided' if @doublesided vppoptions << " --printer=#{@printer}" if @printer if @batch # @batch must contain valid printing commands: @batch.split.each do |e| unless e =~ / ^(q| # n-m or n- or - b| # print a5 booklet t| # print twosided a| # print all x[0-9]+| # x3 -> lpr -#3 (([0-9]+-?[0-9]*|[0-9]*-?[0-9]+),?)+ )$| ^o # output to pdf /x then quit("Illegal argument for --batch option: #{@batch}\n" + "Use q if you want no printout",1) end end vppoptions += " --batch='#{@batch}'" end @view = false if @batch @clean ||= @Clean @print = false if @batch =~ /q$/ makeopt = @verbose ? '' : '-s' targetext = @ps ? 'ps' : 'pdf' vppoptions += @print ? " --print" : " --no-print" vppoptions += @view ? " --view" : " --no-view" dirname,basename,ext,fullpath = findsource target = "#{basename}.#{targetext}" basename or exit 1 at_exit { rio("#{basename}.t2d").rmtree } @edit ||= fullpath unless @edit.empty? # if '', then no editing File.exist?(@edit) or quit("can't find file to be edited (#{@edit})") File.readable?(@edit) or quit("can't read file to be edited (#{@edit})") File.writable?(@edit) or quit("can't write file to be edited (#{@edit})") end Dir.chdir(dirname) # save the Makefile: makefile = rio(??) makefile < DATA.read.tran( '\bpdflatex\b' => @pdflatex, '\blatex\b' => @latex, '\.tex\b' => ext ) makefile.close makefile = makefile.path if @clean r = sys(%Q{TEX_SOURCE_BASE="#{basename}" make #{makeopt} -f #{makefile} clean}) if @Clean && File.exist?(target) # It may be useful to protect target, in order to prevent that they become # recompiled with changed style files: if File.writable?(target) File.delete(target) else quit("#{target} is write-protected, so I'll keep it!") end end quit end # for the Makefile, fill the environment variable TEX_DEP with the files that # the TEX_SOURCE_BASE depends upon: \input files, graphics files, style files, etc. # For those, we use tex's log file; if it isn't there yet, we run tex ########## dit is waarschijnlijk toch niet nodig: ########## on a fresh start, there may be a log file from other ########## processes, for example: the result of tex basename.ins ########## So we create a fresh log file ##########compile(basename,makefile,makeopt,target,targetext) loop do if File.exist?(target) && !File.writable?(target) puts "Target #{target} is write-protected, so I'll not re-compile it!" sleep 1 elsif target =~ /\s/ quit("mk does not (yet) handle filenames with spaces!") else compile(basename,makefile,makeopt,target,targetext) end if @view || @print unless File.exist?(target) puts "After compilation, no file #{target} was found" if targetext == 'pdf' puts "One possible cause is that your file pdftex.cfg" puts "contains 'output_format 0' instead of 'output_format 1'" end puts "Quitting..." quit end error = sys("ruby -S vpp #{vppoptions} #{target}",true)[:status] case error when EDITEXIT ready = edit(@edit,1,false) next unless ready when COMPILEEXIT next when 0 exit(0) else quit("Unexpected value (#{error}) for error") end end @edit = '' show_error_and_edit(basename,target) if @warn break end # $Id: mk,v 1.83 2009-10-06 11:52:59 wybo Exp $ __END__ # Makefile for latex (don't remove this line - mk uses it for testing) # @Author: SUN, Tong # Copyright (c)2001, Tong SUN, all right reserved # @Home URL: http://xpt.sourceforge.net/ SHELL=bash ifndef SYNTAXCHK SYNTAXCHK = chktex endif ifndef DVIPS DVIPS=dvips endif ifndef DVIVIEWER DVIVIEWER=xdvi endif ifndef MAKEFILE MAKEFILE=Makefile endif .SUFFIXES: .bbl .tex .dvi .chk .ps .pdf # Disable standard pattern rule: %.dvi: %.tex # Do not delete the following targets: .PRECIOUS: %.chk %.aux %.bbl .tex.bbl: bibtex -t $* %.chk: %.tex # $(SYNTAXCHK) -o $@ $< @touch $@ %.dvi: %.tex %.chk LATEX='latex -recorder -interaction=batchmode' texi2dvi --no-line-error -q $< %.ps : %.dvi %.chk $(DVIPS) -o $@ $< @[ $${TEX_DEST_DIR:+T} ] && mv $@ ${TEX_DEST_DIR} || true %.pdf : %.tex %.chk PDFLATEX='pdflatex -recorder -interaction=batchmode' texi2dvi --no-line-error -p -q $< @[ $${TEX_DEST_DIR:+T} ] && mv $@ ${TEX_DEST_DIR} || true dvi : $(TEX_SOURCE_BASE).chk $(TEX_SOURCE_BASE).dvi view: $(TEX_SOURCE_BASE).dvi @TEX_DEST_DIR=$${TEX_DEST_DIR:-.}; \ $(DVIVIEWER) $$TEX_DEST_DIR/${TEX_SOURCE_BASE}.dvi & ps : $(TEX_SOURCE_BASE).ps pdf : $(TEX_SOURCE_BASE).pdf check: # Make sure the TEX_SOURCE_BASE is set and help set it if not. @if [ $${TEX_SOURCE_BASE:+T} ]; then \ printf "TEX_SOURCE_BASE=${TEX_SOURCE_BASE}\nTEX_DEST_DIR=${TEX_DEST_DIR}\n"; \ else { \ if [ `ls *.tex | wc -l` = "1" ]; then \ TEX_SOURCE_BASE=`basename \`ls *.tex\` .tex`; \ true; \ else \ TEX_SOURCE_BASE=`echo $$PWD|tr '/' '\n'|tail -1`; \ true; \ fi; \ printf "\nPlease set\n\n export TEX_SOURCE_BASE=$$TEX_SOURCE_BASE\nor,\n setenv TEX_SOURCE_BASE $$TEX_SOURCE_BASE\n"; \ }; fi # .............................................................. &ss ... .PHONY : help usage check clean cleangen clean-bak clean-th help: @echo Tools used: @echo texi2dvi --help @echo @echo "To see the usage of this make file, type 'make usage'" @echo " (need to set the environment var MAKEFILE if you " @echo " have change the default name/location of this Makefile" @echo " which requires the -f parameter for the make)" usage: @cat ${MAKEFILE} | sed -n '/ [Cc]ommentary/,/ [Cc]ommentary/ p' | cut -c3- clean: rm -f ${TEX_SOURCE_BASE}.{tui,tuo,chk,dvi,log,ent,fls,aux,bbl,blg,ilg,toc,lof,lot,idx,ind,out,glo,gls,tmp*} cleangen : rm -f *.chk *.dvi *.log *.aux *.bbl *.blg *.ilg *.toc *.lof *.lot *.idx *.ind *.out *.ps *.pdf clean-bak : clean rm -f *~ clean-th : clean rm -f *.txt *.html *.css # .............................................................. &ss ... $(TEX_SOURCE_BASE).pdf: $(TEX_DEP) $(TEX_SOURCE_BASE).ps: $(TEX_DEP)