From 75a9ad6b597ca31c07f38850761832951b0f6224 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 18 Nov 2010 00:35:41 +0000 Subject: luatexbase (17nov10) git-svn-id: svn://tug.org/texlive/trunk@20476 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/luatex/luatexbase/Changes | 30 +- Master/texmf-dist/doc/luatex/luatexbase/README | 15 +- Master/texmf-dist/doc/luatex/luatexbase/TODO | 48 +- .../doc/luatex/luatexbase/luatexbase-attr.pdf | Bin 333424 -> 333430 bytes .../doc/luatex/luatexbase/luatexbase-cctb.pdf | Bin 390323 -> 371582 bytes .../doc/luatex/luatexbase/luatexbase-compat.pdf | Bin 427408 -> 426509 bytes .../doc/luatex/luatexbase/luatexbase-loader.pdf | Bin 398854 -> 379396 bytes .../doc/luatex/luatexbase/luatexbase-mcb.pdf | Bin 348362 -> 419935 bytes .../doc/luatex/luatexbase/luatexbase-modutils.pdf | Bin 416741 -> 430199 bytes .../doc/luatex/luatexbase/luatexbase-regs.pdf | Bin 376886 -> 376442 bytes .../doc/luatex/luatexbase/luatexbase.pdf | Bin 320564 -> 321844 bytes .../doc/luatex/luatexbase/test-cctb-latex.tex | 24 +- .../doc/luatex/luatexbase/test-cctb-plain.tex | 24 +- .../doc/luatex/luatexbase/test-mcb-aux.tex | 1 + .../doc/luatex/luatexbase/test-mcb-latex.tex | 52 +- .../doc/luatex/luatexbase/test-mcb-plain.tex | 51 +- .../texmf-dist/doc/luatex/luatexbase/test-mcb.lua | 132 +++ .../doc/luatex/luatexbase/test-modutils-latex.tex | 6 +- .../doc/luatex/luatexbase/test-modutils-plain.tex | 6 +- .../doc/luatex/luatexbase/test-modutils.lua | 4 +- .../texmf-dist/source/luatex/luatexbase/Makefile | 25 +- .../source/luatex/luatexbase/luatexbase-attr.dtx | 21 +- .../source/luatex/luatexbase/luatexbase-cctb.dtx | 48 +- .../source/luatex/luatexbase/luatexbase-compat.dtx | 21 +- .../source/luatex/luatexbase/luatexbase-loader.dtx | 21 +- .../source/luatex/luatexbase/luatexbase-mcb.dtx | 984 +++++++++++++-------- .../luatex/luatexbase/luatexbase-modutils.dtx | 469 ++++++---- .../source/luatex/luatexbase/luatexbase-regs.dtx | 23 +- .../source/luatex/luatexbase/luatexbase.dtx | 55 +- .../tex/luatex/luatexbase/luatexbase-attr.sty | 15 +- .../tex/luatex/luatexbase/luatexbase-cctb.sty | 15 +- .../tex/luatex/luatexbase/luatexbase-compat.sty | 15 +- .../tex/luatex/luatexbase/luatexbase-loader.sty | 15 +- .../tex/luatex/luatexbase/luatexbase-mcb.sty | 15 +- .../tex/luatex/luatexbase/luatexbase-modutils.sty | 75 +- .../tex/luatex/luatexbase/luatexbase-regs.sty | 17 +- .../tex/luatex/luatexbase/luatexbase.sty | 19 +- Master/texmf-dist/tex/luatex/luatexbase/mcb.lua | 366 ++++---- .../texmf-dist/tex/luatex/luatexbase/modutils.lua | 113 +-- 39 files changed, 1637 insertions(+), 1088 deletions(-) create mode 100644 Master/texmf-dist/doc/luatex/luatexbase/test-mcb-aux.tex create mode 100644 Master/texmf-dist/doc/luatex/luatexbase/test-mcb.lua diff --git a/Master/texmf-dist/doc/luatex/luatexbase/Changes b/Master/texmf-dist/doc/luatex/luatexbase/Changes index 2db8f802daf..d41f72290b6 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/Changes +++ b/Master/texmf-dist/doc/luatex/luatexbase/Changes @@ -1,7 +1,33 @@ Changes in the luatexbase package/bundle +The [BI] tag signals backward-incompatible changes. +Starting with v0.3, the only possible source of such changes is the upcoming +merge with luatex.sty. Afterwards, no other BI change is to be expected. + +2010/10/10 v0.3 + all not using LuaTeX results in an error (formerly a warning) + modutils + - [BI] \luatexUseModule and \luatexRequireModule replaced by + \RequireLuaModule with a unified syntax. + - [BI] luatexbase.use_module removed (use luatexbase.require_module with + a single argument instead). + - [BI] luatexbase.module_term removed. + - [BI] removed support for version check using a floating point + number, only date is supported now. + - module_{error,warning,info,log} now apply string.format + automatically + - date, version and description are now optional. + - improved formatting of messages. + - luatexbase.require_module now returns curstom err/war/inf functions. + mcb + - [BI] rationalise "list"-type callbacks handling. The new calling + convention differs from the old one only in edge cases. + - add user documentation + - misc code tuning (more locals, etc) + 2010/10/04 - various documentation updates/fixes uploaded to CTAN + - various documentation updates/fixes uploaded to CTAN + - luatexbase.sty used to be broken on CTAN (bad docstrip) 2010/05/27 v0.2a attr @@ -12,7 +38,7 @@ luatexbase - new, loads: compat,loader,regs,attr,cctb. -Summary of backwards-incompatible interface changes between 0.1 and 0.2: +[BI] Summary of backwards-incompatible interface changes between 0.1 and 0.2: - Lua objects are now in table luatexbase, not luatextra. - Lua tables tex.attributenumber and tex.catcodetablenumber are not created any more, use their couterparts in luatexbase. diff --git a/Master/texmf-dist/doc/luatex/luatexbase/README b/Master/texmf-dist/doc/luatex/luatexbase/README index f81c990bdce..44249108018 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/README +++ b/Master/texmf-dist/doc/luatex/luatexbase/README @@ -1,8 +1,9 @@ - The luatexbase generic bundle + The luatexbase generic package for LuaTeX -The bundle provides basic facilities for LuaTeX macro programmers, mostly -resource allocation and convenience packages. Provided are: +This package provides resource management for the LuaTeX macro programmer. +It is composed of the following sub-packages, which can be used independantly +if desired: – luatexbase-compat: compatibility helpers; – luatexbase-loader: Lua module loading; @@ -12,18 +13,16 @@ resource allocation and convenience packages. Provided are: – luatexbase-modutils: Lua module declaration; and - luatexbase-mcb: callbacks extensions. -Additionally, a `luatexbase' package loads all of the above in one step (and -does nothing else) for your convenience. - Installation ------------ Here are the recommended installation methods (preferred first). 1. If you are using TeX Live 2010 or later, use 'tlmgr install luatexbase'. -Alternatively, try your (TeX or Linux) distribution's package management system. +If your are using MiKTeX, use the MiKTeX Package Manager. +Alternatively, try you Linux distribution's package management system. -2. a. Grab luatextra.tds.zip on the CTAN. +2. a. Grab luatexbase.tds.zip on the CTAN. b. Unzip it at the root of one or your TDS trees. c. You may need to update some filename database after this, see your TeX distribution's manual for details. (Hint: with TeX Live, run 'mktexlsr'; diff --git a/Master/texmf-dist/doc/luatex/luatexbase/TODO b/Master/texmf-dist/doc/luatex/luatexbase/TODO index 60329a347ee..ae89fbfc3c4 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/TODO +++ b/Master/texmf-dist/doc/luatex/luatexbase/TODO @@ -1,30 +1,36 @@ -attr: \newluatexattribute -> \newattribute +Version 0.3 +=========== -all: error if not running luatex! +general +------- + +- `make check` for luaotfload & fontspec (lltxb branch) +- synchronize release + + +Later +===== + +all +--- + +- discuss merge with Heiko... + +- regression checks on the results of the tests (sed+diff the log) +- add debug messages to be used in the test suite? modutils -------- -- Renaming: - \luatexUseModule - \luatexRequireModule -- syntax of public TeX macros and Lua functions -- create private functions for infwarrerr? -- use tex.error for error reporting if available -- review logic (see what LaTeX2e does) -- General review of code and comments. -- Update user documentation. Include template(s) for Lua modules. - -mcb ---- +- make `\listfiles` show Lua modules? -- Incorporate remaining bits from luatextra? -- Enhance test file? -- General review of code and comments. -- Update user documentation. +cctb +---- +- support for unicode-letters? -afterwards ----------- +bytecode registers +------------------ -- Bump version number, upload. +- create submodule for that +- only lua interface, most probably diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-attr.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-attr.pdf index 0945f79b16d..7ae3916a8a2 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-attr.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-attr.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-cctb.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-cctb.pdf index 57712cc5ed9..e02e405c46a 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-cctb.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-cctb.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-compat.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-compat.pdf index b000cbcbf14..230ab1bacb4 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-compat.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-compat.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-loader.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-loader.pdf index 8c0df231ed3..85c997aae47 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-loader.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-loader.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-mcb.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-mcb.pdf index ed8dba1b40a..8d7983fce53 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-mcb.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-mcb.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-modutils.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-modutils.pdf index bcbdab8cb95..dd5bd91e799 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-modutils.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-modutils.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-regs.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-regs.pdf index a1f96554016..ef1eb3b40f1 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-regs.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase-regs.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase.pdf b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase.pdf index 49241e4cbec..f425c7d478c 100644 Binary files a/Master/texmf-dist/doc/luatex/luatexbase/luatexbase.pdf and b/Master/texmf-dist/doc/luatex/luatexbase/luatexbase.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-latex.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-latex.tex index dbff69b2727..30a40e32f90 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-latex.tex +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-latex.tex @@ -11,6 +11,7 @@ %% This work is under the CC0 license. %% See source file 'luatexbase-cctb.dtx' for details. %% +\catcode00 15 \RequirePackage{luatexbase-cctb} \begingroup \catcode64 11 \global\let\lua\luatexbase@directlua \endgroup @@ -21,10 +22,25 @@ \newluatexcatcodetable\anothercctb \endgroup \lua{assert(luatexbase.catcodetables.anothercctb)} -\luatexcatcodetable\CatcodeTableLaTeXAtLetter -\ifnum\catcode64=11 \else \ERROR \fi -\luatexcatcodetable\CatcodeTableLaTeX -\ifnum\catcode64=12 \else \ERROR \fi +\def\test#1#2#3{% + \begingroup + \ifcsname CatcodeTable#1\endcsname \else \INTERR \fi + \luatexcatcodetable\csname CatcodeTable#1\endcsname + \ifnum\catcode#2=#3 \else \ERROR \fi + \endgroup} +\test {IniTeX} {00} {09} +\test {IniTeX} {92} {00} +\test {IniTeX} {64} {12} +\test {IniTeX} {65} {11} +\test {String} {92} {12} +\test {String} {65} {12} +\test {String} {32} {10} +\test {Other} {92} {12} +\test {Other} {65} {12} +\test {Other} {32} {12} +\test {LaTeXAtLetter} {64} {11} +\test {LaTeX} {64} {12} +\test {Expl} {32} {09} \documentclass{minimal} \lua{% tex.sprint('\string\\setbox0=\string\\hbox{') diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-plain.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-plain.tex index 5d55e1f5e41..fbd96601dfe 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-plain.tex +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-cctb-plain.tex @@ -11,6 +11,7 @@ %% This work is under the CC0 license. %% See source file 'luatexbase-cctb.dtx' for details. %% +\catcode00 15 \input luatexbase-cctb.sty \begingroup \catcode64 11 \global\let\lua\luatexbase@directlua \endgroup @@ -21,10 +22,25 @@ \newluatexcatcodetable\anothercctb \endgroup \lua{assert(luatexbase.catcodetables.anothercctb)} -\luatexcatcodetable\CatcodeTableLaTeXAtLetter -\ifnum\catcode64=11 \else \ERROR \fi -\luatexcatcodetable\CatcodeTableLaTeX -\ifnum\catcode64=12 \else \ERROR \fi +\def\test#1#2#3{% + \begingroup + \ifcsname CatcodeTable#1\endcsname \else \INTERR \fi + \luatexcatcodetable\csname CatcodeTable#1\endcsname + \ifnum\catcode#2=#3 \else \ERROR \fi + \endgroup} +\test {IniTeX} {00} {09} +\test {IniTeX} {92} {00} +\test {IniTeX} {64} {12} +\test {IniTeX} {65} {11} +\test {String} {92} {12} +\test {String} {65} {12} +\test {String} {32} {10} +\test {Other} {92} {12} +\test {Other} {65} {12} +\test {Other} {32} {12} +\test {LaTeXAtLetter} {64} {11} +\test {LaTeX} {64} {12} +\test {Expl} {32} {09} \lua{% tex.sprint('\string\\setbox0=\string\\hbox{') tex.sprint(luatexbase.catcodetables.string, "\string\\undef # _^&") diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-aux.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-aux.tex new file mode 100644 index 00000000000..f5d5fef42e2 --- /dev/null +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-aux.tex @@ -0,0 +1 @@ +\relax diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-latex.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-latex.tex index be36abc6d4a..8a242cbb08b 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-latex.tex +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-latex.tex @@ -13,28 +13,38 @@ %% \RequirePackage{luatexbase-mcb} \catcode 64 11 -\luatexbase@directlua{ - local function one(head,...) - texio.write_nl("I'm number 1") - return head, true - end - - local function two(head,...) - texio.write_nl("I'm number 2") - return head, true - end - - local function three(head,...) - texio.write_nl("I'm number 3") - return head, true - end - - luatexbase.add_to_callback("hpack_filter",one,"my sample function one",1) - luatexbase.add_to_callback("hpack_filter",two,"my sample function two",2) - luatexbase.add_to_callback("hpack_filter",three,"my sample function three",1) - - luatexbase.remove_from_callback("hpack_filter","my sample function three") +\def\msg{\immediate\write16} +\msg{===== BEGIN =====} +\luatexbase@directlua{dofile('test-mcb.lua')} +\def\test#1#2{% + \msg{^^J*********^^J* Testing #1 (type #2)^^J*********} + \msg{* Add two functions} + \luatexbase@directlua{add_#1()} + \csname test_#1\endcsname + \msg{* Remove one} + \luatexbase@directlua{rm_one_#1()} + \csname test_#1\endcsname + \msg{* Remove the second} + \luatexbase@directlua{rm_two_#1()} + \csname test_#1\endcsname + \msg{* Add two functions again} + \luatexbase@directlua{add_#1()} + \csname test_#1\endcsname + \msg{* Remove all functions} + \luatexbase@directlua{luatexbase.reset_callback("#1")} + \csname test_#1\endcsname } +\catcode`\_ 11 +\everypar{} +\def\test_hpack_filter{\setbox0=\hbox{bla}} +\def\test_hyphenate{\showhyphens{hyphenation}} +\def\test_find_write_file{\immediate\openout15 test-mcb-out.log} +\def\test_process_input_buffer{\input test-mcb-aux.tex} +\test{hpack_filter}{list} +\test{hyphenate}{simple} +\test{find_write_file}{first} +\test{process_input_buffer}{data} +\msg{===== END =====} \stop \endinput %% diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-plain.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-plain.tex index c3f556da86a..d98dd536ec7 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-plain.tex +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb-plain.tex @@ -13,28 +13,37 @@ %% \input luatexbase-mcb.sty \catcode 64 11 -\luatexbase@directlua{ - local function one(head,...) - texio.write_nl("I'm number 1") - return head, true - end - - local function two(head,...) - texio.write_nl("I'm number 2") - return head, true - end - - local function three(head,...) - texio.write_nl("I'm number 3") - return head, true - end - - luatexbase.add_to_callback("hpack_filter",one,"my sample function one",1) - luatexbase.add_to_callback("hpack_filter",two,"my sample function two",2) - luatexbase.add_to_callback("hpack_filter",three,"my sample function three",1) - - luatexbase.remove_from_callback("hpack_filter","my sample function three") +\def\msg{\immediate\write16} +\msg{===== BEGIN =====} +\luatexbase@directlua{dofile('test-mcb.lua')} +\def\test#1#2{% + \msg{^^J*********^^J* Testing #1 (type #2)^^J*********} + \msg{* Add two functions} + \luatexbase@directlua{add_#1()} + \csname test_#1\endcsname + \msg{* Remove one} + \luatexbase@directlua{rm_one_#1()} + \csname test_#1\endcsname + \msg{* Remove the second} + \luatexbase@directlua{rm_two_#1()} + \csname test_#1\endcsname + \msg{* Add two functions again} + \luatexbase@directlua{add_#1()} + \csname test_#1\endcsname + \msg{* Remove all functions} + \luatexbase@directlua{luatexbase.reset_callback("#1")} + \csname test_#1\endcsname } +\catcode`\_ 11 +\def\test_hpack_filter{\setbox0=\hbox{bla}} +\def\test_hyphenate{\showhyphens{hyphenation}} +\def\test_find_write_file{\immediate\openout15 test-mcb-out.log} +\def\test_process_input_buffer{\input test-mcb-aux.tex} +\test{hpack_filter}{list} +\test{hyphenate}{simple} +\test{find_write_file}{first} +\test{process_input_buffer}{data} +\msg{===== END =====} \bye \endinput %% diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-mcb.lua b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb.lua new file mode 100644 index 00000000000..c760299d844 --- /dev/null +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-mcb.lua @@ -0,0 +1,132 @@ +-- +-- This is file `test-mcb.lua', +-- generated with the docstrip utility. +-- +-- The original source files were: +-- +-- luatexbase-mcb.dtx (with options: `testlua') +-- +-- Copyright (C) 2009 by Elie Roux +-- +-- This work is under the CC0 license. +-- See source file 'luatexbase-mcb.dtx' for details. +-- +local msg = texio.write_nl +local function sample(head,...) + return head, true +end +local prio = luatexbase.priority_in_callback +msg("\n*********\n* Testing management functions\n*********") +luatexbase.add_to_callback("hpack_filter", sample, "sample one", 1) +luatexbase.add_to_callback("hpack_filter", sample, "sample two", 2) +luatexbase.add_to_callback("hpack_filter", sample, "sample three", 1) +assert(prio("hpack_filter", "sample three")) +luatexbase.remove_from_callback("hpack_filter", "sample three") +assert(not prio("hpack_filter", "sample three")) +luatexbase.reset_callback("hpack_filter") +assert(not prio("hpack_filter", "sample one")) +local function data_one(s) + texio.write_nl("I'm data 1 whith argument: "..s) + return s +end +local function data_two(s) + texio.write_nl("I'm data 2 whith argument: "..s) + return s +end +local function data_three(s) + texio.write_nl("I'm data 3 whith argument: "..s) + return s +end +msg("\n*********\n* Testing user-defined callbacks\n*********") +msg("* create one") +luatexbase.create_callback("fooback", "data", data_one) +msg("* call it") +luatexbase.call_callback("fooback", "default") +msg("* add two functions") +luatexbase.add_to_callback("fooback", data_two, "function two", 2) +luatexbase.add_to_callback("fooback", data_three, "function three", 1) +msg("* call") +luatexbase.call_callback("fooback", "all") +msg("* rm one function") +luatexbase.remove_from_callback("fooback", "function three") +msg("* call") +luatexbase.call_callback("fooback", "all but three") +msg("* reset") +luatexbase.reset_callback("fooback") +msg("* call") +luatexbase.call_callback("fooback", "default") +function add_hpack_filter() + luatexbase.add_to_callback('hpack_filter', function(head, ...) + texio.write_nl("I'm a dummy hpack_filter") + return head + end, + 'dummy hpack filter') + luatexbase.add_to_callback('hpack_filter', function(head, ...) + texio.write_nl("I'm an optimized dummy hpack_filter") + return true + end, + 'optimized dummy hpack filter') +end +function rm_one_hpack_filter() + luatexbase.remove_from_callback('hpack_filter', 'dummy hpack filter') +end +function rm_two_hpack_filter() + luatexbase.remove_from_callback('hpack_filter', + 'optimized dummy hpack filter') +end +function add_hyphenate() + luatexbase.add_to_callback('hyphenate', function(head, tail) + texio.write_nl("I'm a dummy hyphenate") + end, + 'dummy hyphenate') + luatexbase.add_to_callback('hyphenate', function(head, tail) + texio.write_nl("I'm an other dummy hyphenate") + end, + 'other dummy hyphenate') +end +function rm_one_hyphenate() + luatexbase.remove_from_callback('hyphenate', 'dummy hyphenate') +end +function rm_two_hyphenate() + luatexbase.remove_from_callback('hyphenate', 'other dummy hyphenate') +end +function add_find_write_file() + luatexbase.add_to_callback('find_write_file', function(id, name) + texio.write_nl("I'm a dummy find_write_file") + return "dummy-"..name + end, + 'dummy find_write_file') + luatexbase.add_to_callback('find_write_file', function(id, name) + texio.write_nl("I'm an other dummy find_write_file") + return "dummy-other-"..name + end, + 'other dummy find_write_file') +end +function rm_one_find_write_file() + luatexbase.remove_from_callback('find_write_file', + 'dummy find_write_file') +end +function rm_two_find_write_file() + luatexbase.remove_from_callback('find_write_file', + 'other dummy find_write_file') +end +function add_process_input_buffer() + luatexbase.add_to_callback('process_input_buffer', function(buffer) + return buffer.."\\msg{dummy}" + end, + 'dummy process_input_buffer') + luatexbase.add_to_callback('process_input_buffer', function(buffer) + return buffer.."\\msg{otherdummy}" + end, + 'other dummy process_input_buffer') +end +function rm_one_process_input_buffer() + luatexbase.remove_from_callback('process_input_buffer', + 'dummy process_input_buffer') +end +function rm_two_process_input_buffer() + luatexbase.remove_from_callback('process_input_buffer', + 'other dummy process_input_buffer') +end +-- +-- End of File `test-mcb.lua'. diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-latex.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-latex.tex index ece22be054b..4e583d54ac4 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-latex.tex +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-latex.tex @@ -12,10 +12,8 @@ %% See source file 'luatexbase-modutils.dtx' for details. %% \RequirePackage{luatexbase-modutils} -\luatexUseModule{test-modutils} -\luatexRequireModule -[1970/01/01] -{test-modutils} +\RequireLuaModule{test-modutils} +\RequireLuaModule{test-modutils}[1970/01/01] \stop \endinput %% diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-plain.tex b/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-plain.tex index f00ecc41b8d..9e256822c7f 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-plain.tex +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-modutils-plain.tex @@ -12,10 +12,8 @@ %% See source file 'luatexbase-modutils.dtx' for details. %% \input luatexbase-modutils.sty -\luatexUseModule{test-modutils} -\luatexRequireModule -{test-modutils} -{1970/01/01} +\RequireLuaModule{test-modutils} +\RequireLuaModule{test-modutils}[1970/01/01] \bye \endinput %% diff --git a/Master/texmf-dist/doc/luatex/luatexbase/test-modutils.lua b/Master/texmf-dist/doc/luatex/luatexbase/test-modutils.lua index 98a21e81d9c..14218185f60 100644 --- a/Master/texmf-dist/doc/luatex/luatexbase/test-modutils.lua +++ b/Master/texmf-dist/doc/luatex/luatexbase/test-modutils.lua @@ -11,11 +11,13 @@ -- This work is under the CC0 license. -- See source file 'luatexbase-modutils.dtx' for details. -- -luatexbase.provides_module { +local err, warn, info, log = luatexbase.provides_module { name = 'test-modutils', date = '2000/01/01', version = 1, description = 'dummy test package', } +info('It works!\nOh, rly?\nYeah rly!') +log("I'm a one-line info.") -- -- End of File `test-modutils.lua'. diff --git a/Master/texmf-dist/source/luatex/luatexbase/Makefile b/Master/texmf-dist/source/luatex/luatexbase/Makefile index 0b854b07500..03784a546cd 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/Makefile +++ b/Master/texmf-dist/source/luatex/luatexbase/Makefile @@ -7,20 +7,21 @@ DTXSTY = lltxb-dtxstyle.tex # Files grouped by generation mode UNPACKED_MCB = luatexbase-mcb.sty mcb.lua \ - test-mcb-latex.tex test-mcb-plain.tex + test-mcb-latex.tex test-mcb-plain.tex \ + test-mcb.lua $(TEST_MCB) UNPACKED_REGS = luatexbase-regs.sty \ - test-regs-plain.tex test-regs-latex.tex + test-regs-plain.tex test-regs-latex.tex UNPACKED_ATTR = luatexbase-attr.sty attr.lua \ - test-attr-plain.tex test-attr-latex.tex + test-attr-plain.tex test-attr-latex.tex UNPACKED_CCTB = luatexbase-cctb.sty cctb.lua \ - test-cctb-plain.tex test-cctb-latex.tex + test-cctb-plain.tex test-cctb-latex.tex UNPACKED_LOADER = luatexbase-loader.sty luatexbase.loader.lua \ - test-loader-plain.tex test-loader-latex.tex \ - $(TEST_LOADER).lua test-loader.sub.lua + test-loader-plain.tex test-loader-latex.tex \ + $(TEST_LOADER).lua test-loader.sub.lua UNPACKED_MODUTILS = luatexbase-modutils.sty modutils.lua test-modutils.lua \ - test-modutils-plain.tex test-modutils-latex.tex + test-modutils-plain.tex test-modutils-latex.tex UNPACKED_COMPAT = luatexbase-compat.sty \ - test-compat-plain.tex test-compat-latex.tex + test-compat-plain.tex test-compat-latex.tex UNPACKED_BASE = luatexbase.sty test-base-plain.tex test-base-latex.tex UNPACKED = $(UNPACKED_MCB) $(UNPACKED_REGS) $(UNPACKED_ATTR) $(UNPACKED_CCTB) \ $(UNPACKED_LOADER) $(UNPACKED_MODUTILS) $(UNPACKED_COMPAT) \ @@ -32,6 +33,7 @@ SOURCE = $(DTX) $(DTXSTY) README TODO Changes Makefile # used for check TEST_LOADER = test-loader TMP_LOADER = $(TEST_LOADER).tex +TEST_MCB = test-mcb-aux.tex # Files grouped by installation location RUNFILES = $(filter-out test-%, $(UNPACKED)) @@ -60,7 +62,7 @@ TDS_ZIP = $(NAME).tds.zip ZIPS = $(CTAN_ZIP) $(TDS_ZIP) DO_TEX = tex --interaction=batchmode $< >/dev/null -DO_LATEXMK = latexmk -silent $< >/dev/null +DO_LATEXMK = latexmk -pdf -silent $< >/dev/null # Main targets definition all: $(GENERATED) @@ -80,6 +82,7 @@ luatexbase.%.lua: %.lua $(UNPACKED_MCB): luatexbase-mcb.dtx $(DO_TEX) + echo \\\\relax > $(TEST_MCB) $(UNPACKED_REGS): luatexbase-regs.dtx $(DO_TEX) @@ -123,7 +126,7 @@ check-modutils: install-runfiles $(TESTENV) luatex --interaction=batchmode test-modutils-plain.tex >/dev/null $(TESTENV) lualatex --interaction=batchmode test-modutils-latex.tex >/dev/null -check-mcb: install-runfiles +check-mcb: install-runfiles $(UNPACKED_MCB) $(TESTENV) luatex --interaction=batchmode test-mcb-plain.tex >/dev/null $(TESTENV) lualatex --interaction=batchmode test-mcb-latex.tex >/dev/null @@ -170,7 +173,7 @@ manifest: clean: @latexmk -silent -c *.dtx >/dev/null - @# for tex-only runs + @#for non-latexmk runs @$(RM) -- *.log mrproper: clean diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-attr.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-attr.dtx index 5847daec422..d377f7c619f 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-attr.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-attr.dtx @@ -113,11 +113,7 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \pk{luatexbase-attr} package} -% \date{v0.2a 2010-05-27} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \email{mpg@elzevir.fr} \and -% \'Elie Roux \\ \email{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase-attr}{v0.3 2010-05-27} % % \maketitle % @@ -238,7 +234,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-attr}[2010/05/27 v0.2a Attributes allocation for LuaTeX] +\x{luatexbase-attr}[2010/10/10 v0.3 Attributes allocation for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -252,14 +248,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@attr@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-cctb.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-cctb.dtx index 4b7b8c64231..c60cdc0c709 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-cctb.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-cctb.dtx @@ -113,11 +113,7 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \pk{luatexbase-cctb} package} -% \date{v0.2a 2010-05-27} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \texttt{mpg@elzevir.fr} \and -% \'Elie Roux \\ \texttt{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase-cctb}{v0.3 2010-05-27} % % \maketitle % @@ -246,7 +242,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-cctb}[2010/05/27 v0.2a Catcodetable allocation for LuaTeX] +\x{luatexbase-cctb}[2010/10/10 v0.3 Catcodetable allocation for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -260,14 +256,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-cctb}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@cctb@AtEnd \expandafter\endinput \fi @@ -505,6 +504,7 @@ end % Plain TeX. % % \begin{macrocode} +%\catcode00 15 %\input luatexbase-cctb.sty %\RequirePackage{luatexbase-cctb} %<*testplain,testlatex> @@ -524,13 +524,29 @@ end \lua{assert(luatexbase.catcodetables.anothercctb)} % \end{macrocode} % -% Now, play a little bit with predefined tables. +% Now, play a little bit with predefined tables. Be careful to change +% catcodes only inside a group to avoid chaos. % % \begin{macrocode} -\luatexcatcodetable\CatcodeTableLaTeXAtLetter -\ifnum\catcode64=11 \else \ERROR \fi -\luatexcatcodetable\CatcodeTableLaTeX -\ifnum\catcode64=12 \else \ERROR \fi +\def\test#1#2#3{% + \begingroup + \ifcsname CatcodeTable#1\endcsname \else \INTERR \fi + \luatexcatcodetable\csname CatcodeTable#1\endcsname + \ifnum\catcode#2=#3 \else \ERROR \fi + \endgroup} +\test {IniTeX} {00} {09} +\test {IniTeX} {92} {00} +\test {IniTeX} {64} {12} +\test {IniTeX} {65} {11} +\test {String} {92} {12} +\test {String} {65} {12} +\test {String} {32} {10} +\test {Other} {92} {12} +\test {Other} {65} {12} +\test {Other} {32} {12} +\test {LaTeXAtLetter} {64} {11} +\test {LaTeX} {64} {12} +\test {Expl} {32} {09} %\documentclass{minimal} \lua{% tex.sprint('\string\\setbox0=\string\\hbox{') diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-compat.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-compat.dtx index f4a903b74be..e7d29b2b107 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-compat.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-compat.dtx @@ -102,11 +102,7 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \pk{luatexbase-compat} package} -% \date{v0.2a 2010/05/27} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \email{mpg@elzevir.fr} \and -% \'Elie Roux \\ \email{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase-compat}{2010/10/10 v0.3} % % \maketitle % @@ -258,7 +254,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-compat}[2010/05/27 v0.2a Compatibility tools for LuaTeX] +\x{luatexbase-compat}[2010/10/10 v0.3 Compatibility tools for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -272,14 +268,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-compat}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@compat@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-loader.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-loader.dtx index bd900c26969..9d57ac57c86 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-loader.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-loader.dtx @@ -116,11 +116,7 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \pk{luatexbase-loader} package} -% \date{v0.2a 2010-05-27} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \texttt{mpg@elzevir.fr} \and -% \'Elie Roux \\ \texttt{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase-loader}{v0.3 2010-05-27} % % \maketitle % @@ -230,7 +226,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-loader}[2010/05/27 v0.2a Lua module loader for LuaTeX] +\x{luatexbase-loader}[2010/10/10 v0.3 Lua module loader for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -244,14 +240,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-loader}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@loader@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-mcb.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-mcb.dtx index 09c8c1c53dd..b944cd261e4 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-mcb.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-mcb.dtx @@ -69,6 +69,11 @@ See source file '\inFileName' for details. \file{mcb.lua}{\from{luatexbase-mcb.dtx}{lua}}% } +\generate{% + \usedir{doc/luatex/luatexbase}% + \file{test-mcb.lua}{\from{luatexbase-mcb.dtx}{testlua}}% +} + \obeyspaces \Msg{************************************************************************} \Msg{*} @@ -113,73 +118,163 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \textsf{luatexbase-mcb} package} -% \date{2010/05/27 v0.2a} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \email{mpg@elzevir.fr} \and -% \'Elie Roux \\ \email{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase-mcb}{2010/10/10 v0.3} % % \maketitle % % \begin{abstract} -% This package manages the callback adding and removing, by providing new -% functions and overwriting \texttt{callback.register}. It also allows to -% create and call new callbacks.\par -% The user part of this documentation is currently very incomplete, and will -% be expanded later. Sorry for this and thanks for your patience.\par -% \textbf{Warning.} Currently assumes that \textsf{luatexbase-modutils} -% has been previously loaded. (This is a temporary limitation.) +% The primary feature of this package is to allow many functions to be +% registered in the same callback. Depending of the type of the callback, the +% functions will be combined in some way when the callback is called. Functions +% are provided for addition and removal of individual functions from a +% callback's list, with a priority system.\par +% Additionally, you can create new callbacks that will be handled the same way +% as predefined callbacks, except that they must be called explicitly. % \end{abstract} % % \tableofcontents % % \section{Documentation} % -% Lua\TeX\ provides an extremely interesting feature, named callbacks. It -% allows to call some lua functions at some points of the \TeX\ algorithm (a +% Before we start, let me mention that test files are provided (they should be +% in the same directory as this PDF file). You can have a look at them, +% compile them and have a look at the log, if you want examples of how this +% module works. +% +% \subsection{Managing functions in callbacks} +% +% \luatex provides an extremely interesting feature, named callbacks. It +% allows to call some Lua functions at some points of the \TeX\ algorithm (a % \emph{callback}), like when \TeX\ breaks likes, puts vertical spaces, etc. -% The Lua\TeX\ core offers a function called \texttt{callback.register} that +% The \luatex core offers a function called \texttt{callback.register} that % enables to register a function in a callback. % -% The problem with \texttt{callback.register} is that is registers only one -% function in a callback. For a lot of callbacks it can be common to have -% several packages registering their function in a callback, and thus it is -% impossible with them to be compatible with each other. -% -% This package solves this problem by adding mainly one new function -% \verb+luatexbase.add_to_callback+ that adds a function in a callback. With -% this function it is possible for packages to register their function in a -% callback without overwriting the functions of the other packages. There are -% also functions to remove one or all functions from a callback. -% See comments in the implementation section for details. -% -% The functions are called in a certain order, and when a package registers a -% callback it can assign a priority to its function. Conflicts can still -% remain even with the priority mechanism, for example in the case where two -% packages want to have the highest priority. In these cases the packages have -% to solve the conflicts themselves. -% See comments in the implementation section for details. -% -% This package also privides a way to create and call new callbacks, in -% addition to the default Lua\TeX\ callbacks. -% See comments in the implementation section for details. -% -% \subsubsection*{Limitations} -% -% This package only works for callbacks where it's safe to add multiple -% functions without changing the functions' signatures. There are callbacks, -% though, where registering several functions is not possible without changing -% the function's signatures, like for example the readers callbacks. These -% callbacks take a filename and give the datas in it. One solution would be to -% change the functions' signature to open it when the function is the first, -% and to take the datas and modify them eventually if they are called after -% the first. But it seems rather fragile and useless, so it's not implemented. -% With these callbacks, in this package we simply execute the first function -% in the list. -% -% Other callbacks in this case are \texttt{define\_font} and -% \texttt{open\_read\_file}. There is though a solution for several packages -% to use these callbacks, see the implementation of \texttt{luatextra}. +% The problem with |callback.register| is that is registers only one function +% in a callback. This package solves the problem by disabling +% |callback.register| and providing a new interface allowing many functions to +% be registered in a single callback. +% +% The way the functions are combined together depends on +% the type of the callback. There are currently 4 types of callback, depending +% on the calling convention of the functions the callback can hold: +% \begin{description} +% \item[simple] is for functions that don't return anything: they are called +% in order, all with the same argument; +% \item[data] is for functions receiving a piece of data of nay type +% except node list head (and possibly other arguments) and returning it +% (possibly modified): the functions are called in order, and each is +% passed the return value of the previous (and the other arguments +% untouched, if any). The return value is that of the last function; +% \item[list] is a specialized variant of \emph{data} for functions +% filtering node lists. Such functions may return either the head of a +% modified node list, or the boolean values |true| or |false|. The +% functions are chained the same way as for \emph{data} except that for +% the following. If +% one function returns |false|, then |false| is immediately return and the +% following functions are \emph{not} called. If one function returns +% |true|, then the same head is passed to the next function. If all +% functions return |true|, then |true| is returned, otherwise the return +% value of the last function not returning |true| is used. +% \item[first] is for functions with more complex signatures; functions in +% this type of callback are \emph{not} combined: only the first one +% (according to priorities) is executed. +% \end{description} +% +% To add a function to a callback, use: +% \begin{verbatim} +% luatexbase.add_to_callback(name, func, description, priority) +% \end{verbatim} +% The first argument is the name of the callback, the second is a function, +% the third one is a string used to identify the function later, and the +% optional priority is a positive integer, representing the rank of the +% function in the list of functions to be executing for this callback. So, +% |1| is the highest priority. If no priority is specified, the function is +% appended to the list, that is, its priority is the one of the last function +% plus one. +% +% The priority system is intended to help resolving conflicts between packages +% competing on the same callback, but it cannot solve every possible issue. If +% two packages request priority |1| on the same callback, then the last one +% loaded will win. +% +% To remove a function from a callback, use: +% \begin{verbatim} +% luatexbase.remove_from_callback(name, description) +% \end{verbatim} +% The first argument must be the name of the callback, and the second one the +% description used when adding the function to this callback. You can also +% remove all functions from a callback at once using +% \begin{verbatim} +% luatexbase.reset_callback(name, make_false) +% \end{verbatim} +% The |make_false| argument is optional. If it is |true| (repeat: |true|, not +% |false|) then the value |false| is registered in the callback, which has a +% special meaning for some callback. +% +% Note that |reset_callback| is very invasive since it removes all functions +% possibly installed by other packages in this callback. So, use it with care +% if there is any chance that another package wants to share this callback +% with you. +% +% When new functions are added at the beginning of the list, other functions +% are shifted down the list. To get the current rank of a function in a +% callback's list, use: +% \begin{verbatim} +% priority = luatexbase.priority_in_callback(name, description) +% \end{verbatim} +% Again, the description is the string used when adding the function. If the +% function identified by this string is not in this callback's list, the +% priority returned is the boolean value |false|. +% +% \subsection{Creating new callbacks} +% +% This package also provides a way to create and call new callbacks, in +% addition to the default \luatex callbacks. +% \begin{verbatim} +% luatexbase.create_callback(name, type, default) +% \end{verbatim} +% The first argument is the callback's name, it must be unique. Then, the type +% goes as explained above, it is given as a string. Finally all user-defined +% callbacks have a default function which must\footnote{You can obviously +% provide a dummy function. If you're doing so often, please tell me, I may +% want to make this argument optional.} be provided as the third +% argument. It will be used when no other function is registered for this +% callback. +% +% Functions are added to and removed from user-defined callbacks just the same +% way as predefined callback, so the previous section still applies. There is +% one difference, however: user-defined callbacks must be called explicitly at +% some point in your code, while predefined callbacks are called automatically +% by \luatex. To do so, use: +% \begin{verbatim} +% luatexbase.call_callback(name, arguments...) +% \end{verbatim} +% The functions registered for this callback (or the default function) will be +% called with |arguments...| as arguments. +% +% \subsubsection{Limitations} +% +% For callbacks of type |first|, our new management system isn't actually +% better than good old |callback.register|. For some of them, is may be +% possible to split them into many callbacks, so that these callbacks can +% accept multiple functions. However, its seems risky and limited in use and +% is therefore nor implemented. +% +% At some point, \pk{luatextra} used to split |open_read_file| that way, but +% support for this was removed. It may be added back (as well as support for +% other split callbacks) if it appears there is an actual need for it. +% +% \subsection{Compatibility} +% +% Some callbacks have a calling convention that varies depending on the +% version of \luatex used. This package \emph{does not} try to track the type +% of the callbacks in every possible version of \luatex. The types are based +% on the last stable beta version (0.60.2 at the time this doc is written). +% +% However, for callbacks that have the same calling convention for every +% version of \luatex, this package should work with the same range of \luatex +% version as other packages in the \pk{luatexbase} bundle (currently, 0.25.4 +% to 0.60.2). % % \section{Implementation} % @@ -245,7 +340,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-mcb}[2010/05/27 v0.2a Callback management for LuaTeX] +\x{luatexbase-mcb}[2010/10/10 v0.3 Callback management for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -259,14 +354,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-mcb}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@mcb@AtEnd \expandafter\endinput \fi @@ -304,309 +402,280 @@ See source file '\inFileName' for details. % % \begin{macrocode} module('luatexbase', package.seeall) -luatexbase.provides_module({ - name = "luamcallbacks", +local err, warning, info = luatexbase.provides_module({ + name = "luatexbase-mcb", version = 0.2, date = "2010/05/12", description = "register several functions in a callback", - author = "Hans Hagen, Elie Roux and Manuel Pégourie-Gonnard", - copyright = "Hans Hagen, Elie Roux and Manuel Pégourie-Gonnard", + author = "Hans Hagen, Elie Roux and Manuel Pegourie-Gonnard", + copyright = "Hans Hagen, Elie Roux and Manuel Pegourie-Gonnard", license = "CC0", }) % \end{macrocode} % -% Shortcuts for error functions. +% \subsubsection{Housekeeping} +% +% The main table: keys are callback names, and values are the associated +% lists of functions. More precisely, the entries in the list are tables +% holding the actual function as |func| and the identifying description as +% |description|. Only callbacks with a non-empty list of functions have an +% entry in this list. % % \begin{macrocode} -local log = log or function(...) - luatexbase.module_log('luamcallbacks', string.format(...)) -end -local info = info or function(...) - luatexbase.module_info('luamcallbacks', string.format(...)) -end -local warning = warning or function(...) - luatexbase.module_warning('luamcallbacks', string.format(...)) -end -local err = err or function(...) - luatexbase.module_error('luamcallbacks', string.format(...)) -end +local callbacklist = callbacklist or { } % \end{macrocode} % -% \subsubsection{Initialisations} +% Numerical codes for callback types, and name to value association (the +% table keys are strings, the values are numbers). % -% \texttt{callbacklist} is the main list, that contains the callbacks as -% keys and a table of the registered functions a values. +% \begin{macrocode} +local list, data, first, simple = 1, 2, 3, 4 +local types = { + list = list, + data = data, + first = first, + simple = simple, +} +% \end{macrocode} +% +% Now, list all predefined callbacks with their current type, based on the +% LuaTeX manual version 0.60.2. % % \begin{macrocode} -local callbacklist = callbacklist or { } +local callbacktypes = callbacktypes or { % \end{macrocode} % -% A table with the default functions of the created callbacks. See -% \texttt{create} for further informations. +% Section 4.1.1: file discovery callbacks. % % \begin{macrocode} -local lua_callbacks_defaults = { } + find_read_file = first, + find_write_file = first, + find_font_file = data, + find_output_file = data, + find_format_file = data, + find_vf_file = data, + find_ocp_file = data, + find_map_file = data, + find_enc_file = data, + find_sfd_file = data, + find_pk_file = data, + find_data_file = data, + find_opentype_file = data, + find_truetype_file = data, + find_type1_file = data, + find_image_file = data, % \end{macrocode} % -% There are 4 types of callback: -% \begin{itemize} -% \item the ones taking a list of nodes and returning a boolean and -% eventually a new head (\texttt{list}) -% \item the ones taking datas and returning the modified ones -% (\texttt{data}) -% \item the ones that can't have multiple functions registered in them -% (\texttt{first}) -% \item the ones for functions that don't return anything (\texttt{simple}) -% \end{itemize} +% Section 4.1.2: file reading callbacks. % % \begin{macrocode} -local list = 1 -local data = 2 -local first = 3 -local simple = 4 + open_read_file = first, + read_font_file = first, + read_vf_file = first, + read_ocp_file = first, + read_map_file = first, + read_enc_file = first, + read_sfd_file = first, + read_pk_file = first, + read_data_file = first, + read_truetype_file = first, + read_type1_file = first, + read_opentype_file = first, % \end{macrocode} % -% \texttt{callbacktypes} is the list that contains the callbacks as keys -% and the type (list or data) as values. +% Section 4.1.3: data processing callbacks. % % \begin{macrocode} -local callbacktypes = callbacktypes or { - buildpage_filter = simple, - token_filter = first, - pre_output_filter = list, - hpack_filter = list, - process_input_buffer = data, - mlist_to_hlist = list, - vpack_filter = list, - define_font = first, - open_read_file = first, - linebreak_filter = list, - post_linebreak_filter = list, - pre_linebreak_filter = list, - start_page_number = simple, - stop_page_number = simple, - start_run = simple, - show_error_hook = simple, - stop_run = simple, - hyphenate = simple, - ligaturing = simple, - kerning = data, - find_write_file = first, - find_read_file = first, - find_vf_file = data, - find_map_file = data, - find_format_file = data, - find_opentype_file = data, - find_output_file = data, - find_truetype_file = data, - find_type1_file = data, - find_data_file = data, - find_pk_file = data, - find_font_file = data, - find_image_file = data, - find_ocp_file = data, - find_sfd_file = data, - find_enc_file = data, - read_sfd_file = first, - read_map_file = first, - read_pk_file = first, - read_enc_file = first, - read_vf_file = first, - read_ocp_file = first, - read_opentype_file = first, - read_truetype_file = first, - read_font_file = first, - read_type1_file = first, - read_data_file = first, -} + process_input_buffer = data, + process_output_buffer = data, + token_filter = first, % \end{macrocode} % -% In Lua\TeX\ version 0.43, a new callback called |process_output_buffer| -% appeared, so we enable it. Test the version using the compat package for, -% well, compatibility. +% Section 4.1.4: node list processiong callbacks. % % \begin{macrocode} -if luatexbase.luatexversion > 42 then - callbacktypes["process_output_buffer"] = data -end + buildpage_filter = simple, + pre_linebreak_filter = list, + linebreak_filter = list, + post_linebreak_filter = list, + hpack_filter = list, + vpack_filter = list, + pre_output_filter = list, + hyphenate = simple, + ligaturing = simple, + kerning = simple, + mlist_to_hlist = list, % \end{macrocode} % -% As we overwrite \texttt{callback.register}, we save it as -% \texttt{internalregister}. +% Section 4.1.5: information reporting callbacks. % % \begin{macrocode} -local internalregister = internalregister or callback.register + start_run = simple, + stop_run = simple, + start_page_number = simple, + stop_page_number = simple, + show_error_hook = simple, % \end{macrocode} % -% \subsubsection{Unsorted stuff} +% Section 4.1.6: font-related callbacks. % -% A simple function we'll use later to understand the arguments of the -% \texttt{create} function. It takes a string and returns the type -% corresponding to the string or nil. +% \begin{macrocode} + define_font = first, +} +% \end{macrocode} +% +% All user-defined callbacks have a default function. The following table's +% keys are the names of the user-defined callback, the associated value is +% the default functon for this callback. This table is also used to +% identify the user-defined callbacks. % % \begin{macrocode} -local function str_to_type(str) - if str == 'list' then - return list - elseif str == 'data' then - return data - elseif str == 'first' then - return first - elseif str == 'simple' then - return simple - else - return nil - end +local lua_callbacks_defaults = { } +% \end{macrocode} +% +% Overwrite |callback.register|, but save it first. Also define a wrapper +% that automatically raise an error when something goes wrong. +% +% \begin{macrocode} +local original_register = original_register or callback.register +callback.register = function () + err("function callback.register has been trapped,\n" + .."please use luatexbase.add_to_callback instead.") +end +local function register_callback(...) + return assert(original_register(...)) end % \end{macrocode} % -% This function and the following ones are only internal. This one is the -% handler for the first type of callbacks: the ones that take a list head -% and return true, false, or a new list head. +% \subsubsection{Handlers} +% +% Normal (as opposed to user-defined) callbacks have handlers depending on +% their type. The handler function is registered into the callback when the +% first function is added to this callback's list. Then, when the callback +% is called, then handler takes care of running all functions in the list. +% When the last function is removed from the callback's list, the handler +% is unregistered. +% +% More precisely, the functions below are used to generate a specialized +% function (closure) for a given callback, which is the actual handler. +% +% Handler for |list| callbacks. % % \begin{macrocode} --- local -function listhandler (name) +local function listhandler (name) return function(head,...) - local l = callbacklist[name] - if l then - local done = true - for _, f in ipairs(l) do - -- the returned value is either true or a new head plus true - rtv1, rtv2 = f.func(head,...) - if type(rtv1) == 'boolean' then - done = rtv1 - elseif type (rtv1) == 'userdata' then - head = rtv1 - end - if type(rtv2) == 'boolean' then - done = rtv2 - elseif type(rtv2) == 'userdata' then - head = rtv2 - end - if done == false then - err("function \"%s\" returned false in callback '%s'", - f.description, name) - end + local ret + local alltrue = true + for _, f in ipairs(callbacklist[name]) do + ret = f.func(head, ...) + if ret == false then + warn("function '%s' returned false\nin callback '%s'", + f.description, name) + break + end + if ret ~= true then + alltrue = false + head = ret end - return head, done - else - return head, false end + return alltrue and true or head end end % \end{macrocode} % -% The handler for callbacks taking datas and returning modified ones. +% Handler for |data| callbacks. % % \begin{macrocode} local function datahandler (name) - return function(data,...) - local l = callbacklist[name] - if l then - for _, f in ipairs(l) do - data = f.func(data,...) - end + return function(data, ...) + for _, f in ipairs(callbacklist[name]) do + data = f.func(data, ...) end return data end end % \end{macrocode} % -% This function is for the handlers that don't support more than one -% functions in them. In this case we only call the first function of the -% list. +% Handler for |first| callbacks. We can assume |callbacklist[name]| is not +% empty: otherwise, the function wouldn't be registered in the callback any +% more. % % \begin{macrocode} local function firsthandler (name) return function(...) - local l = callbacklist[name] - if l then - local f = l[1].func - return f(...) - else - return nil, false - end + return callbacklist[name][1].func(...) end end % \end{macrocode} % -% Handler for simple functions that don't return anything. +% Handler for |simple| callbacks. % % \begin{macrocode} local function simplehandler (name) return function(...) - local l = callbacklist[name] - if l then - for _, f in ipairs(l) do - f.func(...) - end + for _, f in ipairs(callbacklist[name]) do + f.func(...) end end end % \end{macrocode} % -% \subsubsection{Public functions} +% Finally, keep a handlers table for indexed access. % -% The main function. The signature is \texttt{add (name, -% func, description, priority)} with \texttt{name} being the name of the -% callback in which the function is added; \texttt{func} is the added -% function; \texttt{description} is a small character string describing the -% function, and \texttt{priority} an optional argument describing the -% priority the function will have. +% \begin{macrocode} +local handlers = { + [list] = listhandler, + [data] = datahandler, + [first] = firsthandler, + [simple] = simplehandler, +} +% \end{macrocode} % -% The functions for a callbacks are added in a list (in -% \texttt{callbacklist\\.callbackname}). If they have no -% priority or a high priority number, they will be added at the end of the -% list, and will be called after the others. If they have a low priority -% number, the will be added at the beginning of the list and will be called -% before the others. +% \subsubsection{Public functions for functions management} % -% Something that must be made clear, is that there is absolutely no -% solution for packages conflicts: if two packages want the top priority on -% a certain callback, they will have to decide the priority they will give -% to their function themselves. Most of the time, the priority is not needed. +% Add a function to a callback. First check arguments. % % \begin{macrocode} function add_to_callback (name,func,description,priority) if type(func) ~= "function" then - err("unable to add function, no proper function passed") - return + return err("unable to add function:\nno proper function passed") end if not name or name == "" then - err("unable to add function, no proper callback name passed") + err("unable to add function:\nno proper callback name passed") return elseif not callbacktypes[name] then - err("unable to add function, '%s' is not a valid callback", name) + err("unable to add function:\n'%s' is not a valid callback", name) return end if not description or description == "" then - err("unable to add function to '%s', no proper description passed", + err("unable to add function to '%s':\nno proper description passed", name) return end - if priority_in_callback(name, description) ~= 0 then - warning("function '%s' already registered in callback '%s'", + if priority_in_callback(name, description) then + err("function '%s' already registered\nin callback '%s'", description, name) + return end +% \end{macrocode} +% +% Then test if this callback is already in use. If not, initialise its list +% and register the proper handler. +% +% \begin{macrocode} local l = callbacklist[name] if not l then l = {} callbacklist[name] = l if not lua_callbacks_defaults[name] then - if callbacktypes[name] == list then - internalregister(name, listhandler(name)) - elseif callbacktypes[name] == data then - internalregister(name, datahandler(name)) - elseif callbacktypes[name] == simple then - internalregister(name, simplehandler(name)) - elseif callbacktypes[name] == first then - internalregister(name, firsthandler(name)) - else - err("unknown callback type") - end + register_callback(name, handlers[callbacktypes[name]](name)) end end +% \end{macrocode} +% +% Actually register the function. +% +% \begin{macrocode} local f = { func = func, description = description, @@ -617,33 +686,35 @@ function add_to_callback (name,func,description,priority) elseif priority < 1 then priority = 1 end - if callbacktypes[name] == first and (priority ~= 1 or #l ~= 0) then - warning("several callbacks registered in callback '%s', " - .."only the first function will be active.", name) - end table.insert(l,priority,f) - log("inserting function '%s' at position %s in callback list for '%s'", +% \end{macrocode} +% +% Keep user informed. +% +% \begin{macrocode} + if callbacktypes[name] == first and #l ~= 1 then + warning("several functions in '%s',\n" + .."only one will be active.", name) + end + info("inserting '%s'\nat position %s in '%s'", description, priority, name) end % \end{macrocode} % -% The function that removes a function from a callback. The signature is -% \texttt{remove (name, description)} with \texttt{name} being -% the name of callbacks, and description the description passed to -% \texttt{add}. +% Remove a function from a callback. First check arguments. % % \begin{macrocode} function remove_from_callback (name, description) if not name or name == "" then - err("unable to remove function, no proper callback name passed") + err("unable to remove function:\nno proper callback name passed") return elseif not callbacktypes[name] then - err("unable to remove function, '%s' is not a valid callback", name) + err("unable to remove function:\n'%s' is not a valid callback", name) return end if not description or description == "" then err( - "unable to remove function from '%s', no proper description passed", + "unable to remove function from '%s':\nno proper description passed", name) return end @@ -652,45 +723,84 @@ function remove_from_callback (name, description) err("no callback list for '%s'",name) return end +% \end{macrocode} +% +% Then loop over the callback's function list until we find a matching +% entry. Remove it and check if the list gets empty: if so, unregister the +% callback handler unless the callback is user-defined. +% +% \begin{macrocode} + local index = false for k,v in ipairs(l) do if v.description == description then - table.remove(l,k) - log("removing function '%s' from '%s'",description,name) - if not next(l) then - callbacklist[name] = nil - if not lua_callbacks_defaults[name] then - internalregister(name, nil) - end - end - return + index = k + break + end + end + if not index then + err("unable to remove '%s'\nfrom '%s'", description, name) + return + end + table.remove(l, index) + info("removing '%s'\nfrom '%s'", description, name) + if table.maxn(l) == 0 then + callbacklist[name] = nil + if not lua_callbacks_defaults[name] then + register_callback(name, nil) end end - warning("unable to remove function '%s' from '%s'",description,name) + return end % \end{macrocode} % -% This function removes all the functions registered in a callback. +% Remove all the functions registered in a callback. Unregisters the +% callback handler unless the callback is user-defined. % % \begin{macrocode} -function reset_callback (name) +function reset_callback (name, make_false) if not name or name == "" then - err("unable to reset, no proper callback name passed") + err("unable to reset:\nno proper callback name passed") return elseif not callbacktypes[name] then - err("reset error, '%s' is not a valid callback", name) + err("unable to reset '%s':\nis not a valid callback", name) return end + info("resetting callback '%s'", name) + callbacklist[name] = nil if not lua_callbacks_defaults[name] then - internalregister(name, nil) + if make_false == true then + info("setting '%s' to false", name) + register_callback(name, false) + else + register_callback(name, nil) + end + end +end +% \end{macrocode} +% +% Get a function's priority in a callback list, or false if the function is +% not in the list. +% +% \begin{macrocode} +function priority_in_callback (name, description) + if not name or name == "" + or not callbacktypes[name] + or not description then + return false end local l = callbacklist[name] - if l then - log("resetting callback list '%s'",name) - callbacklist[name] = nil + if not l then return false end + for p, f in pairs(l) do + if f.description == description then + return p + end end + return false end % \end{macrocode} % +% \subsubsection{Public functions for user-defined callbacks} +% % This first function creates a new callback. The signature is % \texttt{create(name, ctype, default)} where \texttt{name} is the name of % the new callback to create, \texttt{ctype} is the type of callback, and @@ -705,24 +815,24 @@ end % \begin{macrocode} function create_callback(name, ctype, default) if not name then - err("unable to call callback, no proper name passed", name) + err("unable to call callback:\nno proper name passed", name) return nil end if not ctype or not default then - err("unable to create callback '%s': " + err("unable to create callback '%s':\n" .."callbacktype or default function not specified", name) return nil end if callbacktypes[name] then - err("unable to create callback '%s', callback already exists", name) + err("unable to create callback '%s':\ncallback already exists", name) return nil end - local temp = str_to_type(ctype) - if not temp then - err("unable to create callback '%s', type '%s' undefined", name, ctype) + ctype = types[ctype] + if not ctype then + err("unable to create callback '%s':\ntype '%s' undefined", name, ctype) return nil end - ctype = temp + info("creating '%s' type %s", name, ctype) lua_callbacks_defaults[name] = default callbacktypes[name] = ctype end @@ -734,11 +844,11 @@ end % \begin{macrocode} function call_callback(name, ...) if not name then - err("unable to call callback, no proper name passed", name) + err("unable to call callback:\nno proper name passed", name) return nil end if not lua_callbacks_defaults[name] then - err("unable to call lua callback '%s', unknown callback", name) + err("unable to call lua callback '%s':\nunknown callback", name) return nil end local l = callbacklist[name] @@ -746,92 +856,254 @@ function call_callback(name, ...) if not l then f = lua_callbacks_defaults[name] else - if callbacktypes[name] == list then - f = listhandler(name) - elseif callbacktypes[name] == data then - f = datahandler(name) - elseif callbacktypes[name] == simple then - f = simplehandler(name) - elseif callbacktypes[name] == first then - f = firsthandler(name) - else + f = handlers[callbacktypes[name]](name) + if not f then err("unknown callback type") + return end end return f(...) end % \end{macrocode} % -% This function tells if a function has already been registered in a -% callback, and gives its current priority. The arguments are the name of -% the callback and the description of the function. If it has already been -% registered, it gives its priority, and if not it returns false. +% That's all folks! % % \begin{macrocode} -function priority_in_callback (name, description) - if not name or name == "" - or not callbacktypes[name] - or not description then - return 0 - end - local l = callbacklist[name] - if not l then return 0 end - for p, f in pairs(l) do - if f.description == description then - return p - end - end - return 0 +% +% \end{macrocode} +% +% \section{Test files} +% +% A few basic tests for Plain and LaTeX. Use a separate Lua file for +% convenience, since this package works on the Lua side of the force. +% +% \begin{macrocode} +%<*testlua> +local msg = texio.write_nl +% \end{macrocode} +% +% Test the management functions with a predefined callback. +% +% \begin{macrocode} +local function sample(head,...) + return head, true end +local prio = luatexbase.priority_in_callback +msg("\n*********\n* Testing management functions\n*********") +luatexbase.add_to_callback("hpack_filter", sample, "sample one", 1) +luatexbase.add_to_callback("hpack_filter", sample, "sample two", 2) +luatexbase.add_to_callback("hpack_filter", sample, "sample three", 1) +assert(prio("hpack_filter", "sample three")) +luatexbase.remove_from_callback("hpack_filter", "sample three") +assert(not prio("hpack_filter", "sample three")) +luatexbase.reset_callback("hpack_filter") +assert(not prio("hpack_filter", "sample one")) % \end{macrocode} % -% Finally we -% overwrite \texttt{callback.register} so that it outputs an error. +% Create a callback, and check that the managment functions work with this +% callback too. % % \begin{macrocode} -callback.register = function () -err("function callback.register has been deleted by luamcallbacks, " -.."please use luatexbase.add_to_callback instead.") +local function data_one(s) + texio.write_nl("I'm data 1 whith argument: "..s) + return s end +local function data_two(s) + texio.write_nl("I'm data 2 whith argument: "..s) + return s +end +local function data_three(s) + texio.write_nl("I'm data 3 whith argument: "..s) + return s +end +msg("\n*********\n* Testing user-defined callbacks\n*********") +msg("* create one") +luatexbase.create_callback("fooback", "data", data_one) +msg("* call it") +luatexbase.call_callback("fooback", "default") +msg("* add two functions") +luatexbase.add_to_callback("fooback", data_two, "function two", 2) +luatexbase.add_to_callback("fooback", data_three, "function three", 1) +msg("* call") +luatexbase.call_callback("fooback", "all") +msg("* rm one function") +luatexbase.remove_from_callback("fooback", "function three") +msg("* call") +luatexbase.call_callback("fooback", "all but three") +msg("* reset") +luatexbase.reset_callback("fooback") +msg("* call") +luatexbase.call_callback("fooback", "default") % \end{macrocode} % -% That's all folks! +% Now, we want to make each handler run at least once. So, define dummy +% functions and register them in various callbacks. We will make sure the +% callbacks are executed on the \tex end. Also, we want to check that +% everything works when we unload the functions either one by one, or using +% reset. +% +% A |list| callback. % % \begin{macrocode} -% +function add_hpack_filter() + luatexbase.add_to_callback('hpack_filter', function(head, ...) + texio.write_nl("I'm a dummy hpack_filter") + return head + end, + 'dummy hpack filter') + luatexbase.add_to_callback('hpack_filter', function(head, ...) + texio.write_nl("I'm an optimized dummy hpack_filter") + return true + end, + 'optimized dummy hpack filter') +end +function rm_one_hpack_filter() + luatexbase.remove_from_callback('hpack_filter', 'dummy hpack filter') +end +function rm_two_hpack_filter() + luatexbase.remove_from_callback('hpack_filter', + 'optimized dummy hpack filter') +end % \end{macrocode} % -% \section{Test files} +% A |simple| callback. +% +% \begin{macrocode} +function add_hyphenate() + luatexbase.add_to_callback('hyphenate', function(head, tail) + texio.write_nl("I'm a dummy hyphenate") + end, + 'dummy hyphenate') + luatexbase.add_to_callback('hyphenate', function(head, tail) + texio.write_nl("I'm an other dummy hyphenate") + end, + 'other dummy hyphenate') +end +function rm_one_hyphenate() + luatexbase.remove_from_callback('hyphenate', 'dummy hyphenate') +end +function rm_two_hyphenate() + luatexbase.remove_from_callback('hyphenate', 'other dummy hyphenate') +end +% \end{macrocode} +% +% A |first| callback. +% +% \begin{macrocode} +function add_find_write_file() + luatexbase.add_to_callback('find_write_file', function(id, name) + texio.write_nl("I'm a dummy find_write_file") + return "dummy-"..name + end, + 'dummy find_write_file') + luatexbase.add_to_callback('find_write_file', function(id, name) + texio.write_nl("I'm an other dummy find_write_file") + return "dummy-other-"..name + end, + 'other dummy find_write_file') +end +function rm_one_find_write_file() + luatexbase.remove_from_callback('find_write_file', + 'dummy find_write_file') +end +function rm_two_find_write_file() + luatexbase.remove_from_callback('find_write_file', + 'other dummy find_write_file') +end +% \end{macrocode} % -% A few basic tests for Plain and LaTeX. +% A |data| callback. +% +% \begin{macrocode} +function add_process_input_buffer() + luatexbase.add_to_callback('process_input_buffer', function(buffer) + return buffer.."\\msg{dummy}" + end, + 'dummy process_input_buffer') + luatexbase.add_to_callback('process_input_buffer', function(buffer) + return buffer.."\\msg{otherdummy}" + end, + 'other dummy process_input_buffer') +end +function rm_one_process_input_buffer() + luatexbase.remove_from_callback('process_input_buffer', + 'dummy process_input_buffer') +end +function rm_two_process_input_buffer() + luatexbase.remove_from_callback('process_input_buffer', + 'other dummy process_input_buffer') +end +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} % % \begin{macrocode} %\input luatexbase-mcb.sty %\RequirePackage{luatexbase-mcb} %<*testplain,testlatex> \catcode 64 11 -\luatexbase@directlua{ - local function one(head,...) - texio.write_nl("I'm number 1") - return head, true - end - - local function two(head,...) - texio.write_nl("I'm number 2") - return head, true - end - - local function three(head,...) - texio.write_nl("I'm number 3") - return head, true - end - - luatexbase.add_to_callback("hpack_filter",one,"my sample function one",1) - luatexbase.add_to_callback("hpack_filter",two,"my sample function two",2) - luatexbase.add_to_callback("hpack_filter",three,"my sample function three",1) - - luatexbase.remove_from_callback("hpack_filter","my sample function three") +\def\msg{\immediate\write16} +\msg{===== BEGIN =====} +% \end{macrocode} +% +% Loading the lua files tests that the management functions can be called +% without raising errors. +% +% \begin{macrocode} +\luatexbase@directlua{dofile('test-mcb.lua')} +% \end{macrocode} +% +% We now want to load and unload stuff from the various callbacks have them +% called to test the handlers. Here is a helper macro for that. +% +% \begin{macrocode} +\def\test#1#2{% + \msg{^^J*********^^J* Testing #1 (type #2)^^J*********} + \msg{* Add two functions} + \luatexbase@directlua{add_#1()} + \csname test_#1\endcsname + \msg{* Remove one} + \luatexbase@directlua{rm_one_#1()} + \csname test_#1\endcsname + \msg{* Remove the second} + \luatexbase@directlua{rm_two_#1()} + \csname test_#1\endcsname + \msg{* Add two functions again} + \luatexbase@directlua{add_#1()} + \csname test_#1\endcsname + \msg{* Remove all functions} + \luatexbase@directlua{luatexbase.reset_callback("#1")} + \csname test_#1\endcsname } +% \end{macrocode} +% +% For each callback, we need a specific macro that triggers it. For the +% hyphenate test, we need to untrap |\everypar| first, in the \latex case. +% +% \begin{macrocode} +\catcode`\_ 11 +%\everypar{} +\def\test_hpack_filter{\setbox0=\hbox{bla}} +\def\test_hyphenate{\showhyphens{hyphenation}} +\def\test_find_write_file{\immediate\openout15 test-mcb-out.log} +\def\test_process_input_buffer{\input test-mcb-aux.tex} +% \end{macrocode} +% +% Now actually test them +% +% \begin{macrocode} +\test{hpack_filter}{list} +\test{hyphenate}{simple} +\test{find_write_file}{first} +\test{process_input_buffer}{data} +% \end{macrocode} +% +% Done. +% +% \begin{macrocode} +\msg{===== END =====} % %\bye %\stop diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx index dd5b118f9aa..81394be2f93 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-modutils.dtx @@ -115,11 +115,7 @@ See source file '\inFileName' for details. % 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}} +% \pkdate{luatexbase-modutils}{v0.2 2010-05-12} % % \maketitle % @@ -129,15 +125,16 @@ See source file '\inFileName' for details. % \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}. +% an option mechanism). It also provides functions for reporting errors and +% warnings in a standardised format. % \end{abstract} % % \tableofcontents % % \section{Documentation} % +% \subsection{Scope of this package} +% % 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 @@ -147,57 +144,148 @@ See source file '\inFileName' for details. % 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. +% \latex's system. % -% This package also provides Lua functions for reporting errors, warnings, -% etc. +% \medskip % % 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()|. +% completely orthogonal with the present package. It has nothing to do with +% identification and deals only with namespaces: more precisely, it +% modifies the current environment. So, you should continue to +% use it normally regardless of whether you chose to use this package's +% features for identification. +% +% It is recommended to always use |module()| or any other method that ensure +% the global name space remains clean. For example, you may heavily use the +% |local| keyword and explicitly qualify the name of every non-local symbol. +% Chapter 15 of \href{http://www.lua.org/pil/}{Programming in Lua, 1st ed.} +% discusses various methods for managing packages. % % \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. +% \begin{qcode} +% \cs{RequireLuaModule}\marg{name}\oarg{date} +% \end{qcode} +% +% The macro |\RequireLuaModule| is an interface to the Lua function +% |require_module|; it take the same arguments with the same meaning. The +% second argument is optional. % % \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). +% \begin{qcode} +% luatexbase.require_module({\meta{name}} [, \meta{required date}]) +% \end{qcode} +% +% The function |luatexbase.require_module()| may be used as a replacement to +% |require()|. If only one argument is given, the only difference with +% |require()| is it checks that the module properly identifies itself (as +% explained below) with the same name. +% +% The second argument is optional; if used, it must be a +% string\footnote{Previous versions of the package supported floating-point +% version numbers as well, but it caused confusion with authors trying to use +% version strings such as |0.3a| and probably isn't worth the trouble.} +% containing a date in |YYYY//MM/DD| format which specifies the minimum +% version of the module required. +% +% \begin{qcode} +% luatexbase.provides_module(\meta{info}) +% \end{qcode} +% This function is used by modules to identify themselves; the argument is a +% table containing information about the module. The required field |name| +% must contain the name of the module. It is recommended to provide a field +% |date| with the same format as above. Optional fields |version| (number or +% string) and |description| may be used if present. Other fields are ignored. +% +% If a date was required, then a warning is issued if the required date is +% strictly newer than the declared date (or if no date was declared). A list +% of loaded modules and their associated information is kept, and used to +% check the date without reloading the module (since |require()| won't reload +% it anyway) if a module is required several times. +% +% \begin{qcode} +% luatexbase.module_error(\meta{name}, \meta{message}, ...) +% luatexbase.module_warning(\meta{name}, \meta{message}, ...) +% luatexbase.module_info(\meta{name}, \meta{message}, ...) +% luatexbase.module_log(\meta{name}, \meta{message}, ...) +% \end{qcode} +% These functions are similar to \latex's |\PackageError|, |\PackageWarning| +% and |\PackageInfo| in the way they format the output. No automatic line +% breaking is done, you may still use |\n| as usual for that, and the name of +% the package will be prepended to each output line (except for |log| which is +% intended for short messages in a non-verbose format). The first argument +% is the name of the current module; the remaining arguments are passed to +% |string.format()|. +% +% Note that |module_error| raises an actual Lua error with |error()|, which +% currently means a call stack will be dumped. While this may not look pretty, +% at least it provides useful information for tracking the error down. +% +% \begin{qcode} +% local err, warn, info, log = luatexbase.errwarinf(\meta{name}) +% local err, warn, info, log = luatexbase.provides_module(\meta{name}) +% \end{qcode} +% Customised versions of the above commands maybe obtained by invoking +% |errwarinf()| and are also returned by |provides_module()|. They don't take +% the name of the module as their first argument any more, so that you don't +% need to repeat it all over the place. (Notice that |error| is the name of a +% standard Lua function, so you may want to avoid overwriting it, hence the +% use of |err| in the above example.) +% +% \subsection{Templates} +% +% Let me emphasize again that, while |luatexbase.require_module()| is meant to +% be used as a replacement for |require()|, the function +% |luatexbase.provides_module()| \emph{is not} a replacement for |module()|: +% they just don't do the same thing (declaring information vs changing the +% current name space). +% +% Now, here is how you module may begin: +% \begin{verbatim} +% local err, warn, info, log = luatexbase.provides_module({ +% -- required +% name = 'mymodule', +% -- recommended +% date = '1970/01/01', +% version = 0.0, -- or version = '0.0a', +% description = 'a Lua module template', +% -- optional and ignored +% author = 'A. U. Thor', +% licence = 'LPPL v1.3+', +% }) +% +% module('mynamespace', package.seeall) +% -- or any other method (see chapter 15 of PIL for examples) +% \end{verbatim} +% +% Alternatively, if you don't want to assume \pk{luatexbase-modutils} is +% loaded, you may load your module with: +% \begin{verbatim} +% (luatexbase.require_module or require)('mymodule') +% \end{verbatim} +% and begin your module's code with: +% \begin{verbatim} +% if luatexbase._provides_module then +% luatexbase.provides_module({ +% -- required +% name = 'mymodule', +% -- recommended +% date = '1970/01/01', +% version = 0.0, -- or version = '0.0a', +% description = 'a Lua module template', +% -- optional and ignored +% author = 'A. U. Thor', +% licence = 'LPPL v1.3+', +% }) +% end +% +% module('mynamespace', package.seeall) +% -- or any other method (see chapter 15 of PIL for examples) +% +% local function err(msg) +% -- etc. +% \end{verbatim} % % \section{Implementation} % @@ -263,7 +351,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-modutils}[2010/05/27 v0.2a Module utilities for LuaTeX] +\x{luatexbase-modutils}[2010/10/10 v0.3 Module utilities for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -277,60 +365,94 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-modutils}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@modutils@AtEnd \expandafter\endinput \fi % \end{macrocode} % -% Load \pk{luatexbase-loader} (hence \pk{luatexbase-compat}) and require -% supporting Lua module. +% Load \pk{luatexbase-loader} (hence \pk{luatexbase-compat}), require the +% supporting Lua module and make sure |luaescapestring| is available. % % \begin{macrocode} -\begingroup\expandafter\expandafter\expandafter\endgroup -\expandafter\ifx\csname RequirePackage\endcsname\relax - \input luatexbase-loader.sty -\else +\ifdefined\RequirePackage \RequirePackage{luatexbase-loader} +\else + \input luatexbase-loader.sty \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} +% \subsection{Auxiliary definitions} % -% Interface to |use_module()|. +% We need a version of |\@ifnextchar|. The definitions for the not-\latex +% case are stolen from \pk{ltxcmds} verbatim, only the prefix is changed. % % \begin{macrocode} -\def\luatexUseModule#1{\luatexbase@directlua{% - luatexbase.use_module("\luatexluaescapestring{#1}")}} +\ifdefined\kernel@ifnextchar + \let\lltxb@ifnextchar\kernel@ifnextchar +\else + \chardef\lltxb@zero0 + \chardef\lltxb@two2 + \long\def\lltxb@ifnextchar#1#2#3{% + \begingroup + \let\lltxb@CharToken= #1\relax + \toks\lltxb@zero{#2}% + \toks\lltxb@two{#3}% + \futurelet\lltxb@LetToken\lltxb@ifnextchar@ + } + \def\lltxb@ifnextchar@{% + \ifx\lltxb@LetToken\lltxb@CharToken + \expandafter\endgroup\the\toks\expandafter\lltxb@zero + \else + \ifx\lltxb@LetToken\lltxb@SpaceToken + \expandafter\expandafter\expandafter\lltxb@@ifnextchar + \else + \expandafter\endgroup\the\toks + \expandafter\expandafter\expandafter\lltxb@two + \fi + \fi + } + \begingroup + \def\x#1{\endgroup + \def\lltxb@@ifnextchar#1{% + \futurelet\lltxb@LetToken\lltxb@ifnextchar@ + }% + }% + \x{ } + \begingroup + \def\x#1{\endgroup + \let\lltxb@SpaceToken= #1% + }% + \x{ } +\fi % \end{macrocode} % -% Interface to |require_module()| with syntax depending on the format. +% \subsubsection{User macro} +% +% Interface to the Lua function for module loading. Avoid passing a second +% argument to the function if empty (most probably not specified). % % \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 +\def\RequireLuaModule#1{% + \lltxb@ifnextchar[{\lltxb@requirelua{#1}}{\lltxb@requirelua{#1}[]}} +\def\lltxb@requirelua#1[#2]{% + \luatexbase@directlua{luatexbase.require_module( + "\luatexluaescapestring{#1}" + \expandafter\ifx\expandafter\/\detokenize{#2}\/\else + , "\luatexluaescapestring{#2}" + \fi)}} % \end{macrocode} % % \begin{macrocode} @@ -348,75 +470,75 @@ module("luatexbase", package.seeall) % \subsection{Internal functions and data} % % Tables holding informations about the modules loaded and the versions -% required. +% required. Keys are module names and values are the info tables as passed +% to |provides_module()|. % % \begin{macrocode} local modules = modules or {} -local requiredversions = {} % \end{macrocode} % -% Convert a date in YYYY/MM/DD format into a number +% Convert a date in YYYY/MM/DD format into a number. % % \begin{macrocode} -local function datetonumber(date) +local function date_to_int(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. +% Here are the reporting functions for the modules. An internal function is +% used for error messages, so that the calling level (last argument of +% |error()| remains constant using either |module_error()| or a custom +% version as returned by |errwarinf()|. % % \begin{macrocode} +local function msg_format(msg_type, mod_name, ...) + local cont = '('..mod_name..')' .. ('Module: '..msg_type):gsub('.', ' ') + return 'Module '..mod_name..' '..msg_type..': ' + .. string.format(...):gsub('\n', '\n'..cont) .. '\n' +end local function module_error_int(mod, ...) - error('Module '..mod..' error: '..string.format(...), 3) + error(msg_format('error', mod, ...), 3) end function module_error(mod, ...) module_error_int(mod, ...) end +% \end{macrocode} +% +% Split the lines explicitly in order not to depend on the value of +% |\newlinechar|. +% +% \begin{macrocode} function module_warning(mod, ...) - texio.write_nl("Module "..mod.." warning: "..string.format(...)) + for _, line in ipairs(msg_format('warning', mod, ...):explode('\n')) do + texio.write_nl(line) + end end function module_info(mod, ...) - texio.write_nl(mod..": "..string.format(...)) + for _, line in ipairs(msg_format('info', mod, ...):explode('\n')) do + texio.write_nl(line) + end end -function module_log(mod, ...) - texio.write_nl('log', mod..": "..string.format(...)) +% \end{macrocode} +% +% No line splitting or advanced formating here. +% +% \begin{macrocode} +function module_log(mod, msg, ...) + texio.write_nl('log', mod..': '..msg:format(...)) end -function module_term(mod, ...) - texio.write_nl('term', mod..": "..string.format(...)) +% \end{macrocode} +% +% Produce custom versions of the reporting functions. +% +% \begin{macrocode} +function errwarinf(name) + return function(...) module_error_int(name, ...) end, + function(...) module_warning(name, ...) end, + function(...) module_info(name, ...) end, + function(...) module_log(name, ...) end end % \end{macrocode} % @@ -424,83 +546,42 @@ end % present module. % % \begin{macrocode} -local function err(...) module_error_int('luatexbase.modutils', ...) end -local function warn(...) module_warning('luatexbase.modutils', ...) end +local err, warn = errwarinf('luatexbase.modutils') % \end{macrocode} % % \subsubsection{module loading and providing functions} % -% Load a module without version checking. +% Load a module with mandatory name checking and optional version checking. % % \begin{macrocode} -function use_module(name) +function require_module(name, req_date) 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 + local info = modules[name] + if not info then + warn("module '%s' was not properly identified", name) + elseif version then + if not (info.date and date_to_int(info.date) > date_to_int(req_date)) + then + warn("module '%s' required in version '%s'\n" + .. "but found in version '%s'", name, req_date, info.date) end - else - requiredversions[name] = luaversion - use_module(name) end end % \end{macrocode} % -% Provide identification information for a module. +% Provide identification information for a module. As a bonus, custom +% reporting functions are returned. No need to do any check here, +% everything done in |require_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 +function provides_module(info) + if not (info and info.name) then + err('provides_module: missing information') end - modules[mod.name] = mod - texio.write_nl('log', string.format("Lua module: %s %s v%.02f %s\n", - mod.name, mod.date, mod.version, mod.description)) + texio.write_nl('log', string.format("Lua module: %s %s %s %s\n", + info.name, info.date or '', info.version or '', info.description or '')) + modules[info.name] = info + return errwarinf(info.name) end % \end{macrocode} % @@ -514,28 +595,26 @@ end % % \begin{macrocode} %<*testdummy> -luatexbase.provides_module { +local err, warn, info, log = luatexbase.provides_module { name = 'test-modutils', date = '2000/01/01', version = 1, description = 'dummy test package', } +info('It works!\nOh, rly?\nYeah rly!') +log("I'm a one-line info.") % % \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 +% TeX, is able to load and identify the above dummy module. % % \begin{macrocode} %\input luatexbase-modutils.sty %\RequirePackage{luatexbase-modutils} %<*testplain,testlatex> -\luatexUseModule{test-modutils} -\luatexRequireModule -%[1970/01/01] -{test-modutils} -%{1970/01/01} +\RequireLuaModule{test-modutils} +\RequireLuaModule{test-modutils}[1970/01/01] % %\bye %\stop diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-regs.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-regs.dtx index 08d1060ab23..079b0045fba 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase-regs.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase-regs.dtx @@ -103,11 +103,7 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \pk{luatexbase-regs} package} -% \date{v0.2a 2010/05/27} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \email{mpg@elzevir.fr} \and -% \'Elie Roux \\ \email{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase-regs}{2010/10/10 v0.3} % % \maketitle % @@ -211,7 +207,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-regs}[2010/05/27 v0.2a Registers allocation for LuaTeX] +\x{luatexbase-regs}[2010/10/10 v0.3 Registers allocation for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -225,14 +221,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-regs}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@regs@AtEnd \expandafter\endinput \fi @@ -267,7 +266,7 @@ See source file '\inFileName' for details. \let\x\PackageWarningNoLine \fi \expandafter\endgroup - \x{luatexbase-regs}{etex macros not loaded!^^J + \x{luatexbase-regs}{etex macros not loaded!^^J% Registers allocation scheme will not be extended.} \else % \end{macrocode} diff --git a/Master/texmf-dist/source/luatex/luatexbase/luatexbase.dtx b/Master/texmf-dist/source/luatex/luatexbase/luatexbase.dtx index 3e14f4cf1f4..405e72007de 100644 --- a/Master/texmf-dist/source/luatex/luatexbase/luatexbase.dtx +++ b/Master/texmf-dist/source/luatex/luatexbase/luatexbase.dtx @@ -96,24 +96,20 @@ See source file '\inFileName' for details. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \pk{luatexbase} package} -% \date{v0.2a 2010-05-27} -% \author{% -% Manuel P\'egouri\'e-Gonnard \\ \email{mpg@elzevir.fr} \and -% \'Elie Roux \\ \email{elie.roux@telecom-bretagne.eu}} +% \pkdate{luatexbase}{v0.3 2010-05-27} % % \maketitle % % \begin{abstract} -% This convenience package loads all of the (stable) packages in the -% \pk{luatexbase} bundle. +% This package provides resource management for the LuaTeX macro programmer. +% It is divided in sub-packages which can be used independantly if desired. % \end{abstract} % % \tableofcontents % % \section{Documentation} % -% The \pk{luatexbase} package loads the following packages: +% The \pk{luatexbase} package consists of the following sub-packages: % \begin{description} % \subpk{compat} compatibility helpers for \verb+\directlua+, primitive % names and version information from Lua. @@ -124,25 +120,19 @@ See source file '\inFileName' for details. % \emph{\`a la} \pk{etex}. % \subpk{cctb} catcode table allocation. % \subpk{attr} attribute allocation. -% \end{description} -% -% These packages are almost stable: it is unlikely that backward-incompatible -% changes will be made in the future (other than necessary for merging with -% \pk{luatex.sty}, which strongly overlaps with the above). If they happen, -% such changes will be announced on \email{lualatex-dev@tug.org} before they -% are pushed to the master branch and then CTAN. -% -% Other packages included in the bundle, but currently not loaded by the -% present package, are: -% \begin{description} -% \subpk{modutils} Lua module declaration, including version checks. % \subpk{mcb} callbacks extensions allowing to register many functions in a % single callback, and declare new callbacks for packages. +% \subpk{modutils} Lua module declaration, including version checks. % \end{description} % -% All packages in this bundle are supposed to work with \luatex 0.25.4 to -% 0.60.x, with formats based on \plaintex or \latex, as included in \texlive -% 2008, 2009, and 2010. +% The package is mostly stable: it is unlikely that backward-incompatible +% changes will be made in the future, other than necessary for merging with +% \pk{luatex.sty}, with which a few sub-packages strongly overlap. If they do +% happen, such changes will be announced on the development list, and clearly +% identified in the \file{Changes} file. +% +% All sub-packages are tested with \luatex 0.25.4 to 0.60.x and formats based +% on \plaintex or \latex, as included in \texlive 2008, 2009, and 2010. % % \section{Implementation} % @@ -206,7 +196,7 @@ See source file '\inFileName' for details. \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase}[2010/05/27 v0.2a Module utilities for LuaTeX] +\x{luatexbase}[2010/10/06 v0.3 Module utilities for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. @@ -220,14 +210,17 @@ See source file '\inFileName' for details. \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@core@AtEnd \expandafter\endinput \fi @@ -243,12 +236,16 @@ See source file '\inFileName' for details. \input luatexbase-regs.sty \input luatexbase-attr.sty \input luatexbase-cctb.sty + \input luatexbase-mcb.sty + \input luatexbase-modutils.sty \else \RequirePackage{luatexbase-compat} \RequirePackage{luatexbase-loader} \RequirePackage{luatexbase-regs} \RequirePackage{luatexbase-attr} \RequirePackage{luatexbase-cctb} + \RequirePackage{luatexbase-mcb} + \RequirePackage{luatexbase-modutils} \fi % \end{macrocode} % diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-attr.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-attr.sty index 5a78ea8a4fa..cea0e56aaac 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-attr.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-attr.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-attr}[2010/05/27 v0.2a Attributes allocation for LuaTeX] +\x{luatexbase-attr}[2010/10/10 v0.3 Attributes allocation for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@attr@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-cctb.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-cctb.sty index d526f2f46a6..76321642650 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-cctb.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-cctb.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-cctb}[2010/05/27 v0.2a Catcodetable allocation for LuaTeX] +\x{luatexbase-cctb}[2010/10/10 v0.3 Catcodetable allocation for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-cctb}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@cctb@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty index be5d4e8ac3a..4dd53855cc6 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-compat.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-compat}[2010/05/27 v0.2a Compatibility tools for LuaTeX] +\x{luatexbase-compat}[2010/10/10 v0.3 Compatibility tools for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-compat}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@compat@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty index 1609aba726e..787dea8e1c0 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-loader.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-loader}[2010/05/27 v0.2a Lua module loader for LuaTeX] +\x{luatexbase-loader}[2010/10/10 v0.3 Lua module loader for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-loader}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@loader@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-mcb.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-mcb.sty index 0fcd35fc4b9..08d1dcf6524 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-mcb.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-mcb.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-mcb}[2010/05/27 v0.2a Callback management for LuaTeX] +\x{luatexbase-mcb}[2010/10/10 v0.3 Callback management for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-mcb}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@mcb@AtEnd \expandafter\endinput \fi diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty index c33ae6a1c61..d9f7e287f5c 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-modutils.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-modutils}[2010/05/27 v0.2a Module utilities for LuaTeX] +\x{luatexbase-modutils}[2010/10/10 v0.3 Module utilities for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,37 +61,72 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-modutils}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@modutils@AtEnd \expandafter\endinput \fi -\begingroup\expandafter\expandafter\expandafter\endgroup -\expandafter\ifx\csname RequirePackage\endcsname\relax - \input luatexbase-loader.sty -\else +\ifdefined\RequirePackage \RequirePackage{luatexbase-loader} +\else + \input luatexbase-loader.sty \fi \luatexbase@directlua{require('luatexbase.modutils')} \luatexbase@ensure@primitive{luaescapestring} -\def\luatexUseModule#1{\luatexbase@directlua{% - luatexbase.use_module("\luatexluaescapestring{#1}")}} -\begingroup\expandafter\expandafter\expandafter\endgroup -\expandafter\ifx\csname newcommand\endcsname\relax - \def\luatexRequireModule#1#2{% - \luatexbase@directlua{luatexbase.require_module( - "\luatexluaescapestring{#1}", "\luatexluaescapestring{#2}")}} +\ifdefined\kernel@ifnextchar + \let\lltxb@ifnextchar\kernel@ifnextchar \else - \newcommand\luatexRequireModule[2][0]{% - \luatexbase@directlua{luatexbase.require_module( - "\luatexluaescapestring{#2}", "\luatexluaescapestring{#1}")}} + \chardef\lltxb@zero0 + \chardef\lltxb@two2 + \long\def\lltxb@ifnextchar#1#2#3{% + \begingroup + \let\lltxb@CharToken= #1\relax + \toks\lltxb@zero{#2}% + \toks\lltxb@two{#3}% + \futurelet\lltxb@LetToken\lltxb@ifnextchar@ + } + \def\lltxb@ifnextchar@{% + \ifx\lltxb@LetToken\lltxb@CharToken + \expandafter\endgroup\the\toks\expandafter\lltxb@zero + \else + \ifx\lltxb@LetToken\lltxb@SpaceToken + \expandafter\expandafter\expandafter\lltxb@@ifnextchar + \else + \expandafter\endgroup\the\toks + \expandafter\expandafter\expandafter\lltxb@two + \fi + \fi + } + \begingroup + \def\x#1{\endgroup + \def\lltxb@@ifnextchar#1{% + \futurelet\lltxb@LetToken\lltxb@ifnextchar@ + }% + }% + \x{ } + \begingroup + \def\x#1{\endgroup + \let\lltxb@SpaceToken= #1% + }% + \x{ } \fi +\def\RequireLuaModule#1{% + \lltxb@ifnextchar[{\lltxb@requirelua{#1}}{\lltxb@requirelua{#1}[]}} +\def\lltxb@requirelua#1[#2]{% + \luatexbase@directlua{luatexbase.require_module( + "\luatexluaescapestring{#1}" + \expandafter\ifx\expandafter\/\detokenize{#2}\/\else + , "\luatexluaescapestring{#2}" + \fi)}} \lltxb@modutils@AtEnd \endinput %% diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-regs.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-regs.sty index 816ddd411b1..aca0843da93 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-regs.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase-regs.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase-regs}[2010/05/27 v0.2a Registers allocation for LuaTeX] +\x{luatexbase-regs}[2010/10/10 v0.3 Registers allocation for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase-regs}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@regs@AtEnd \expandafter\endinput \fi @@ -86,7 +89,7 @@ \let\x\PackageWarningNoLine \fi \expandafter\endgroup - \x{luatexbase-regs}{etex macros not loaded!^^J + \x{luatexbase-regs}{etex macros not loaded!^^J% Registers allocation scheme will not be extended.} \else \ifnum\count270=32768 \count270=65536 \fi diff --git a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase.sty b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase.sty index 734a860310a..1f2c8ba0541 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/luatexbase.sty +++ b/Master/texmf-dist/tex/luatex/luatexbase/luatexbase.sty @@ -52,7 +52,7 @@ \let\x\ProvidesPackage \fi \expandafter\endgroup -\x{luatexbase}[2010/05/27 v0.2a Module utilities for LuaTeX] +\x{luatexbase}[2010/10/06 v0.3 Module utilities for LuaTeX] \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty @@ -61,14 +61,17 @@ \fi \ifluatex\else \begingroup - \expandafter\ifx\csname PackageWarningNoLine\endcsname\relax - \def\x#1#2{\begingroup\newlinechar10 - \immediate\write16{Package #1 warning: #2}\endgroup} + \expandafter\ifx\csname PackageError\endcsname\relax + \def\x#1#2#3{\begingroup \newlinechar10 + \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else - \let\x\PackageWarningNoLine + \let\x\PackageError \fi \expandafter\endgroup - \x{luatexbase}{LuaTeX is required for this package. Aborting.} + \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{% + This package can only be used with the LuaTeX engine^^J% + (command `lualatex' or `luatex').^^J% + Package loading has been stopped to prevent additional errors.} \lltxb@core@AtEnd \expandafter\endinput \fi @@ -79,12 +82,16 @@ \input luatexbase-regs.sty \input luatexbase-attr.sty \input luatexbase-cctb.sty + \input luatexbase-mcb.sty + \input luatexbase-modutils.sty \else \RequirePackage{luatexbase-compat} \RequirePackage{luatexbase-loader} \RequirePackage{luatexbase-regs} \RequirePackage{luatexbase-attr} \RequirePackage{luatexbase-cctb} + \RequirePackage{luatexbase-mcb} + \RequirePackage{luatexbase-modutils} \fi \lltxb@core@AtEnd \endinput diff --git a/Master/texmf-dist/tex/luatex/luatexbase/mcb.lua b/Master/texmf-dist/tex/luatex/luatexbase/mcb.lua index ff4605af30d..2b65b90a22d 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/mcb.lua +++ b/Master/texmf-dist/tex/luatex/luatexbase/mcb.lua @@ -12,198 +12,154 @@ -- See source file 'luatexbase-mcb.dtx' for details. -- module('luatexbase', package.seeall) -luatexbase.provides_module({ - name = "luamcallbacks", +local err, warning, info = luatexbase.provides_module({ + name = "luatexbase-mcb", version = 0.2, date = "2010/05/12", description = "register several functions in a callback", - author = "Hans Hagen, Elie Roux and Manuel P^^c3^^a9gourie-Gonnard", - copyright = "Hans Hagen, Elie Roux and Manuel P^^c3^^a9gourie-Gonnard", + author = "Hans Hagen, Elie Roux and Manuel Pegourie-Gonnard", + copyright = "Hans Hagen, Elie Roux and Manuel Pegourie-Gonnard", license = "CC0", }) -local log = log or function(...) - luatexbase.module_log('luamcallbacks', string.format(...)) -end -local info = info or function(...) - luatexbase.module_info('luamcallbacks', string.format(...)) -end -local warning = warning or function(...) - luatexbase.module_warning('luamcallbacks', string.format(...)) -end -local err = err or function(...) - luatexbase.module_error('luamcallbacks', string.format(...)) -end local callbacklist = callbacklist or { } -local lua_callbacks_defaults = { } -local list = 1 -local data = 2 -local first = 3 -local simple = 4 +local list, data, first, simple = 1, 2, 3, 4 +local types = { + list = list, + data = data, + first = first, + simple = simple, +} local callbacktypes = callbacktypes or { - buildpage_filter = simple, - token_filter = first, - pre_output_filter = list, - hpack_filter = list, - process_input_buffer = data, - mlist_to_hlist = list, - vpack_filter = list, - define_font = first, - open_read_file = first, - linebreak_filter = list, - post_linebreak_filter = list, - pre_linebreak_filter = list, - start_page_number = simple, - stop_page_number = simple, - start_run = simple, - show_error_hook = simple, - stop_run = simple, - hyphenate = simple, - ligaturing = simple, - kerning = data, - find_write_file = first, - find_read_file = first, - find_vf_file = data, - find_map_file = data, - find_format_file = data, - find_opentype_file = data, - find_output_file = data, - find_truetype_file = data, - find_type1_file = data, - find_data_file = data, - find_pk_file = data, - find_font_file = data, - find_image_file = data, - find_ocp_file = data, - find_sfd_file = data, - find_enc_file = data, - read_sfd_file = first, - read_map_file = first, - read_pk_file = first, - read_enc_file = first, - read_vf_file = first, - read_ocp_file = first, - read_opentype_file = first, - read_truetype_file = first, - read_font_file = first, - read_type1_file = first, - read_data_file = first, + find_read_file = first, + find_write_file = first, + find_font_file = data, + find_output_file = data, + find_format_file = data, + find_vf_file = data, + find_ocp_file = data, + find_map_file = data, + find_enc_file = data, + find_sfd_file = data, + find_pk_file = data, + find_data_file = data, + find_opentype_file = data, + find_truetype_file = data, + find_type1_file = data, + find_image_file = data, + open_read_file = first, + read_font_file = first, + read_vf_file = first, + read_ocp_file = first, + read_map_file = first, + read_enc_file = first, + read_sfd_file = first, + read_pk_file = first, + read_data_file = first, + read_truetype_file = first, + read_type1_file = first, + read_opentype_file = first, + process_input_buffer = data, + process_output_buffer = data, + token_filter = first, + buildpage_filter = simple, + pre_linebreak_filter = list, + linebreak_filter = list, + post_linebreak_filter = list, + hpack_filter = list, + vpack_filter = list, + pre_output_filter = list, + hyphenate = simple, + ligaturing = simple, + kerning = simple, + mlist_to_hlist = list, + start_run = simple, + stop_run = simple, + start_page_number = simple, + stop_page_number = simple, + show_error_hook = simple, + define_font = first, } -if luatexbase.luatexversion > 42 then - callbacktypes["process_output_buffer"] = data +local lua_callbacks_defaults = { } +local original_register = original_register or callback.register +callback.register = function () + err("function callback.register has been trapped,\n" + .."please use luatexbase.add_to_callback instead.") end -local internalregister = internalregister or callback.register -local function str_to_type(str) - if str == 'list' then - return list - elseif str == 'data' then - return data - elseif str == 'first' then - return first - elseif str == 'simple' then - return simple - else - return nil - end +local function register_callback(...) + return assert(original_register(...)) end --- local -function listhandler (name) +local function listhandler (name) return function(head,...) - local l = callbacklist[name] - if l then - local done = true - for _, f in ipairs(l) do - -- the returned value is either true or a new head plus true - rtv1, rtv2 = f.func(head,...) - if type(rtv1) == 'boolean' then - done = rtv1 - elseif type (rtv1) == 'userdata' then - head = rtv1 - end - if type(rtv2) == 'boolean' then - done = rtv2 - elseif type(rtv2) == 'userdata' then - head = rtv2 - end - if done == false then - err("function \"%s\" returned false in callback '%s'", - f.description, name) - end + local ret + local alltrue = true + for _, f in ipairs(callbacklist[name]) do + ret = f.func(head, ...) + if ret == false then + warn("function '%s' returned false\nin callback '%s'", + f.description, name) + break + end + if ret ~= true then + alltrue = false + head = ret end - return head, done - else - return head, false end + return alltrue and true or head end end local function datahandler (name) - return function(data,...) - local l = callbacklist[name] - if l then - for _, f in ipairs(l) do - data = f.func(data,...) - end + return function(data, ...) + for _, f in ipairs(callbacklist[name]) do + data = f.func(data, ...) end return data end end local function firsthandler (name) return function(...) - local l = callbacklist[name] - if l then - local f = l[1].func - return f(...) - else - return nil, false - end + return callbacklist[name][1].func(...) end end local function simplehandler (name) return function(...) - local l = callbacklist[name] - if l then - for _, f in ipairs(l) do - f.func(...) - end + for _, f in ipairs(callbacklist[name]) do + f.func(...) end end end +local handlers = { + [list] = listhandler, + [data] = datahandler, + [first] = firsthandler, + [simple] = simplehandler, +} function add_to_callback (name,func,description,priority) if type(func) ~= "function" then - err("unable to add function, no proper function passed") - return + return err("unable to add function:\nno proper function passed") end if not name or name == "" then - err("unable to add function, no proper callback name passed") + err("unable to add function:\nno proper callback name passed") return elseif not callbacktypes[name] then - err("unable to add function, '%s' is not a valid callback", name) + err("unable to add function:\n'%s' is not a valid callback", name) return end if not description or description == "" then - err("unable to add function to '%s', no proper description passed", + err("unable to add function to '%s':\nno proper description passed", name) return end - if priority_in_callback(name, description) ~= 0 then - warning("function '%s' already registered in callback '%s'", + if priority_in_callback(name, description) then + err("function '%s' already registered\nin callback '%s'", description, name) + return end local l = callbacklist[name] if not l then l = {} callbacklist[name] = l if not lua_callbacks_defaults[name] then - if callbacktypes[name] == list then - internalregister(name, listhandler(name)) - elseif callbacktypes[name] == data then - internalregister(name, datahandler(name)) - elseif callbacktypes[name] == simple then - internalregister(name, simplehandler(name)) - elseif callbacktypes[name] == first then - internalregister(name, firsthandler(name)) - else - err("unknown callback type") - end + register_callback(name, handlers[callbacktypes[name]](name)) end end local f = { @@ -216,25 +172,25 @@ function add_to_callback (name,func,description,priority) elseif priority < 1 then priority = 1 end - if callbacktypes[name] == first and (priority ~= 1 or #l ~= 0) then - warning("several callbacks registered in callback '%s', " - .."only the first function will be active.", name) - end table.insert(l,priority,f) - log("inserting function '%s' at position %s in callback list for '%s'", + if callbacktypes[name] == first and #l ~= 1 then + warning("several functions in '%s',\n" + .."only one will be active.", name) + end + info("inserting '%s'\nat position %s in '%s'", description, priority, name) end function remove_from_callback (name, description) if not name or name == "" then - err("unable to remove function, no proper callback name passed") + err("unable to remove function:\nno proper callback name passed") return elseif not callbacktypes[name] then - err("unable to remove function, '%s' is not a valid callback", name) + err("unable to remove function:\n'%s' is not a valid callback", name) return end if not description or description == "" then err( - "unable to remove function from '%s', no proper description passed", + "unable to remove function from '%s':\nno proper description passed", name) return end @@ -243,68 +199,91 @@ function remove_from_callback (name, description) err("no callback list for '%s'",name) return end + local index = false for k,v in ipairs(l) do if v.description == description then - table.remove(l,k) - log("removing function '%s' from '%s'",description,name) - if not next(l) then - callbacklist[name] = nil - if not lua_callbacks_defaults[name] then - internalregister(name, nil) - end - end - return + index = k + break end end - warning("unable to remove function '%s' from '%s'",description,name) + if not index then + err("unable to remove '%s'\nfrom '%s'", description, name) + return + end + table.remove(l, index) + info("removing '%s'\nfrom '%s'", description, name) + if table.maxn(l) == 0 then + callbacklist[name] = nil + if not lua_callbacks_defaults[name] then + register_callback(name, nil) + end + end + return end -function reset_callback (name) +function reset_callback (name, make_false) if not name or name == "" then - err("unable to reset, no proper callback name passed") + err("unable to reset:\nno proper callback name passed") return elseif not callbacktypes[name] then - err("reset error, '%s' is not a valid callback", name) + err("unable to reset '%s':\nis not a valid callback", name) return end + info("resetting callback '%s'", name) + callbacklist[name] = nil if not lua_callbacks_defaults[name] then - internalregister(name, nil) + if make_false == true then + info("setting '%s' to false", name) + register_callback(name, false) + else + register_callback(name, nil) + end + end +end +function priority_in_callback (name, description) + if not name or name == "" + or not callbacktypes[name] + or not description then + return false end local l = callbacklist[name] - if l then - log("resetting callback list '%s'",name) - callbacklist[name] = nil + if not l then return false end + for p, f in pairs(l) do + if f.description == description then + return p + end end + return false end function create_callback(name, ctype, default) if not name then - err("unable to call callback, no proper name passed", name) + err("unable to call callback:\nno proper name passed", name) return nil end if not ctype or not default then - err("unable to create callback '%s': " + err("unable to create callback '%s':\n" .."callbacktype or default function not specified", name) return nil end if callbacktypes[name] then - err("unable to create callback '%s', callback already exists", name) + err("unable to create callback '%s':\ncallback already exists", name) return nil end - local temp = str_to_type(ctype) - if not temp then - err("unable to create callback '%s', type '%s' undefined", name, ctype) + ctype = types[ctype] + if not ctype then + err("unable to create callback '%s':\ntype '%s' undefined", name, ctype) return nil end - ctype = temp + info("creating '%s' type %s", name, ctype) lua_callbacks_defaults[name] = default callbacktypes[name] = ctype end function call_callback(name, ...) if not name then - err("unable to call callback, no proper name passed", name) + err("unable to call callback:\nno proper name passed", name) return nil end if not lua_callbacks_defaults[name] then - err("unable to call lua callback '%s', unknown callback", name) + err("unable to call lua callback '%s':\nunknown callback", name) return nil end local l = callbacklist[name] @@ -312,38 +291,13 @@ function call_callback(name, ...) if not l then f = lua_callbacks_defaults[name] else - if callbacktypes[name] == list then - f = listhandler(name) - elseif callbacktypes[name] == data then - f = datahandler(name) - elseif callbacktypes[name] == simple then - f = simplehandler(name) - elseif callbacktypes[name] == first then - f = firsthandler(name) - else + f = handlers[callbacktypes[name]](name) + if not f then err("unknown callback type") + return end end return f(...) end -function priority_in_callback (name, description) - if not name or name == "" - or not callbacktypes[name] - or not description then - return 0 - end - local l = callbacklist[name] - if not l then return 0 end - for p, f in pairs(l) do - if f.description == description then - return p - end - end - return 0 -end -callback.register = function () -err("function callback.register has been deleted by luamcallbacks, " -.."please use luatexbase.add_to_callback instead.") -end -- -- End of File `mcb.lua'. diff --git a/Master/texmf-dist/tex/luatex/luatexbase/modutils.lua b/Master/texmf-dist/tex/luatex/luatexbase/modutils.lua index 64b420c12cb..40063557c8b 100644 --- a/Master/texmf-dist/tex/luatex/luatexbase/modutils.lua +++ b/Master/texmf-dist/tex/luatex/luatexbase/modutils.lua @@ -13,103 +13,62 @@ -- module("luatexbase", package.seeall) local modules = modules or {} -local requiredversions = {} -local function datetonumber(date) +local function date_to_int(date) numbers = string.gsub(date, "(%d+)/(%d+)/(%d+)", "%1%2%3") return tonumber(numbers) end -local function isdate(date) - for _, _ in string.gmatch(date, "%d+/%d+/%d+") do - return true - end - return false -end -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 +local function msg_format(msg_type, mod_name, ...) + local cont = '('..mod_name..')' .. ('Module: '..msg_type):gsub('.', ' ') + return 'Module '..mod_name..' '..msg_type..': ' + .. string.format(...):gsub('\n', '\n'..cont) .. '\n' end local function module_error_int(mod, ...) - error('Module '..mod..' error: '..string.format(...), 3) + error(msg_format('error', mod, ...), 3) end function module_error(mod, ...) module_error_int(mod, ...) end function module_warning(mod, ...) - texio.write_nl("Module "..mod.." warning: "..string.format(...)) + for _, line in ipairs(msg_format('warning', mod, ...):explode('\n')) do + texio.write_nl(line) + end end function module_info(mod, ...) - texio.write_nl(mod..": "..string.format(...)) + for _, line in ipairs(msg_format('info', mod, ...):explode('\n')) do + texio.write_nl(line) + end end -function module_log(mod, ...) - texio.write_nl('log', mod..": "..string.format(...)) +function module_log(mod, msg, ...) + texio.write_nl('log', mod..': '..msg:format(...)) end -function module_term(mod, ...) - texio.write_nl('term', mod..": "..string.format(...)) +function errwarinf(name) + return function(...) module_error_int(name, ...) end, + function(...) module_warning(name, ...) end, + function(...) module_info(name, ...) end, + function(...) module_log(name, ...) end end -local function err(...) module_error_int('luatexbase.modutils', ...) end -local function warn(...) module_warning('luatexbase.modutils', ...) end -function use_module(name) +local err, warn = errwarinf('luatexbase.modutils') +function require_module(name, req_date) require(name) - if not modules[name] then - warn("Module didn't properly identified itself: %s", name) - end -end -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 + local info = modules[name] + if not info then + warn("module '%s' was not properly identified", name) + elseif version then + if not (info.date and date_to_int(info.date) > date_to_int(req_date)) + then + warn("module '%s' required in version '%s'\n" + .. "but found in version '%s'", name, req_date, info.date) end - else - requiredversions[name] = luaversion - use_module(name) end end -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 +function provides_module(info) + if not (info and info.name) then + err('provides_module: missing information') end - modules[mod.name] = mod - texio.write_nl('log', string.format("Lua module: %s %s v%.02f %s\n", - mod.name, mod.date, mod.version, mod.description)) + texio.write_nl('log', string.format("Lua module: %s %s %s %s\n", + info.name, info.date or '', info.version or '', info.description or '')) + modules[info.name] = info + return errwarinf(info.name) end -- -- End of File `modutils.lua'. -- cgit v1.2.3