From 2cae2bb164327cd36f426861958b9e76dbdfb80d Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 6 Mar 2014 23:02:07 +0000 Subject: luamplib (2mar14) git-svn-id: svn://tug.org/texlive/trunk@33111 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/luatex/luamplib/NEWS | 16 +- Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf | Bin 119768 -> 126379 bytes .../doc/luatex/luamplib/test-luamplib-latex.tex | 16 +- .../doc/luatex/luamplib/test-luamplib-plain.tex | 19 ++ .../texmf-dist/source/luatex/luamplib/luamplib.dtx | 347 +++++++++++++++------ Master/texmf-dist/tex/luatex/luamplib/luamplib.lua | 234 +++++++++----- Master/texmf-dist/tex/luatex/luamplib/luamplib.sty | 75 ++++- 7 files changed, 528 insertions(+), 179 deletions(-) (limited to 'Master') diff --git a/Master/texmf-dist/doc/luatex/luamplib/NEWS b/Master/texmf-dist/doc/luatex/luamplib/NEWS index 43da66abb30..24e92825cf4 100644 --- a/Master/texmf-dist/doc/luatex/luamplib/NEWS +++ b/Master/texmf-dist/doc/luatex/luamplib/NEWS @@ -1,5 +1,19 @@ History of the luamplib package +2014/03/01 2.5.3 + * using \mplibcachedir{}, users can change the + directory for storing cache files. By default, it is the directory + where pdf output file is saved. + * at the end of package loading, luamplib searches 'luamplib.cfg', + and, when found, reads the file in automatically. + +2014/02/24 2.5.2 + * new macros \mplibmakenocache{...} and \mplibcancelnocache{...} to + register/unregister those .mp files that do not need caches. + These macros affect the compilation speed only. + * added a hack to support graph.mp (in fact, format.mp) + * [fix] luamplib now respects percent sign if it is enclosed by quotes. + 2014/02/19 2.5 * btex ... etex input from external *.mp files will also be processed by luamplib. However, verbatimtex ... etex will be entirely ignored @@ -25,7 +39,7 @@ Using this macro, each mplib box can be moved horizontally and/or vertically. -2013/12/23 2.11 +2013/12/23 2.1.1 * fix a bug wrt "withoutcolor" option * fix a bug wrt "char infont " picture * bypass some ConTeXt commands which raise errors under metafun format diff --git a/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf b/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf index c9b1df7af42..0676a222cdf 100644 Binary files a/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf and b/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex index 993ce15f149..3708916fe51 100644 --- a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex +++ b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex @@ -26,7 +26,8 @@ A% verbatimtex \lower.2em etex beginfig(0); draw origin--(1cm,0) withcolor red; -draw btex g etex withcolor blue; +draw btex g\begin{huge}g\end{huge}etex withcolor blue; +draw bbox currentpicture; endfig; beginfig(18); @@ -100,4 +101,17 @@ u := 10**5*(10**-4); draw unitsquare scaled u; endfig; \end{mplibcode}% +\mplibsetformat{plain}% +\begin{mplibcode} + input graph; + beginfig(0); + draw begingraph(100,100); + gdraw (10,10)--(30,35)--(50,25)--(70,80)--(90,90); + autogrid(otick.bot,); + for y=20,40,60,80: + grid.lft(format("%e",1000y), y) withcolor .85white; + endfor + endgraph; + endfig; +\end{mplibcode}% \end{document} diff --git a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex index a2e9dd1489f..ee5a5231d54 100644 --- a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex +++ b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex @@ -24,6 +24,12 @@ verbatimtex \lower.2em etex beginfig(0); draw origin--(1cm,0) withcolor red; draw btex g etex withcolor blue; +draw btex\tracingcommands0 multi + line + tex code + etex shifted (20,0); +draw textext("\tracingcommands0 textext 50\% color") shifted (10,-10) withcolor .5white; +draw bbox currentpicture; endfig; beginfig(18); @@ -97,4 +103,17 @@ u := 10**5*(10**-4); draw unitsquare scaled u; endfig; \endmplibcode +\mplibsetformat{plain}% +\mplibcode + input graph; + beginfig(0); + draw begingraph(100,100); + gdraw (10,10)--(30,35)--(50,25)--(70,80)--(90,90); + autogrid(otick.bot,); + for y=20,40,60,80: + grid.lft(format("%e",1000y), y) withcolor .85white; + endfor + endgraph; + endfig; +\endmplibcode \bye diff --git a/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx b/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx index ff71bb6fbd9..0024de422f3 100644 --- a/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx +++ b/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx @@ -85,7 +85,7 @@ See source file '\inFileName' for licencing and contact information. %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{luamplib.drv}% - [2014/02/19 v2.5.1 Interface for using the mplib library]% + [2014/03/01 v2.5.3 Interface for using the mplib library]% \documentclass{ltxdoc} \usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace} \usepackage[x11names]{xcolor} @@ -154,7 +154,7 @@ See source file '\inFileName' for licencing and contact information. % \author{Hans Hagen, Taco Hoekwater, Elie Roux, Philipp Gesang and Kim Dohyun\\ % Maintainer: LuaLaTeX Maintainers --- % Support: \email{lualatex-dev@tug.org}} -% \date{2014/02/19 v2.5.1} +% \date{2014/03/01 v2.5.3} % % \maketitle % @@ -191,8 +191,7 @@ See source file '\inFileName' for licencing and contact information. % \item use of luatexbase for errors, warnings and declaration % \item possibility to use |btex ... etex| to typeset \TeX\ code. % |textext()| is a more versatile macro equivalent to |TEX()| from TEX.mp. -% |TEX()| is also allowed unless TEX.mp is loaded, which should be always -% avoided.\par +% |TEX()| is also allowed and is a synomym of |textext()|.\par\smallskip % \textsc{n.b.} Since v2.5, |btex ... etex| input from external |mp| files % will also be processed by \textsf{luamplib}. However, % |verbatimtex ... etex| will be entirely ignored in this case. @@ -251,6 +250,31 @@ See source file '\inFileName' for licencing and contact information. % The default value |scaled| can be changed to |double| by declaring % |\mplibnumbersystem{double}|. For details see % \url{http://github.com/lualatex/luamplib/issues/21}. +% \item To support |btex ... etex| in external |.mp| files, \textsf{luamplib} +% inspects the content of each and every |.mp| input files and makes caches +% if nececcsary, before returning their paths to \LuaTeX's mplib library. +% This would make the compile time longer wastefully, as most |.mp| files +% do not contain |btex ... etex| command. So \textsf{luamplib} provides +% macros as follows, so that users can give instruction about files +% that do not require this functionality. +% \begin{itemize} +% \item |\mplibmakenocache{[,,...]}| +% \item |\mplibcancelnocache{[,,...]}| +% \end{itemize} +% where || is a file name excluding |.mp| extension. +% Note that |.mp| files under |[TEXMFMAIN]/metapost/base| and +% |[TEXMFMAIN]/metapost/context/base| are already registered by default. +% \item By default, cache files will be stored in the same directory as +% pdf output file. This however can be changed by the command +% |\mplibcachedir{}|, where tilde (|~|) is interpreted +% as the user's home directory (on windows machines as well). +% As backslashes (|\|) should be escaped by users, it is easier to use +% slashes (|/|) instead. +% \item At the end of package loading, \textsf{luamplib} searches +% |luamplib.cfg| and, if found, reads the file in automatically. +% Frequently used settings such as |\everymplib| or |\mplibcachedir| +% are suitable for going into this file. +% % \end{itemize} % % There are (basically) two formats for metapost: \emph{plain} and @@ -283,8 +307,8 @@ luamplib.lastlog = "" local err, warn, info, log = luatexbase.provides_module({ name = "luamplib", - version = "2.5.1", - date = "2014/02/19", + version = "2.5.3", + date = "2014/03/01", description = "Lua package to typeset Metapost with LuaTeX's MPLib.", }) @@ -306,6 +330,12 @@ local texsprint = tex.sprint local mplib = require ('mplib') local kpse = require ('kpse') +local lfs = require ('lfs') + +local lfsattributes = lfs.attributes +local lfsisdir = lfs.isdir +local lfstouch = lfs.touch +local ioopen = io.open local file = file if not file then @@ -333,49 +363,44 @@ end % \end{macrocode} % |btex ... etex| in input .mp files will be replaced in finder. % \begin{macrocode} -local mpreplacedabove = {} +local luamplibtime = kpse.find_file("luamplib.lua") +luamplibtime = luamplibtime and lfsattributes(luamplibtime,"modification") -local function replaceinputmpfile (file) - local fh = io.open(file,"r") - if not fh then return file end - local data = fh:read("*all"); fh:close() - data = stringgsub(data, "\".-\"", - function(str) - str = stringgsub(str,"%%","*****PERCENT*****") - str = stringgsub(str,"([bm])tex%f[^A-Z_a-z]","%1***T***E***X***") - return str - end) - data = stringgsub(data,"%%.-\n","") - local count,cnt = 0,0 - data,cnt = stringgsub(data, - "%f[A-Z_a-z]btex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", - function(str) - str = stringgsub(str,"[\n\r]%s*"," ") - str = stringgsub(str,'"','"&ditto&"') - return format("rawtextext(\"%s\")",str) - end) - count = count + cnt - data,cnt = stringgsub(data, - "%f[A-Z_a-z]verbatimtex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", - "") - count = count + cnt - if count == 0 then - mpreplacedabove[file] = file - return file +local currenttime = os.time() + +local outputdir = "." +for _,v in ipairs(arg) do + local t = stringmatch(v,"%-output%-directory=(.+)") + if t then + outputdir = t + break + end +end + +function luamplib.getcachedir(dir) + dir = stringgsub(dir,"##","#") + dir = stringgsub(dir,"^~", + os.type == "windows" and os.getenv("UserProfile") or os.getenv("HOME")) + if lfstouch and dir then + if lfsisdir(dir) then + local tmp = dir.."/_luam_plib_temp_file_" + local fh = ioopen(tmp,"w") + if fh then + fh:close(fh) + os.remove(tmp) + luamplib.cachedir = dir + else + warn("Directory '"..dir.."' is not writable!") + end + else + warn("Directory '"..dir.."' does not exist!") end - data = stringgsub(data,"([bm])***T***E***X***","%1tex") - data = stringgsub(data,"*****PERCENT*****","%%") - local newfile = stringgsub(file,".*/","luamplib_input_") - fh = io.open(newfile,"w") - if not fh then return file end - fh:write(data); fh:close() - mpreplacedabove[file] = newfile - return newfile + end end local noneedtoreplace = { ["boxes.mp"] = true, - ["format.mp"] = true, +-- ["format.mp"] = true, ["graph.mp"] = true, ["marith.mp"] = true, ["mfplain.mp"] = true, @@ -410,6 +435,80 @@ local noneedtoreplace = { ["mp-text.mpiv"] = true, ["mp-tool.mpiv"] = true, } +luamplib.noneedtoreplace = noneedtoreplace + +local function replaceformatmp(file,newfile,ofmodify) + local fh = ioopen(file,"r") + if not fh then return file end + local data = fh:read("*all"); fh:close() + fh = ioopen(newfile,"w") + if not fh then return file end + fh:write( + "let normalinfont = infont;\n", + "primarydef str infont name = rawtextext(str) enddef;\n", + data, + "vardef Fmant_(expr x) = rawtextext(decimal abs x) enddef;\n", + "vardef Fexp_(expr x) = rawtextext(\"$^{\"&decimal x&\"}$\") enddef;\n", + "let infont = normalinfont;\n" + ); fh:close() + lfstouch(newfile,currenttime,ofmodify) + return newfile +end + +local function replaceinputmpfile (name,file) + local ofmodify = lfsattributes(file,"modification") + if not ofmodify then return file end + local cachedir = luamplib.cachedir or outputdir + local newfile = stringgsub(name,"%W","_") + newfile = cachedir .."/luamplib_input_"..newfile + if newfile and luamplibtime then + local nf = lfsattributes(newfile) + if nf and nf.mode == "file" and ofmodify == nf.modification and luamplibtime < nf.access then + return nf.size == 0 and file or newfile + end + end + if name == "format.mp" then return replaceformatmp(file,newfile,ofmodify) end + + local fh = ioopen(file,"r") + if not fh then return file end + local data = fh:read("*all"); fh:close() + data = stringgsub(data, "\"[^\n]-\"", + function(str) + str = stringgsub(str,"%%","*****PERCENT*****") + str = stringgsub(str,"([bem])tex%f[^A-Z_a-z]","%1***T***E***X***") + return str + end) + data = stringgsub(data,"%%.-\n","") + local count,cnt = 0,0 + data,cnt = stringgsub(data, + "%f[A-Z_a-z]btex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", + function(str) + str = stringgsub(str,"[\n\r]%s*"," ") + str = stringgsub(str,'"','"&ditto&"') + return format("rawtextext(\"%s\")",str) + end) + count = count + cnt + data,cnt = stringgsub(data, + "%f[A-Z_a-z]verbatimtex%f[^A-Z_a-z]%s*.-%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", + "") + count = count + cnt + if count == 0 then + noneedtoreplace[name] = true + fh = ioopen(newfile,"w"); + if fh then + fh:close() + lfstouch(newfile,currenttime,ofmodify) + end + return file + end + data = stringgsub(data,"([bem])***T***E***X***","%1tex") + data = stringgsub(data,"*****PERCENT*****","%%") + fh = ioopen(newfile,"w") + if not fh then return file end + fh:write(data); fh:close() + lfstouch(newfile,currenttime,ofmodify) + return newfile +end % \end{macrocode} % As the finder function for |mplib|, use the |kpse| library and % make it behave like as if MetaPost was used (or almost, since the engine @@ -425,9 +524,10 @@ local function finder(name, mode, ftype) else local file = mpkpse:find_file(name,ftype) if file then - if ftype ~= "mp" or noneedtoreplace[name] then return file end - if mpreplacedabove[file] then return mpreplacedabove[file] end - return replaceinputmpfile(file) + if not lfstouch or ftype ~= "mp" or noneedtoreplace[name] then + return file + end + return replaceinputmpfile(name,file) end return mpkpse:find_file(name,stringmatch(name,"[a-zA-Z]+$")) end @@ -508,7 +608,6 @@ else end function luamplib.load(name) - mpreplacedabove = {} -- reset local mpx = mplib.new { ini_version = true, find_file = luamplib.finder, @@ -812,54 +911,42 @@ extra_endfig := extra_endfig & " let VerbatimTeX = specialVerbatimTeX;" ; local function protecttextext(data) local everymplib = tex.toks['everymplibtoks'] or '' local everyendmplib = tex.toks['everyendmplibtoks'] or '' - data = " " .. everymplib .. data .. everyendmplib + data = "\n" .. everymplib .."\n".. data .."\n".. everyendmplib + data = stringgsub(data,"\r","\n") + data = stringgsub(data, "\"[^\n]-\"", + function(str) + str = stringgsub(str,"%%","****PERCENT****") + str = stringgsub(str,"([bem])tex%f[^A-Z_a-z]","%1***T***E***X***") + return str + end) + data = stringgsub(data,"%%.-\n","") data = stringgsub(data, "%f[A-Z_a-z]btex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", function(str) str = stringgsub(str,'"','"&ditto&"') - return format("rawtextext(\\unexpanded{\"%s\"})",str) + str = stringgsub(str,"\n%s*"," ") + return format("rawtextext(\"%s\")",str) end) data = stringgsub(data, "%f[A-Z_a-z]verbatimtex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", function(str) str = stringgsub(str,'"','"&ditto&"') - return format("VerbatimTeX(\\unexpanded{\"%s\"})",str) + str = stringgsub(str,"\n%s*"," ") + return format("VerbatimTeX(\"%s\")",str) end) - data = stringgsub(data, "\".-\"", -- hack for parentheses inside quotes + data = stringgsub(data, "\"[^\n]-\"", function(str) - str = stringgsub(str,"%(","%%%%LEFTPAREN%%%%") - str = stringgsub(str,"%)","%%%%RGHTPAREN%%%%") - return str + str = stringgsub(str,"([bem])***T***E***X***","%1tex") + str = stringgsub(str,"{", "****LEFTBRCE****") + str = stringgsub(str,"}", "****RGHTBRCE****") + str = stringgsub(str,"#", "****SHARPE****") + return format("\\unexpanded{%s}",str) end) - data = stringgsub(data, "%f[A-Z_a-z]TEX%s*%b()", "\\unexpanded{%1}") - data = stringgsub(data, "%f[A-Z_a-z]textext%s*%b()", "\\unexpanded{%1}") - data = stringgsub(data, "%f[A-Z_a-z]textext%.[_a-z]+%s*%b()", "\\unexpanded{%1}") - data = stringgsub(data, "%%%%LEFTPAREN%%%%", "(") -- restore - data = stringgsub(data, "%%%%RGHTPAREN%%%%", ")") -- restore texsprint(data) end luamplib.protecttextext = protecttextext -local factor = 65536*(7227/7200) - -local function putTEXboxes (object,prescript) - local box = prescript.MPlibTEXboxID - local n,tw,th = box[1],box[2],box[3] - if n and tw and th then - local op = object.path - local first, second, fourth = op[1], op[2], op[4] - local tx, ty = first.x_coord, first.y_coord - local sx, sy = (second.x_coord - tx)/tw, (fourth.y_coord - ty)/th - local rx, ry = (second.y_coord - ty)/tw, (fourth.x_coord - tx)/th - if sx == 0 then sx = 0.00001 end - if sy == 0 then sy = 0.00001 end - pdf_literalcode("q %f %f %f %f %f %f cm",sx,rx,ry,sy,tx,ty) - texsprint(format("\\mplibputtextbox{%i}",n)) - pdf_literalcode("Q") - end -end - local TeX_code_t = {} local function domakeTEXboxes (data) @@ -896,6 +983,10 @@ end local function makeTEXboxes (data) data = stringgsub(data, "##", "#") -- restore # doubled in input string + data = stringgsub(data, "****PERCENT****", "%%") + data = stringgsub(data, "****LEFTBRCE****","{") + data = stringgsub(data, "****RGHTBRCE****","}") + data = stringgsub(data, "****SHARPE****", "#" ) local mpx = luamplib.load(currentformat) if mpx and data then local result = mpx:execute(mplibcodepreamble .. data) @@ -906,6 +997,8 @@ end luamplib.makeTEXboxes = makeTEXboxes +local factor = 65536*(7227/7200) + local function processwithTEXboxes (data) local num = tex.count[14] -- the same newbox register local prepreamble = "TEXBOX_ := "..num..";\n" @@ -923,6 +1016,23 @@ end luamplib.processwithTEXboxes = processwithTEXboxes +local function putTEXboxes (object,prescript) + local box = prescript.MPlibTEXboxID + local n,tw,th = box[1],box[2],box[3] + if n and tw and th then + local op = object.path + local first, second, fourth = op[1], op[2], op[4] + local tx, ty = first.x_coord, first.y_coord + local sx, sy = (second.x_coord - tx)/tw, (fourth.y_coord - ty)/th + local rx, ry = (second.y_coord - ty)/tw, (fourth.x_coord - tx)/th + if sx == 0 then sx = 0.00001 end + if sy == 0 then sy = 0.00001 end + pdf_literalcode("q %f %f %f %f %f %f cm",sx,rx,ry,sy,tx,ty) + texsprint(format("\\mplibputtextbox{%i}",n)) + pdf_literalcode("Q") + end +end + % \end{macrocode} % Transparency and Shading % \begin{macrocode} @@ -1273,7 +1383,7 @@ luamplib.colorconverter = colorconverter \else \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luamplib} - [2014/02/19 v2.5.1 mplib package for LuaTeX] + [2014/03/01 v2.5.3 mplib package for LuaTeX] \RequirePackage{luatexbase-modutils} \RequirePackage{pdftexcmds} \fi @@ -1311,10 +1421,8 @@ luamplib.colorconverter = colorconverter \fi \def\mplibsetupcatcodes{% %catcode`\{=12 %catcode`\}=12 - \catcode`\#=12 - \catcode`\^=12 \catcode`\~=12 \catcode`\_=12 - %catcode`\%=12 %% don’t in Plain! - \catcode`\&=12 \catcode`\$=12 + \catcode`\#=12 \catcode`\^=12 \catcode`\~=12 \catcode`\_=12 + \catcode`\&=12 \catcode`\$=12 \catcode`\%=12 \catcode`\^^M=12 \endlinechar=10 } % \end{macrocode} % @@ -1322,6 +1430,14 @@ luamplib.colorconverter = colorconverter % % \begin{macrocode} \def\mplibputtextbox#1{\vbox to 0pt{\vss\hbox to 0pt{\raise\dp#1\copy#1\hss}}} +\newcount\mplibstartlineno +\def\mplibpostmpcatcodes{% + \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\%=12 } +\def\mplibreplacenewlinebr{% + \begingroup \mplibpostmpcatcodes \mplibdoreplacenewlinebr} +\begingroup\lccode`\~=`\^^M \lowercase{% + \gdef\mplibdoreplacenewlinebr#1^^J{\endgroup\luatexscantextokens{{}#1~}}} +\endgroup % \end{macrocode} % % The Plain-specific stuff. @@ -1329,18 +1445,25 @@ luamplib.colorconverter = colorconverter % \begin{macrocode} \bgroup\expandafter\expandafter\expandafter\egroup \expandafter\ifx\csname ProvidesPackage\endcsname\relax +\def\mplibreplacenewlinecs{% + \begingroup \mplibpostmpcatcodes \mplibdoreplacenewlinecs} +\begingroup\lccode`\~=`\^^M \lowercase{% + \gdef\mplibdoreplacenewlinecs#1^^J{\endgroup\luatexscantextokens{\relax#1~}}} +\endgroup \def\mplibcode{% + \mplibstartlineno\inputlineno + \begingroup \begingroup - \bgroup \mplibsetupcatcodes - \mplibdocode % + \mplibdocode } \long\def\mplibdocode#1\endmplibcode{% - \egroup + \endgroup \def\mplibtemp{\directlua{luamplib.protecttextext([===[\unexpanded{#1}]===])}}% \directlua{luamplib.tempdata = luamplib.makeTEXboxes([===[\mplibtemp]===])}% \directlua{luamplib.processwithTEXboxes(luamplib.tempdata)}% \endgroup + \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinecs\fi } \else % \end{macrocode} @@ -1348,13 +1471,15 @@ luamplib.colorconverter = colorconverter % The \LaTeX-specific parts: a new environment. % % \begin{macrocode} -\newenvironment{mplibcode}{\toks@{}\ltxdomplibcode}{} +\newenvironment{mplibcode}{% + \global\mplibstartlineno\inputlineno + \toks@{}\ltxdomplibcode +}{} \def\ltxdomplibcode{% \begingroup \mplibsetupcatcodes - \ltxdomplibcodeindeed % + \ltxdomplibcodeindeed } -% \long\def\ltxdomplibcodeindeed#1\end#2{% \endgroup \toks@\expandafter{\the\toks@#1}% @@ -1363,6 +1488,9 @@ luamplib.colorconverter = colorconverter \directlua{luamplib.tempdata=luamplib.makeTEXboxes([===[\reserved@a]===])}% \directlua{luamplib.processwithTEXboxes(luamplib.tempdata)}% \end{mplibcode}% + \ifnum\mplibstartlineno<\inputlineno + \expandafter\expandafter\expandafter\mplibreplacenewlinebr + \fi \else \toks@\expandafter{\the\toks@\end{#2}}\expandafter\ltxdomplibcode \fi @@ -1377,25 +1505,52 @@ luamplib.colorconverter = colorconverter \newtoks\everymplibtoks \newtoks\everyendmplibtoks \protected\def\everymplib{% + \mplibstartlineno\inputlineno \begingroup \mplibsetupcatcodes \mplibdoeverymplib } -\def\mplibdoeverymplib#1{% +\long\def\mplibdoeverymplib#1{% \endgroup \everymplibtoks{#1}% + \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi } \protected\def\everyendmplib{% + \mplibstartlineno\inputlineno \begingroup \mplibsetupcatcodes \mplibdoeveryendmplib } -\def\mplibdoeveryendmplib#1{% +\long\def\mplibdoeveryendmplib#1{% \endgroup \everyendmplibtoks{#1}% + \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi } \def\mpdim#1{ begingroup \the\dimexpr #1\relax\space endgroup } % gmp.sty \def\mplibnumbersystem#1{\directlua{luamplib.numbersystem = "#1"}} +\def\mplibmakenocache#1{\mplibdomakenocache #1,*,} +\def\mplibdomakenocache#1,{% + \ifx\empty#1\empty + \expandafter\mplibdomakenocache + \else + \ifx*#1\else + \directlua{luamplib.noneedtoreplace["#1.mp"]=true}% + \expandafter\expandafter\expandafter\mplibdomakenocache + \fi + \fi +} +\def\mplibcancelnocache#1{\mplibdocancelnocache #1,*,} +\def\mplibdocancelnocache#1,{% + \ifx\empty#1\empty + \expandafter\mplibdocancelnocache + \else + \ifx*#1\else + \directlua{luamplib.noneedtoreplace["#1.mp"]=false}% + \expandafter\expandafter\expandafter\mplibdocancelnocache + \fi + \fi +} +\def\mplibcachedir#1{\directlua{luamplib.getcachedir("\unexpanded{#1}")}} % \end{macrocode} % % We use a dedicated scratchbox. @@ -1464,6 +1619,16 @@ luamplib.colorconverter = colorconverter } % \end{macrocode} % +% input luamplib.cfg when it exists +% +% \begin{macrocode} +\openin0=luamplib.cfg +\ifeof0 \else + \closein0 + \input luamplib.cfg +\fi +% \end{macrocode} +% % That's all folks! % % \begin{macrocode} diff --git a/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua b/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua index 897dd456737..575e030539b 100644 --- a/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua +++ b/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua @@ -18,8 +18,8 @@ luamplib.lastlog = "" local err, warn, info, log = luatexbase.provides_module({ name = "luamplib", - version = "2.5.1", - date = "2014/02/19", + version = "2.5.3", + date = "2014/03/01", description = "Lua package to typeset Metapost with LuaTeX's MPLib.", }) @@ -35,6 +35,12 @@ local texsprint = tex.sprint local mplib = require ('mplib') local kpse = require ('kpse') +local lfs = require ('lfs') + +local lfsattributes = lfs.attributes +local lfsisdir = lfs.isdir +local lfstouch = lfs.touch +local ioopen = io.open local file = file if not file then @@ -51,49 +57,44 @@ if not file then end end -local mpreplacedabove = {} +local luamplibtime = kpse.find_file("luamplib.lua") +luamplibtime = luamplibtime and lfsattributes(luamplibtime,"modification") -local function replaceinputmpfile (file) - local fh = io.open(file,"r") - if not fh then return file end - local data = fh:read("*all"); fh:close() - data = stringgsub(data, "\".-\"", - function(str) - str = stringgsub(str,"%%","*****PERCENT*****") - str = stringgsub(str,"([bm])tex%f[^A-Z_a-z]","%1***T***E***X***") - return str - end) - data = stringgsub(data,"%%.-\n","") - local count,cnt = 0,0 - data,cnt = stringgsub(data, - "%f[A-Z_a-z]btex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", - function(str) - str = stringgsub(str,"[\n\r]%s*"," ") - str = stringgsub(str,'"','"&ditto&"') - return format("rawtextext(\"%s\")",str) - end) - count = count + cnt - data,cnt = stringgsub(data, - "%f[A-Z_a-z]verbatimtex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", - "") - count = count + cnt - if count == 0 then - mpreplacedabove[file] = file - return file +local currenttime = os.time() + +local outputdir = "." +for _,v in ipairs(arg) do + local t = stringmatch(v,"%-output%-directory=(.+)") + if t then + outputdir = t + break + end +end + +function luamplib.getcachedir(dir) + dir = stringgsub(dir,"##","#") + dir = stringgsub(dir,"^~", + os.type == "windows" and os.getenv("UserProfile") or os.getenv("HOME")) + if lfstouch and dir then + if lfsisdir(dir) then + local tmp = dir.."/_luam_plib_temp_file_" + local fh = ioopen(tmp,"w") + if fh then + fh:close(fh) + os.remove(tmp) + luamplib.cachedir = dir + else + warn("Directory '"..dir.."' is not writable!") + end + else + warn("Directory '"..dir.."' does not exist!") end - data = stringgsub(data,"([bm])***T***E***X***","%1tex") - data = stringgsub(data,"*****PERCENT*****","%%") - local newfile = stringgsub(file,".*/","luamplib_input_") - fh = io.open(newfile,"w") - if not fh then return file end - fh:write(data); fh:close() - mpreplacedabove[file] = newfile - return newfile + end end local noneedtoreplace = { ["boxes.mp"] = true, - ["format.mp"] = true, +-- ["format.mp"] = true, ["graph.mp"] = true, ["marith.mp"] = true, ["mfplain.mp"] = true, @@ -128,6 +129,80 @@ local noneedtoreplace = { ["mp-text.mpiv"] = true, ["mp-tool.mpiv"] = true, } +luamplib.noneedtoreplace = noneedtoreplace + +local function replaceformatmp(file,newfile,ofmodify) + local fh = ioopen(file,"r") + if not fh then return file end + local data = fh:read("*all"); fh:close() + fh = ioopen(newfile,"w") + if not fh then return file end + fh:write( + "let normalinfont = infont;\n", + "primarydef str infont name = rawtextext(str) enddef;\n", + data, + "vardef Fmant_(expr x) = rawtextext(decimal abs x) enddef;\n", + "vardef Fexp_(expr x) = rawtextext(\"$^{\"&decimal x&\"}$\") enddef;\n", + "let infont = normalinfont;\n" + ); fh:close() + lfstouch(newfile,currenttime,ofmodify) + return newfile +end + +local function replaceinputmpfile (name,file) + local ofmodify = lfsattributes(file,"modification") + if not ofmodify then return file end + local cachedir = luamplib.cachedir or outputdir + local newfile = stringgsub(name,"%W","_") + newfile = cachedir .."/luamplib_input_"..newfile + if newfile and luamplibtime then + local nf = lfsattributes(newfile) + if nf and nf.mode == "file" and ofmodify == nf.modification and luamplibtime < nf.access then + return nf.size == 0 and file or newfile + end + end + if name == "format.mp" then return replaceformatmp(file,newfile,ofmodify) end + + local fh = ioopen(file,"r") + if not fh then return file end + local data = fh:read("*all"); fh:close() + data = stringgsub(data, "\"[^\n]-\"", + function(str) + str = stringgsub(str,"%%","*****PERCENT*****") + str = stringgsub(str,"([bem])tex%f[^A-Z_a-z]","%1***T***E***X***") + return str + end) + data = stringgsub(data,"%%.-\n","") + local count,cnt = 0,0 + data,cnt = stringgsub(data, + "%f[A-Z_a-z]btex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", + function(str) + str = stringgsub(str,"[\n\r]%s*"," ") + str = stringgsub(str,'"','"&ditto&"') + return format("rawtextext(\"%s\")",str) + end) + count = count + cnt + data,cnt = stringgsub(data, + "%f[A-Z_a-z]verbatimtex%f[^A-Z_a-z]%s*.-%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", + "") + count = count + cnt + if count == 0 then + noneedtoreplace[name] = true + fh = ioopen(newfile,"w"); + if fh then + fh:close() + lfstouch(newfile,currenttime,ofmodify) + end + return file + end + data = stringgsub(data,"([bem])***T***E***X***","%1tex") + data = stringgsub(data,"*****PERCENT*****","%%") + fh = ioopen(newfile,"w") + if not fh then return file end + fh:write(data); fh:close() + lfstouch(newfile,currenttime,ofmodify) + return newfile +end local mpkpse = kpse.new("luatex", "mpost") @@ -137,9 +212,10 @@ local function finder(name, mode, ftype) else local file = mpkpse:find_file(name,ftype) if file then - if ftype ~= "mp" or noneedtoreplace[name] then return file end - if mpreplacedabove[file] then return mpreplacedabove[file] end - return replaceinputmpfile(file) + if not lfstouch or ftype ~= "mp" or noneedtoreplace[name] then + return file + end + return replaceinputmpfile(name,file) end return mpkpse:find_file(name,stringmatch(name,"[a-zA-Z]+$")) end @@ -205,7 +281,6 @@ else end function luamplib.load(name) - mpreplacedabove = {} -- reset local mpx = mplib.new { ini_version = true, find_file = luamplib.finder, @@ -485,54 +560,42 @@ extra_endfig := extra_endfig & " let VerbatimTeX = specialVerbatimTeX;" ; local function protecttextext(data) local everymplib = tex.toks['everymplibtoks'] or '' local everyendmplib = tex.toks['everyendmplibtoks'] or '' - data = " " .. everymplib .. data .. everyendmplib + data = "\n" .. everymplib .."\n".. data .."\n".. everyendmplib + data = stringgsub(data,"\r","\n") + data = stringgsub(data, "\"[^\n]-\"", + function(str) + str = stringgsub(str,"%%","****PERCENT****") + str = stringgsub(str,"([bem])tex%f[^A-Z_a-z]","%1***T***E***X***") + return str + end) + data = stringgsub(data,"%%.-\n","") data = stringgsub(data, "%f[A-Z_a-z]btex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", function(str) str = stringgsub(str,'"','"&ditto&"') - return format("rawtextext(\\unexpanded{\"%s\"})",str) + str = stringgsub(str,"\n%s*"," ") + return format("rawtextext(\"%s\")",str) end) data = stringgsub(data, "%f[A-Z_a-z]verbatimtex%f[^A-Z_a-z]%s*(.-)%s*%f[A-Z_a-z]etex%f[^A-Z_a-z]", function(str) str = stringgsub(str,'"','"&ditto&"') - return format("VerbatimTeX(\\unexpanded{\"%s\"})",str) + str = stringgsub(str,"\n%s*"," ") + return format("VerbatimTeX(\"%s\")",str) end) - data = stringgsub(data, "\".-\"", -- hack for parentheses inside quotes + data = stringgsub(data, "\"[^\n]-\"", function(str) - str = stringgsub(str,"%(","%%%%LEFTPAREN%%%%") - str = stringgsub(str,"%)","%%%%RGHTPAREN%%%%") - return str + str = stringgsub(str,"([bem])***T***E***X***","%1tex") + str = stringgsub(str,"{", "****LEFTBRCE****") + str = stringgsub(str,"}", "****RGHTBRCE****") + str = stringgsub(str,"#", "****SHARPE****") + return format("\\unexpanded{%s}",str) end) - data = stringgsub(data, "%f[A-Z_a-z]TEX%s*%b()", "\\unexpanded{%1}") - data = stringgsub(data, "%f[A-Z_a-z]textext%s*%b()", "\\unexpanded{%1}") - data = stringgsub(data, "%f[A-Z_a-z]textext%.[_a-z]+%s*%b()", "\\unexpanded{%1}") - data = stringgsub(data, "%%%%LEFTPAREN%%%%", "(") -- restore - data = stringgsub(data, "%%%%RGHTPAREN%%%%", ")") -- restore texsprint(data) end luamplib.protecttextext = protecttextext -local factor = 65536*(7227/7200) - -local function putTEXboxes (object,prescript) - local box = prescript.MPlibTEXboxID - local n,tw,th = box[1],box[2],box[3] - if n and tw and th then - local op = object.path - local first, second, fourth = op[1], op[2], op[4] - local tx, ty = first.x_coord, first.y_coord - local sx, sy = (second.x_coord - tx)/tw, (fourth.y_coord - ty)/th - local rx, ry = (second.y_coord - ty)/tw, (fourth.x_coord - tx)/th - if sx == 0 then sx = 0.00001 end - if sy == 0 then sy = 0.00001 end - pdf_literalcode("q %f %f %f %f %f %f cm",sx,rx,ry,sy,tx,ty) - texsprint(format("\\mplibputtextbox{%i}",n)) - pdf_literalcode("Q") - end -end - local TeX_code_t = {} local function domakeTEXboxes (data) @@ -565,6 +628,10 @@ end local function makeTEXboxes (data) data = stringgsub(data, "##", "#") -- restore # doubled in input string + data = stringgsub(data, "****PERCENT****", "%%") + data = stringgsub(data, "****LEFTBRCE****","{") + data = stringgsub(data, "****RGHTBRCE****","}") + data = stringgsub(data, "****SHARPE****", "#" ) local mpx = luamplib.load(currentformat) if mpx and data then local result = mpx:execute(mplibcodepreamble .. data) @@ -575,6 +642,8 @@ end luamplib.makeTEXboxes = makeTEXboxes +local factor = 65536*(7227/7200) + local function processwithTEXboxes (data) local num = tex.count[14] -- the same newbox register local prepreamble = "TEXBOX_ := "..num..";\n" @@ -592,6 +661,23 @@ end luamplib.processwithTEXboxes = processwithTEXboxes +local function putTEXboxes (object,prescript) + local box = prescript.MPlibTEXboxID + local n,tw,th = box[1],box[2],box[3] + if n and tw and th then + local op = object.path + local first, second, fourth = op[1], op[2], op[4] + local tx, ty = first.x_coord, first.y_coord + local sx, sy = (second.x_coord - tx)/tw, (fourth.y_coord - ty)/th + local rx, ry = (second.y_coord - ty)/tw, (fourth.x_coord - tx)/th + if sx == 0 then sx = 0.00001 end + if sy == 0 then sy = 0.00001 end + pdf_literalcode("q %f %f %f %f %f %f cm",sx,rx,ry,sy,tx,ty) + texsprint(format("\\mplibputtextbox{%i}",n)) + pdf_literalcode("Q") + end +end + local pdf_objs = {} -- objstr => obj , new diff --git a/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty b/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty index efa971be27f..be85a430f32 100644 --- a/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty +++ b/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty @@ -14,7 +14,7 @@ \else \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luamplib} - [2014/02/19 v2.5.1 mplib package for LuaTeX] + [2014/03/01 v2.5.3 mplib package for LuaTeX] \RequirePackage{luatexbase-modutils} \RequirePackage{pdftexcmds} \fi @@ -36,33 +36,49 @@ \fi \def\mplibsetupcatcodes{% %catcode`\{=12 %catcode`\}=12 - \catcode`\#=12 - \catcode`\^=12 \catcode`\~=12 \catcode`\_=12 - %catcode`\%=12 %% don’t in Plain! - \catcode`\&=12 \catcode`\$=12 + \catcode`\#=12 \catcode`\^=12 \catcode`\~=12 \catcode`\_=12 + \catcode`\&=12 \catcode`\$=12 \catcode`\%=12 \catcode`\^^M=12 \endlinechar=10 } \def\mplibputtextbox#1{\vbox to 0pt{\vss\hbox to 0pt{\raise\dp#1\copy#1\hss}}} +\newcount\mplibstartlineno +\def\mplibpostmpcatcodes{% + \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\%=12 } +\def\mplibreplacenewlinebr{% + \begingroup \mplibpostmpcatcodes \mplibdoreplacenewlinebr} +\begingroup\lccode`\~=`\^^M \lowercase{% + \gdef\mplibdoreplacenewlinebr#1^^J{\endgroup\luatexscantextokens{{}#1~}}} +\endgroup \bgroup\expandafter\expandafter\expandafter\egroup \expandafter\ifx\csname ProvidesPackage\endcsname\relax +\def\mplibreplacenewlinecs{% + \begingroup \mplibpostmpcatcodes \mplibdoreplacenewlinecs} +\begingroup\lccode`\~=`\^^M \lowercase{% + \gdef\mplibdoreplacenewlinecs#1^^J{\endgroup\luatexscantextokens{\relax#1~}}} +\endgroup \def\mplibcode{% + \mplibstartlineno\inputlineno + \begingroup \begingroup - \bgroup \mplibsetupcatcodes - \mplibdocode % + \mplibdocode } \long\def\mplibdocode#1\endmplibcode{% - \egroup + \endgroup \def\mplibtemp{\directlua{luamplib.protecttextext([===[\unexpanded{#1}]===])}}% \directlua{luamplib.tempdata = luamplib.makeTEXboxes([===[\mplibtemp]===])}% \directlua{luamplib.processwithTEXboxes(luamplib.tempdata)}% \endgroup + \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinecs\fi } \else -\newenvironment{mplibcode}{\toks@{}\ltxdomplibcode}{} +\newenvironment{mplibcode}{% + \global\mplibstartlineno\inputlineno + \toks@{}\ltxdomplibcode +}{} \def\ltxdomplibcode{% \begingroup \mplibsetupcatcodes - \ltxdomplibcodeindeed % + \ltxdomplibcodeindeed } \long\def\ltxdomplibcodeindeed#1\end#2{% \endgroup @@ -72,6 +88,9 @@ \directlua{luamplib.tempdata=luamplib.makeTEXboxes([===[\reserved@a]===])}% \directlua{luamplib.processwithTEXboxes(luamplib.tempdata)}% \end{mplibcode}% + \ifnum\mplibstartlineno<\inputlineno + \expandafter\expandafter\expandafter\mplibreplacenewlinebr + \fi \else \toks@\expandafter{\the\toks@\end{#2}}\expandafter\ltxdomplibcode \fi @@ -80,25 +99,52 @@ \newtoks\everymplibtoks \newtoks\everyendmplibtoks \protected\def\everymplib{% + \mplibstartlineno\inputlineno \begingroup \mplibsetupcatcodes \mplibdoeverymplib } -\def\mplibdoeverymplib#1{% +\long\def\mplibdoeverymplib#1{% \endgroup \everymplibtoks{#1}% + \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi } \protected\def\everyendmplib{% + \mplibstartlineno\inputlineno \begingroup \mplibsetupcatcodes \mplibdoeveryendmplib } -\def\mplibdoeveryendmplib#1{% +\long\def\mplibdoeveryendmplib#1{% \endgroup \everyendmplibtoks{#1}% + \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi } \def\mpdim#1{ begingroup \the\dimexpr #1\relax\space endgroup } % gmp.sty \def\mplibnumbersystem#1{\directlua{luamplib.numbersystem = "#1"}} +\def\mplibmakenocache#1{\mplibdomakenocache #1,*,} +\def\mplibdomakenocache#1,{% + \ifx\empty#1\empty + \expandafter\mplibdomakenocache + \else + \ifx*#1\else + \directlua{luamplib.noneedtoreplace["#1.mp"]=true}% + \expandafter\expandafter\expandafter\mplibdomakenocache + \fi + \fi +} +\def\mplibcancelnocache#1{\mplibdocancelnocache #1,*,} +\def\mplibdocancelnocache#1,{% + \ifx\empty#1\empty + \expandafter\mplibdocancelnocache + \else + \ifx*#1\else + \directlua{luamplib.noneedtoreplace["#1.mp"]=false}% + \expandafter\expandafter\expandafter\mplibdocancelnocache + \fi + \fi +} +\def\mplibcachedir#1{\directlua{luamplib.getcachedir("\unexpanded{#1}")}} \ifx\mplibscratchbox\undefined \newbox\mplibscratchbox \fi \def\mplibstarttoPDF#1#2#3#4{% \hbox\bgroup @@ -147,6 +193,11 @@ \box\mplibscratchbox \endgroup } +\openin0=luamplib.cfg +\ifeof0 \else + \closein0 + \input luamplib.cfg +\fi \endinput %% %% End of file `luamplib.sty'. -- cgit v1.2.3