diff options
Diffstat (limited to 'Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx')
-rw-r--r-- | Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx new file mode 100644 index 00000000000..9c2936f4ce8 --- /dev/null +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx @@ -0,0 +1,544 @@ +% \iffalse meta-comment +% +% Written in 2009, 2010 by Manuel Pégourié-Gonnard and Élie Roux. +% <mpg@elzevir.fr> +% <elie.roux@telecom-bretagne.eu> +% +% This work is under the CC0 license. +% +% This work consists of the main source file luatexbase-modutils.dtx +% and the derived files +% luatexbase-modutils.sty modutils.lua +% test-modutils-plain.tex test-modutils-latex.tex test-modutils.lua +% +% Unpacking: +% tex luatexbase-modutils.dtx +% Documentation: +% pdflatex luatexbase-modutils.dtx +% +%<*ignore> +\begingroup + \def\x{LaTeX2e}% +\expandafter\endgroup +\ifcase 0\ifx\install y1\fi\expandafter + \ifx\csname processbatchFile\endcsname\relax\else1\fi + \ifx\fmtname\x\else 1\fi\relax +\else\csname fi\endcsname +%</ignore> +%<*install> +\input docstrip.tex + +\keepsilent +\askforoverwritefalse + +\let\MetaPrefix\relax + +\preamble + +Written in 2009, 2010 by Manuel Pegourie-Gonnard and Elie Roux. + +This work is under the CC0 license. +See source file '\inFileName' for details. + +\endpreamble + +\let\MetaPrefix\DoubleperCent + +\generate{% + \usedir{tex/luatex/luatexbase}% + \file{luatexbase-modutils.sty}{\from{luatexbase-modutils.dtx}{texpackage}}% +} + +\generate{% + \usedir{doc/luatex/luatexbase}% + \file{test-modutils-plain.tex}{\from{luatexbase-modutils.dtx}{testplain}}% + \file{test-modutils-latex.tex}{\from{luatexbase-modutils.dtx}{testlatex}}% +} + +\def\MetaPrefix{-- } + +\def\luapostamble{% + \MetaPrefix^^J% + \MetaPrefix\space End of File `\outFileName'.% +} + +\def\currentpostamble{\luapostamble}% + +\generate{% + \usedir{tex/luatex/luatexbase}% + \file{modutils.lua}{\from{luatexbase-modutils.dtx}{luamodule}}% + \usedir{doc/luatex/luatexbase}% + \file{test-modutils.lua}{\from{luatexbase-modutils.dtx}{testdummy}}% +} + +\obeyspaces +\Msg{************************************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the following} +\Msg{* files into a directory searched by TeX:} +\Msg{*} +\Msg{* luatexbase-modutils.sty modutils.lua} +\Msg{*} +\Msg{* Happy TeXing!} +\Msg{*} +\Msg{************************************************************************} + +\endbatchfile +%</install> +%<*ignore> +\fi +%</ignore> +%<*driver> +\documentclass{ltxdoc} +\input{lltxb-dtxstyle} +\begin{document} + \DocInput{luatexbase-modutils.dtx}% +\end{document} +%</driver> +% \fi +% +% \CheckSum{0} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% \title{The \pk{luatexbase-modutils} package} +% \date{v0.2 2010-05-12} +% \author{% +% Manuel P\'egouri\'e-Gonnard \\ \email{mpg@elzevir.fr} \and +% \'Elie Roux \\ \email{elie.roux@telecom-bretagne.eu}} +% +% \maketitle +% +% \begin{abstract} +% This package provides functions similar to \latex's |\usepackage| and +% |\ProvidesPackage| macros,\footnote{and their variants or synonyms such as +% \cs{documentclass} and \cs{RequirePackage} or \cs{ProvidesClass} and +% \cs{ProvidesFiles}} or more precisely the part of these macros that deals +% with identification and version checking (no attempt is done at implementing +% an option mechanism). Functions for error reporting are provided too. +% +% It also loads \pk{luatexbase-loader}. +% \end{abstract} +% +% \tableofcontents +% +% \section{Documentation} +% +% Lua's standard function |require()| is similar to \tex's |\input| primitive +% but is somehow more evolved in that it makes a few checks to avoid loading +% the same module twice. In the \tex world, this needs to be taken care of by +% macro packages; in the \latex world this is done by |\usepackage|. +% +% But |\usepackage| also takes care of many other things. Most notably, it +% implements a complex option system, and does some identification and version +% checking. The present package doesn't try to provide anything for options, +% but implements a system for identification and version checking similar to +% \latex's system. Both \tex macros and Lua functions are provided. +% +% This package also provides Lua functions for reporting errors, warnings, +% etc. +% +% It is important to notice that Lua's standard function |module()| is +% completely unrelated to the present package. It has nothing to do with +% identification and deals only with namespaces.\footnote{More precisely, it +% modifies the current environment.} So, you should continue to +% use it normally, unlike the |require()| function which can be replaced with +% this package's |luatexbase.require_module()|. +% +% \subsection{\tex macros} +% +% The two macros |\luatexUseModule| and |\luatexRequireModule| are very +% similar and are interfaces to the Lua functions |use_module| and +% |require_module|. The only difference between those macros is the number of +% arguments (just as the underlying Lua functions): |\luatexUseModule| only +% take one argument: the module name\footnote{without extension} while +% |\luatexRequireModule| takes another argument for specifying a minimal +% version (see below). With \latex, this argument is the first and is +% optional. Otherwise, it's the second one and it's mandatory. +% +% \subsection{Lua functions} +% +% The main functions are |luatexbase.require_module| and +% |luatexbase.use_module| which may be used as a replacement to |require()|. +% The only difference between these functions is, |require_module| accepts a +% second, optional argument in order to specify a minimal version. They do the +% same as |require()| but also make sure the module loaded correctly +% identifies itself with the name given, and its version is greater than the +% minimal version required. The version can be given either as a (floating +% point) number or as a date in YYYY/MM/DD format. +% +% Modules identify themselves using |luatexbase.provides_module|, whose only +% argument is a table with some information about the module. The mandatory +% fields are |name| (a string), |version| (a number), |date| (a string) and +% |description| (a string). Other fields are optional and ignored, and usually +% include |copyright|, |author| and |license|. +% +% \bigskip +% +% Functions for reporting are provided; similarly to \latex's |\PackageError| +% etc. they take the module name as their first argument and include it in the +% printed message in an appropriate way. The remaining arguments are passed to +% |string.format()| before being printed. +% +% The functions provided (all found in the |luatexbase| table) are +% |module_error|, |module_warning|, |module_info| (writes to terminal and +% log), |module_log| (writes only to the log file) and |module_term| (writes +% only to the terminal). +% +% \section{Implementation} +% +% \subsection{\tex package} +% +% \begin{macrocode} +%<*texpackage> +% \end{macrocode} +% +% \subsubsection{Preliminaries} +% +% Reload protection, especially for \plaintex. +% +% \begin{macrocode} + \csname lltxb@modutils@loaded\endcsname +\expandafter\let\csname lltxb@modutils@loaded\endcsname\endinput +% \end{macrocode} +% +% Catcode defenses. +% +% \begin{macrocode} +\begingroup + \catcode123 1 % { + \catcode125 2 % } + \catcode 35 6 % # + \toks0{}% + \def\x{}% + \def\y#1 #2 {% + \toks0\expandafter{\the\toks0 \catcode#1 \the\catcode#1}% + \edef\x{\x \catcode#1 #2}}% + \y 123 1 % { + \y 125 2 % } + \y 35 6 % # + \y 10 12 % ^^J + \y 34 12 % " + \y 36 3 % $ $ + \y 39 12 % ' + \y 40 12 % ( + \y 41 12 % ) + \y 42 12 % * + \y 43 12 % + + \y 44 12 % , + \y 45 12 % - + \y 46 12 % . + \y 47 12 % / + \y 60 12 % < + \y 61 12 % = + \y 64 11 % @ (letter) + \y 62 12 % > + \y 95 12 % _ (other) + \y 96 12 % ` + \edef\y#1{\endgroup\edef#1{\the\toks0\relax}\x}% +\expandafter\y\csname lltxb@modutils@AtEnd\endcsname +% \end{macrocode} +% +% Package declaration. +% +% \begin{macrocode} +\begingroup + \expandafter\ifx\csname ProvidesPackage\endcsname\relax + \def\x#1[#2]{\immediate\write16{Package: #1 #2}} + \else + \let\x\ProvidesPackage + \fi +\expandafter\endgroup +\x{luatexbase-modutils}[2010/05/12 v0.2 Module utilities for LuaTeX] +% \end{macrocode} +% +% Make sure \luatex is used. +% +% \begin{macrocode} +\begingroup\expandafter\expandafter\expandafter\endgroup +\expandafter\ifx\csname RequirePackage\endcsname\relax + \input ifluatex.sty +\else + \RequirePackage{ifluatex} +\fi +\ifluatex\else + \begingroup + \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax + \def\x#1#2{\begingroup\newlinechar10 + \immediate\write16{Package #1 warning: #2}\endgroup} + \else + \let\x\PackageWarningNoLine + \fi + \expandafter\endgroup + \x{luatexbase-modutils}{LuaTeX is required for this package. Aborting.} + \lltxb@modutils@AtEnd + \expandafter\endinput +\fi +% \end{macrocode} +% +% Load \pk{luatexbase-loader} (hence \pk{luatexbase-compat}) and require +% supporting Lua module. +% +% \begin{macrocode} +\begingroup\expandafter\expandafter\expandafter\endgroup +\expandafter\ifx\csname RequirePackage\endcsname\relax + \input luatexbase-loader.sty +\else + \RequirePackage{luatexbase-loader} +\fi +\luatexbase@directlua{require('luatexbase.modutils')} +% \end{macrocode} +% +% Make sure the primitives we need are available. +% +% \begin{macrocode} +\luatexbase@ensure@primitive{luaescapestring} +% \end{macrocode} +% +% \subsubsection{User macros} +% +% Interface to |use_module()|. +% +% \begin{macrocode} +\def\luatexUseModule#1{\luatexbase@directlua{% + luatexbase.use_module("\luatexluescapestring{#1}")}} +% \end{macrocode} +% +% Interface to |require_module()| with syntax depending on the format. +% +% \begin{macrocode} +\begingroup\expandafter\expandafter\expandafter\endgroup +\expandafter\ifx\csname newcommand\endcsname\relax + \def\luatexRequireModule#1#2{% + \luatexbase@directlua{luatexbase.require_module( + "\luatexluaescapestring{#1}", "\luatexluaescapestring{#2}")}} +\else + \newcommand\luatexRequireModule[2][0]{% + \luatexbase@directlua{luatexbase.require_module( + "\luatexluaescapestring{#2}", "\luatexluaescapestring{#1}")}} +\fi +% \end{macrocode} +% +% \begin{macrocode} +\lltxb@modutils@AtEnd +%</texpackage> +% \end{macrocode} +% +% \subsection{Lua module} +% +% \begin{macrocode} +%<*luamodule> +module("luatexbase", package.seeall) +% \end{macrocode} +% +% \subsection{Internal functions and data} +% +% Tables holding informations about the modules loaded and the versions +% required. +% +% \begin{macrocode} +local modules = modules or {} +local requiredversions = {} +% \end{macrocode} +% +% Convert a date in YYYY/MM/DD format into a number +% +% \begin{macrocode} +local function datetonumber(date) + numbers = string.gsub(date, "(%d+)/(%d+)/(%d+)", "%1%2%3") + return tonumber(numbers) +end +% \end{macrocode} +% +% Say if a string is a date in YYYY//MM/DD format. +% +% \begin{macrocode} +local function isdate(date) + for _, _ in string.gmatch(date, "%d+/%d+/%d+") do + return true + end + return false +end +% \end{macrocode} +% +% Parse a version into a table indicating a type (date or number), a +% numeric version and the original version string. +% +% \begin{macrocode} +local date, number = 1, 2 +local function parse_version(version) + if isdate(version) then + return {type = date, version = datetonumber(version), orig = version} + else + return {type = number, version = tonumber(version), orig = version} + end +end +% \end{macrocode} +% +% \subsubsection{Error, warning and info function for modules} +% +% Here are the reporting functions for the modules. For errors, Lua's +% |error()| is used. For now, the error reports look less good than with +% \tex's |\errmessage|, but hopefully it will be improved in future +% versions of \luatex. We could invoke |\errmessage| using |tex.sprint()|, +% but it may cause problems on the \tex end, and moreover |error()| will +% still be used by Lua for other errors, so it makes messages more +% consistent. +% +% \begin{macrocode} +local function module_error_int(mod, ...) + error('Module '..mod..' error: '..string.format(...), 3) +end +function module_error(mod, ...) + module_error_int(mod, ...) +end +function module_warning(mod, ...) + texio.write_nl("Module "..mod.." warning: "..string.format(...)) +end +function module_info(mod, ...) + texio.write_nl(mod..": "..string.format(...)) +end +function module_log(mod, ...) + texio.write_nl('log', mod..": "..string.format(...)) +end +function module_term(mod, ...) + texio.write_nl('term', mod..": "..string.format(...)) +end +% \end{macrocode} +% +% For our own convenience, local functions for warning and errors in the +% present module. +% +% \begin{macrocode} +local function err(...) module_error_int('luatexbase.modutils', ...) end +local function warn(...) module_warning('luatexbase.modutils', ...) end +% \end{macrocode} +% +% \subsubsection{module loading and providing functions} +% +% Load a module without version checking. +% +% \begin{macrocode} +function use_module(name) + require(name) + if not modules[name] then + warn("Module didn't properly identified itself: %s", name) + end +end +% \end{macrocode} +% +% Load a module with optional version checking. +% +% \begin{macrocode} +function require_module(name, version) + if not version then + return use_module(name) + end + luaversion = parse_version(version) + if modules[name] then + if luaversion.type == date then + if datetonumber(modules[name].date) < luaversion.version then + err("found module `%s' loaded in version %s, " + .."but version %s was required", + name, modules[name].date, version) + end + else + if modules[name].version < luaversion.version then + err("found module `%s' loaded in version %.02f, " + .."but version %s was required", + name, modules[name].version, version) + end + end + else + requiredversions[name] = luaversion + use_module(name) + end +end +% \end{macrocode} +% +% Provide identification information for a module. +% +% \begin{macrocode} +function provides_module(mod) + if not mod then + err('cannot provide nil module') + return + end + if not mod.version or not mod.name or not mod.date + or not mod.description then + err("invalid module registered: " + .."fields name, version, date and description are mandatory") + return + end + requiredversion = requiredversions[mod.name] + if requiredversion then + if requiredversion.type == date + and requiredversion.version > datetonumber(mod.date) then + err("loading module %s in version %s, " + .."but version %s was required", + mod.name, mod.date, requiredversion.orig) + elseif requiredversion.type == number + and requiredversion.version > mod.version then + err("loading module %s in version %.02f, " + .."but version %s was required", + mod.name, mod.version, requiredversion.orig) + end + end + modules[mod.name] = module + texio.write_nl('log', string.format("Lua module: %s %s v%.02f %s\n", + mod.name, mod.date, mod.version, mod.description)) +end +% \end{macrocode} +% +% \begin{macrocode} +%</luamodule> +% \end{macrocode} +% +% \section{Test files} +% +% A dummy lua file for tests. +% +% \begin{macrocode} +%<*testdummy> +luatexbase.provides_module { + name = 'test-modutils', + date = '2000/01/01', + version = 1, + description = 'dummy test package', +} +%</testdummy> +% \end{macrocode} +% +% We just check that the package loads properly, under both LaTeX and Plain +% TeX. Anyway, the test files of other modules using this one already are a +% test\dots +% +% \begin{macrocode} +%<testplain>\input luatexbase-modutils.sty +%<testlatex>\RequirePackage{luatexbase-modutils} +%<*testplain,testlatex> +\luatexRequireModule +%<testlatex>[1970/01/01] +{test-modutils} +%<testplain>{1970/01/01} +%</testplain,testlatex> +%<testplain>\bye +%<testlatex>\stop +% \end{macrocode} +% +% \Finale +\endinput |