diff options
author | Karl Berry <karl@freefriends.org> | 2014-03-06 23:02:07 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2014-03-06 23:02:07 +0000 |
commit | 2cae2bb164327cd36f426861958b9e76dbdfb80d (patch) | |
tree | 1095ab4ae2e813797ab3e02408060579b1f0ca32 /Master/texmf-dist/source/luatex | |
parent | eac3699c6b426ce060acf916c17d2b25f06f8818 (diff) |
luamplib (2mar14)
git-svn-id: svn://tug.org/texlive/trunk@33111 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/luatex')
-rw-r--r-- | Master/texmf-dist/source/luatex/luamplib/luamplib.dtx | 347 |
1 files changed, 256 insertions, 91 deletions
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{<filename>[,<filename>,...]}| +% \item |\mplibcancelnocache{<filename>[,<filename>,...]}| +% \end{itemize} +% where |<filename>| 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{<directory path>}|, 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} |