% \iffalse meta-comment % %% File: l3luatex.dtx Copyright (C) 2010-2016 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the "l3kernel bundle" (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX3 Project. %% %% ----------------------------------------------------------------------- % %<*driver> \documentclass[full]{l3doc} % %<*driver|package&tex> \GetIdInfo$Id: l3luatex.dtx 6465 2016-03-26 16:15:09Z joseph $ {L3 Experimental LuaTeX-specific functions} % %<*driver> \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \pkg{l3luatex} package\\LuaTeX-specific functions^^A % \thanks{This file describes v\ExplFileVersion, % last revised \ExplFileDate.}^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released \ExplFileDate} % % \maketitle % % \begin{documentation} % % \section{Breaking out to \Lua{}} % % The \LuaTeX{} engine provides access to the \Lua{} programming language, % and with it access to the \enquote{internals} of \TeX{}. In order to use % this within the framework provided here, a family of functions is % available. When used with \pdfTeX{} or \XeTeX{} these will raise an % error: use \cs{sys_if_engine_luatex:T} to avoid this. Details of coding % the \LuaTeX{} engine are detailed in the \LuaTeX{} manual. % % \subsection{\TeX{} code interfaces} % % \begin{function}[EXP, added = 2015-06-29]{\lua_now_x:n, \lua_now:n} % \begin{syntax} % \cs{lua_now:n} \Arg{token list} % \end{syntax} % The \meta{token list} is first tokenized by \TeX{}, which will include % converting line ends to spaces in the usual \TeX{} manner and which % respects currently-applicable \TeX{} category codes. The resulting % \meta{\Lua{} input} is passed to the \Lua{} interpreter for processing. % Each \cs{lua_now:n} block is treated by \Lua{} as a separate chunk. % The \Lua{} interpreter will execute the \meta{\Lua{} input} immediately, % and in an expandable manner. % % In the case of the \cs{lua_now_x:n} version the input is fully expanded % by \TeX{} in an \texttt{x}-type manner \emph{but} the function remains % fully expandable. % \begin{texnote} % \cs{lua_now_x:n} is a macro wrapper around \tn{directlua}: when % \LuaTeX{} is in use two expansions will be required to yield the % result of the \Lua{} code. % \end{texnote} % \end{function} % % \begin{function}[added = 2015-06-30]{\lua_shipout_x:n, \lua_shipout:n} % \begin{syntax} % \cs{lua_shipout:n} \Arg{token list} % \end{syntax} % The \meta{token list} is first tokenized by \TeX{}, which will include % converting line ends to spaces in the usual \TeX{} manner and which % respects currently-applicable \TeX{} category codes. The resulting % \meta{\Lua{} input} is passed to the \Lua{} interpreter when the % current page is finalised (\emph{i.e.}~at shipout). Each % \cs{lua_shipout:n} block is treated by \Lua{} as a separate chunk. % The \Lua{} interpreter will execute the \meta{\Lua{} input} during the % page-building routine: no \TeX{} expansion of the \meta{\Lua{} input} % will occur at this stage. % % In the case of the \cs{lua_shipout_x:n} version the input is fully % expanded by \TeX{} in an \texttt{x}-type manner during the shipout % operation. % \begin{texnote} % At a \TeX{} level, the \meta{\Lua{} input} is stored as a % \enquote{whatsit}. % \end{texnote} % \end{function} % % \begin{function}[EXP, added = 2015-06-29]{\lua_escape_x:n, \lua_escape:n} % \begin{syntax} % \cs{lua_escape:n} \Arg{token list} % \end{syntax} % Converts the \meta{token list} such that it can safely be passed to % \Lua{}: embedded backslashes, double and single quotes, and newlines % and carriage returns are escaped. This is done by prepending an extra % token consisting of a backslash with category code~$12$, and for the line % endings, converting them to |\n| and |\r|, respectively. % % In the case of the \cs{lua_escape_x:n} version the input is fully expanded % by \TeX{} in an \texttt{x}-type manner \emph{but} the function remains % fully expandable. % \begin{texnote} % \cs{lua_escape_x:n} is a macro wrapper around \tn{luaescapestring}: % when \LuaTeX{} is in use two expansions will be required to yield the % result of the \Lua{} code. % \end{texnote} % \end{function} % % \subsection{Lua interfaces} % % As well as interfaces for \TeX{}, there are a small number of Lua functions % provided here. Currently these are intended for internal use only. % % \begin{function}{l3kernel.strcmp} % \begin{syntax} % \cs{l3kernel.strcmp}|(|\meta{str one}, \meta{str two}|)| % \end{syntax} % Compares the two strings and returns |0| to \TeX{} % if the two are identical. % \end{function} % % \begin{function}{l3kernel.charcat} % \begin{syntax} % \cs{l3kernel.charcat}|(|\meta{charcode}, \meta{catcode}|)| % \end{syntax} % Constructs a character of \meta{charcode} and \meta{catcode} and returns % the result to \TeX{}. % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3luatex} implementation} % % \begin{macrocode} %<*initex|package> % \end{macrocode} % % \subsection{Breaking out to \Lua{}} % % \begin{macrocode} %<*tex> % \end{macrocode} % % \begin{macro}[EXP]{\lua_now_x:n, \lua_now:n} % \begin{macro}{\lua_shipout_x:n, \lua_shipout:n} % \begin{macro}[EXP]{\lua_escape_x:n, \lua_escape:n} % Wrappers around the primitives. As with engines other than \LuaTeX{} % these have to be macros, we give them the same status in all cases. % When \LuaTeX{} is not in use, simply give an error message/ % \begin{macrocode} \cs_new:Npn \lua_now_x:n #1 { \luatex_directlua:D {#1} } \cs_new:Npn \lua_now:n #1 { \lua_now_x:n { \exp_not:n {#1} } } \cs_new_protected:Npn \lua_shipout_x:n #1 { \luatex_latelua:D {#1} } \cs_new_protected:Npn \lua_shipout:n #1 { \lua_shipout_x:n { \exp_not:n {#1} } } \cs_new:Npn \lua_escape_x:n #1 { \luatex_luaescapestring:D {#1} } \cs_new:Npn \lua_escape:n #1 { \lua_escape_x:n { \exp_not:n {#1} } } \sys_if_engine_luatex:F { \clist_map_inline:nn { \lua_now_x:n , \lua_now:n , \lua_escape_x:n , \lua_escape:n } { \cs_set:Npn #1 ##1 { \__msg_kernel_expandable_error:nnn { kernel } { luatex-required } { #1 } } } \clist_map_inline:nn { \lua_shipout_x :n , \lua_shipout:n } { \cs_set_protected:Npn #1 ##1 { \__msg_kernel_error:nnn { kernel } { luatex-required } { #1 } } } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Messages} % % \begin{macrocode} \__msg_kernel_new:nnnn { kernel } { luatex-required } { LuaTeX~engine~not~in~use!~Ignoring~#1. } { The~feature~you~are~using~is~only~available~ with~the~LuaTeX~engine.~LaTeX3~ignored~'#1'. } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\Lua{} functions for internal use} % % \begin{macrocode} %<*lua> % \end{macrocode} % % \begin{macro}{l3kernel} % Create a table for the kernel's own use. % \begin{macrocode} l3kernel = l3kernel or { } % \end{macrocode} % \end{macro} % % Various local copies of standard functions: naming convention is to retain % the full text but replace all |.| by |_|. % \begin{macrocode} local tex_setcatcode = tex.setcatcode local tex_sprint = tex.sprint local tex_write = tex.write local unicode_utf8_char = unicode.utf8.char % \end{macrocode} % % \begin{macro}{l3kernel.strcmp} % String comparison which gives the same results as \pdfTeX{}'s % \tn{pdfstrcmp}, although the ordering should likely not be relied upon! % \begin{macrocode} local function strcmp (A, B) if A == B then tex_write("0") elseif A < B then tex_write("-1") else tex_write("1") end end l3kernel.strcmp = strcmp % \end{macrocode} % \end{macro} % % \begin{macro}{l3kernel.charcat} % Creating arbitrary chars needs a category code table. As set up here, % one may have been assigned earlier (see \pkg{l3bootstrap}) or a hard-coded % one is used. The latter is intended for format mode and should be adjusted % to match an eventual allocator. % \begin{macrocode} local charcat_table = l3kernel.charcat_table or 1 local function charcat (charcode, catcode) tex_setcatcode(charcat_table, charcode, catcode) tex_sprint(charcat_table, unicode_utf8_char(charcode)) end l3kernel.charcat = charcat % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{Format mode code: font loader} % % \begin{macrocode} %<*fontloader> % \end{macrocode} % % In format mode, there needs to be a font loader available to let us % use OpenType fonts. For testing, this is provided by % \texttt{fontloader.lua} from the Speedata Publisher system % (\url{https://github.com/speedata/publisher}). The code there is designed % to be self-contained and has a certain number of build-in assumptions, % so there is a small amount of compatibility required. % % The code we load looks up \texttt{texmf} tree files using % \texttt{kpse.filelist}, which isn't part of the standard \texttt{kpse} % library. The interface is emulated using metatable. % \begin{macrocode} kpse.filelist = setmetatable({}, { __index = function (t, key) return kpse.lookup(key) end }) % \end{macrocode} % There is a built-in assumption in \texttt{fontloader.lua} that various % environmental variables are set. We deal with that by intercepting the % relevant names and returning something sane. % \begin{macrocode} local os_getenv = os.getenv function os.getenv (var) if var == "SP_FONT_PATH" then return "" end return os_getenv(var) end % \end{macrocode} % As detailed in % \url{https://github.com/speedata/publisher/blob/develop/COPYING}, the current % license for Speedata Publisher is \textsc{AGPLv3}. We therefore only % load the file and use its public interfaces rather than copying/modifying % the code itself. Note though that we do have permission to use % \texttt{fontloader.lua} as a public domain work % (\url{http://chat.stackexchange.com/transcript/message/27273687#27273687}): % if we want to develop a richer loader we may want to take advantage of that % (which also applies to the simple shaper in the related \texttt{fonts.lua} % file). % \begin{macrocode} local fontloader = require("fontloader.lua") % \end{macrocode} % That done, register a callback which at present simply passes everything % through. There's no attempt to pick up font settings (which presumably % will be needed). Syntax is coerced to the same as for \XeTeX{}. % \begin{macrocode} callback.register("define_font", function (name, size, id) local opts, opttab, otfeatures = "", { }, { } if string.match(name, "^%[") then name, opts = string.match(name, "^%[([^%]]*)%][^:]*:?(.*)") end if opts ~= "" then for _,kv in ipairs(string.explode(opts,";")) do if string.match(kv, "=") then local k, v = string.match(kv, "([^=]*)=?(.*)") opttab[k] = v else if string.match(kv, "^+") then otfeatures[string.sub(kv,2,-1)] = "true" elseif string.match(kv, "^-") then otfeatures[string.sub(kv,2,-1)] = "false" else otfeatures[kv] = "true" end end end end if next(otfeatures) then opttab["otfeatures"] = otfeatures end return select(2, fontloader.define_font(name, size, opttab)) end ) % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % %\end{implementation} % %\PrintIndex