diff options
Diffstat (limited to 'Master/texmf-dist/scripts/musixtex/musixtex.lua')
-rwxr-xr-x | Master/texmf-dist/scripts/musixtex/musixtex.lua | 505 |
1 files changed, 352 insertions, 153 deletions
diff --git a/Master/texmf-dist/scripts/musixtex/musixtex.lua b/Master/texmf-dist/scripts/musixtex/musixtex.lua index c85f38a8a15..f4de32954af 100755 --- a/Master/texmf-dist/scripts/musixtex/musixtex.lua +++ b/Master/texmf-dist/scripts/musixtex/musixtex.lua @@ -1,11 +1,13 @@ #!/usr/bin/env texlua -VERSION = "0.12" +VERSION = "0.15" --[[ - musixtex.lua: processes MusiXTeX files (and deletes intermediate files) + musixtex.lua: processes MusiXTeX files using prepmx and/or pmxab and/or + autosp as pre-processors (and deletes intermediate files) - (c) Copyright 2012-15 Bob Tennent rdt@cs.queensu.ca + (c) Copyright 2011-2015 Bob Tennent rdt@cs.queensu.ca + and Dirk Laurie dirk.laurie@gmail.com 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 @@ -26,8 +28,28 @@ VERSION = "0.12" --[[ ChangeLog: + + version 0.15 2015-12-03 DL + Option -q added, which redirects most screen output into + a temporary file. If an error occurs at the TeX stage, processing + halts immediately and the tail of the log file is sent to stderr. + + version 0.14 2015-12-01 DL + Writes `musixtex.log` and deletes other logfiles (except with -i) + Hierarchy of extensions emphasized in usage() and consistently + used elsewhere. + Unknown option-like arguments reported and ignored, not treated + as filenames + Warnings and error messages generated by musixtex.lua start with + respctively `!` and `!!`. + + version 0.13 2015-11-30 RDT + Process .mtx and .pmx files (suggested by Dirk Laurie) + exit_code is now an error count + Use pmxab exit code to distinguish between errors and warnings + version 0.12 2015-11-28 RDT - Process .ltx files with -l implied + Process .ltx files, with -l implied version 0.11 2015-07-16 RDT Automatic autosp preprocessing. @@ -63,188 +85,365 @@ VERSION = "0.12" Allow basename.tex as filename. Add -p option for pdfetex processing. Add standard -v -h options. - --]] +local orig_print = print function usage() - print("Usage: [texlua] musixtex.lua { option | basename[.tex] | basename[.aspc] basename[.ltx] } ... ") - print("options: -v version") - print(" -h help") - print(" -l latex (or pdflatex) (implied with .ltx extension)") - print(" -p pdfetex (or pdflatex)") - print(" -d dvipdfm") - print(" -s stop at dvi") - print(" -g stop at ps") - print(" -i retain intermediate files") - print(" -1 one-pass [pdf][la]tex processing") - print(" -F fmt use fmt as the TeX processor") - print(" -x run makeindex") - print(" -a preprocess using autosp (impled with .aspc extension)") - print(" -f restore default processing") + orig_print +[[ +Usage: [texlua] musixtex.lua { option | basename[.mtx | .pmx | .aspc | .tex | .ltx] } ... + When no extension is given, extensions are tried in the above order + until a source file is found. Preprocessing goes mtx-pmx-tex or + aspc-tex, with the entry point determined by the extension. + The normal route after preprocessing goes tex-dvi-ps-pdf, but shorter + routes are also available, see the options. +Options: -v version + -h help + -l latex source + -p direct tex-pdf (pdftex etc) + -F fmt use fmt as the TeX processor + -d tex-dvi-pdf (dvipdfm) + -c preprocess pmx file using pmxchords + -m stop at pmx + -t stop at tex/mid + -s stop at dvi + -g stop at ps + -i retain intermediate and log files + -q quiet mode (give only musixtex's own messages) + -1 one-pass [pdf][la]tex processing + -x run makeindex + -f restore default processing +Four TeX engines are available via the -l and -p options. + etex default + latex -l + pdfetex -p + pdflatex -l -p +The -F option allows any engine to be named. In that case, an attempt is made +to deduce implied -l and -p settings from the presence or absence of the +strings `latex` and `pdf` in the name of the engine. If this is not correct, +the user should explicitly specify the appropriate option.]] end function whoami () print("This is musixtex.lua version ".. VERSION .. ".") end -whoami() +function exists (filename, nolog) + local f = io.open(filename, "r") + if f then + f:close() + if not nolog then musixlog:write("Processing " .. filename,'\n' ) end + return true + else + return false + end +end + +-- The global variables below may be changed by set_options(). System +-- commands for the various programs are mostly set to nil if the step +-- is to be omitted, which can be tested by a simple "if" statement. +-- Exceptions: +-- 'tex' is the command for processing a TeX file, but it is important +-- to know whether the user has explicitly specified an option that +-- affects this choice, in which case the automatic selection of the +-- command is restricted or disabled. +-- force_engine "use the command provided" +-- override records when 'l' and/or 'p' options are in effect +-- 'dvi' is the command for processing a DVI file, but there are two +-- reasons for not needing it and it is important for the automatic +-- selection of a TeX engine to know which is in effect. This is +-- possible by exploiting the the fact that Lua has two false values. +-- dvi == nil "do not produce a DVI file" (but maybe PDF) +-- dvi == false "do not process the DVI file" (but stop after TeX) +local dvips = "dvips -e0" +function defaults() + prepmx = "prepmx" + pmx = "pmxab" + tex = "etex" + musixflx = "musixflx" + dvi = dvips + ps2pdf = "ps2pdf" + cleanup = true -- clean up intermediate and log files + index = false + latex = false + force_engine = false -- indicates whether -F is specified + override = "" + passes = 2 + quiet = "" -- set by "-q" +end + + if #arg == 0 then + whoami() usage() os.exit(0) end --- defaults: -tex = "etex" -musixflx = "musixflx" -dvips = "dvips -e0 " -dvi = dvips -ps2pdf = "ps2pdf" -intermediate = 1 -passes = 2 -index = 0 -preprocess = 0 +-- Logging on `musixtex.log` everything that is printed, all os calls, +-- and warnings from other log files. -exit_code = 0 -narg = 1 -repeat - this_arg = arg[narg] +musixlog = io.open("musixtex.log","w") +if not musixlog then + print"!! Can't open files for writing in current directory, aborting" + os.exit(1) +end + +print = function(...) + orig_print(...) + musixlog:write(...,"\n") -- only the first argument gets written! +end + +local orig_remove = os.remove +remove = function(filename) + if exists(filename,"nolog") then + musixlog:write(" removing ",filename,"\n") + return orig_remove(filename) + end +end + +local orig_execute = os.execute +execute = function(command) + musixlog:write(" ",command,"\n") + return orig_execute(command .. quiet) +end + +function report_warnings(filename,pattern) + local log = io.open(filename) + if not log then + print("! No file "..filename) + return + end + for line in log:lines() do + if line:match(pattern) then + musixlog:write("! "..line,"\n") + end + end +end + +function report_error(filename) + local log = io.open(filename) + if not log then + print("! No file "..filename) + return + end + local trigger = false + for line in log:lines() do + trigger = trigger or line:match"^!" + if trigger then + io.stderr:write("! "..line,"\n") + end + end +end + + function process_option(this_arg) if this_arg == "-v" then os.exit(0) elseif this_arg == "-h" then usage() os.exit(0) - elseif this_arg == "-l" then - if tex == "pdfetex" then - tex = "pdflatex" - else - tex = "latex" - end + elseif this_arg == "-l" then + latex = true + override = override .. 'l' elseif this_arg == "-p" then - if tex == "latex" then - tex = "pdflatex" - else - tex = "pdfetex" - end - dvi = ""; ps2pdf = "" + dvi = nil + override = override .. 'p' elseif this_arg == "-d" then - dvi = "dvipdfm"; ps2pdf = "" + dvi = "dvipdfm"; ps2pdf = nil + elseif this_arg == "-c" then + pmx = "pmxchords" + elseif this_arg == "-F" then + narg = narg+1 + tex = arg[narg] + force_engine = true elseif this_arg == "-s" then - dvi = ""; ps2pdf = "" + dvi = false; ps2pdf = nil; + elseif this_arg == "-g" then + dvi = dvips; ps2pdf = nil elseif this_arg == "-i" then - intermediate = 0 + cleanup = false + elseif this_arg == "-x" then + index = true elseif this_arg == "-1" then passes = 1 elseif this_arg == "-f" then - tex = "etex"; dvi = dvips; ps2pdf = "ps2pdf"; intermediate = 1; passes = 2; index = 0; preprocess = 0 - elseif this_arg == "-g" then - dvi = dvips; ps2pdf = "" - elseif this_arg == "-x" then - index = 1 - elseif this_arg == "-a" then - preprocess = 1 - elseif this_arg == "-F" then - narg = narg+1 - tex = arg[narg] + defaults() + elseif this_arg == "-t" then + tex, dvi, ps2pdf = nil,nil,nil + elseif this_arg == "-m" then + pmx, tex, dvi, ps2pdf = nil,nil,nil + elseif this_arg == "-q" then + if not tempname then + tempname = tempname or os.tmpname() + print("Redirecting screen output to "..tempname) + end + if dvi == dvips then dvi = dvi .. " -q" end + quiet = " >> " .. tempname else - repeat -- pseudo loop to get effect of "continue" using "break" - texfilename = this_arg - if texfilename ~= "" and string.sub(texfilename, -5, -1) == ".aspc" then - if io.open(texfilename, "r") then - print("Processing ".. texfilename ) - else - print("No file: " .. texfilename ) - break -- out of pseudo loop - end - preprocess = 1 - filename = string.sub(texfilename, 1, -6) - texfilename = filename .. ".tex" - elseif texfilename ~= "" and string.sub(texfilename, -4, -1) == ".ltx" then - if io.open(texfilename, "r") then - print("Processing ".. texfilename ) - else - print("No file: " .. texfilename ) - break -- out of pseudo loop - end - if tex == "pdfetex" then - tex = "pdflatex" - else - tex = "latex" - end - filename = string.sub(texfilename, 1, -5) - elseif texfilename ~= "" and string.sub(texfilename, -4, -1) == ".tex" then - if io.open(texfilename, "r") then - print("Processing ".. texfilename ) - else - print("No file: " .. texfilename ) - break -- out of pseudo loop - end - filename = string.sub(texfilename, 1, -5) - elseif io.open(texfilename .. ".aspc", "r") then - preprocess = 1 - print("Processing ".. texfilename .. ".aspc") - filename = texfilename - elseif io.open(texfilename .. ".ltx", "r") then - if tex == "pdfetex" then - tex = "pdflatex" - else - tex = "latex" - end - ltx = 1 - filename = texfilename - texfilename = filename .. ".ltx" - elseif io.open(texfilename .. ".tex", "r") then - print("Processing ".. texfilename .. ".tex") - filename = texfilename - texfilename = filename .. ".tex" + print("! Unknown option "..this_arg.." ignored") + end +end + +function find_file(this_arg) + basename, extension = this_arg:match"(.*)%.(.*)" + if not extension then + basename = this_arg + for ext in ("mtx,pmx,aspc,tex,ltx"):gmatch"[^,]+" do + if exists (basename .. "." .. ext) then + extension = ext + break + end + end + if not extension then + print("!! No file " .. basename .. "[.mtx|.pmx|.aspc|.tex|.ltx]") + exit_code = exit_code+1 + return + end + end + if tex then -- tex output enabled, now select engine + if tex:match"pdf" then dvi = nil end + if not dvi then ps2pdf = nil end + -- .ltx extension will be taken into account later, in `process` + -- deduce tex/latex from current engine name if -l is not specified + if not override:match"l" then latex = tex:match"latex" end + if not force_engine then -- select appropriate default engine + if latex then + if dvi==nil then tex = "pdflatex" else tex = "latex" end + else + if dvi==nil then tex = "pdfetex" else tex = "etex" end + end + end + end + return basename, extension +end + +function preprocess(basename,extension) + if not (basename and extension) then return end + if extension == "mtx" then + if execute(prepmx .. " " .. basename ) == 0 then + extension = "pmx" + else + print ("!! prepmx preprocessing of " .. basename .. ".mtx fails.") + return + end + end + if extension == "pmx" then + local OK = true + if pmx then + local code = execute(pmx .. " " .. basename) + local pmxaerr = io.open("pmxaerr.dat", "r") + if (not pmxaerr) then + OK = false + print("!! No pmx log file.") else - print("No file: " .. texfilename ) - break -- out of pseudo loop - end - if preprocess == 1 and os.execute("autosp " .. filename) ~= 0 then - print ("Preprocessing fails.") - break -- out of pseudo loop - end - os.remove( filename .. ".mx2" ) - if (passes == 1 or os.execute(tex .. " " .. texfilename) == 0) and - (passes == 1 or os.execute(musixflx .. " " .. filename) == 0) and - (os.execute(tex .. " " .. texfilename) == 0) and - ((tex ~= "latex" and tex ~="pdflatex") - or (index == 0) - or (os.execute("makeindex -q " .. filename) == 0)) and - ((tex ~= "latex" and tex ~= "pdflatex") - or (os.execute(tex .. " " .. texfilename) == 0)) and - ((tex ~= "latex" and tex ~= "pdflatex") - or (os.execute(tex .. " " .. texfilename) == 0)) and - ((tex ~= "latex" and tex ~= "pdflatex") - or (os.execute(tex .. " " .. texfilename) == 0)) and - (dvi == "" or (os.execute(dvi .. " " .. filename) == 0)) and - (ps2pdf == "" or (os.execute(ps2pdf .. " " .. filename .. ".ps") == 0) ) - then - if ps2pdf ~= "" then - print(filename .. ".pdf generated by " .. ps2pdf .. ".") - end - if intermediate == 1 then -- clean-up: - os.remove( filename .. ".mx1" ) - os.remove( filename .. ".mx2" ) - if dvi ~= "" then - os.remove( filename .. ".dvi" ) - end - if ps2pdf ~= "" then - os.remove( filename .. ".ps" ) + extension = "tex" + local linebuf = pmxaerr:read() + local err = tonumber(linebuf) + if (code == 0) then + if err ~=0 then + print ("! pmx produced a warning on line "..err.. + " of "..basename..".pmx") end + else + OK = false + print ("!! pmx processing of " .. basename .. ".pmx fails.") end - else - print("Musixtex processing of " .. texfilename " fails.\n") - exit_code = 2 - --[[ uncomment for debugging - print("tex = ", tex) - print("dvi = ", dvi) - print("ps2pdf = ", ps2pdf) - --]] + pmxaerr:close() end - until true -- end of pseudo loop + end + if not OK then + exit_code = exit_code+1 + return + end + end + if extension == "aspc" then + if execute ("autosp " .. basename .. ".aspc" ) == 0 then + extension = "tex" + else + print ("!! autosp preprocessing of " .. filename .. " fails.") + exit_code = exit_code+1 + return + end + end + return extension +end - end --if this_arg == ... +function tex_process(tex,basename,extension) + if not (extension == "tex" or extension == "ltx") or not tex then return end + remove(basename .. ".mx2") + local filename = basename .. "." ..extension +-- .ltx extension re-selects engine only for the current file, and only +-- if default processing is plain TeX + local latex = latex + if extension == "ltx" then + if not force_engine and not latex then + if dvi then tex = "latex" else tex = "pdflatex" end + end + latex = true + end + if quiet ~= "" then + tex = tex .. " -halt-on-error" + end + local OK = (execute(tex .. " " .. filename) == 0) + if passes ~= 1 then + OK = OK and (execute(musixflx .. " " .. basename) == 0) + and (execute(tex .. " " .. filename) == 0) + if latex and index then + OK = OK and (execute("makeindex -q " .. basename) == 0) + and (execute(tex .. " " .. filename) == 0) + if exists (basename .. ".toc","nolog") then + -- an extra line for the index will have been added + OK = OK and (execute(tex .. " " .. filename) == 0) + -- there is a tiny possibility that the extra line for the index + -- has changed the pagination. If you feel this should not be + -- ignored, here are the possibilities: + -- a. Do an extra TeX pass regardless. + -- b. Provide a user option -4 to force the extra pass. + -- c. Compare aux files to find out. + end + end + end + if (quiet ~= "") and not OK then + report_error(basename..".log") + end + if OK and latex then + report_warnings(basename..".log","LaTeX.*Warning") + end + if dvi then OK = OK and (execute(dvi .. " " .. basename) == 0) end + if dvi and ps2pdf then + OK = OK and (execute(ps2pdf .. " " .. basename .. ".ps") == 0) + if OK then + print(basename .. ".pdf generated by " .. ps2pdf .. ".") + end + end + if not OK then + print("!! Processing of " .. filename .. " fails.\n") + exit_code = exit_code+1 + end +end + +whoami() + +defaults() + +exit_code = 0 +narg = 1 + +repeat + this_arg = arg[narg] + if this_arg:match"^%-" then process_option(this_arg) + else + basename, extension = find_file(this_arg) -- nil,nil if not found + extension = preprocess(basename,extension) + tex_process(tex,basename,extension) + if basename and cleanup then + remove("pmxaerr.dat") + for ext in ("mx1,mx2,dvi,ps,idx,log,ilg,pml"):gmatch"[^,]+" do + remove(basename.."."..ext) + end + end + end narg = narg+1 until narg > #arg + +musixlog:close() os.exit( exit_code ) |