%D \module %D [ file=luat-ini, %D version=2005.08.11, %D title=\CONTEXT\ Lua Macros, %D subtitle=Initialization, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Lua Macros / Initialization} \unprotect %D Loading lua code can be done using \type {startup.lua}. The following %D method uses the \TEX\ input file locator of kpse. At least we need to %D use that way of loading when we haven't yet define our own code, which %D we keep outside the format. We will keep code outside \TEX\ files as %D much as possible. \ifdefined\setnaturalcatcodes \else \let\setnaturalcatcodes\relax \fi \ifdefined\obeylualines \else \let\obeylualines \relax \fi \ifdefined\obeyluatokens \else \let\obeyluatokens \relax \fi %D A few more goodies: \let\stoplua \relax % tex catcodes \let\stopluacode\relax % lua catcodes % It might makes sense to have a \type {\directelua} so that we can avoid % the \type {\normalexpanded} around \type {\directlua}. Something to discuss % in the team. \unexpanded\def\startlua % \stoplua {\begingroup \obeylualines \luat_start_lua_indeed} \def\luat_start_lua_indeed#1\stoplua {\normalexpanded{\endgroup\noexpand\directlua{#1}}} % \zerocount is default \unexpanded\def\startluacode % \stopluacode {\begingroup \obeylualines \obeyluatokens \luat_start_lua_code_indeed} \def\luat_start_lua_code_indeed#1\stopluacode {\normalexpanded{\endgroup\noexpand\directlua{#1}}} % \zerocount is default %D Some delayed definitions: \ifdefined\obeylines \else \let\obeylines \relax \fi \ifdefined\obeyedline \else \let\obeyedline \relax \fi \ifdefined\obeyspaces \else \let\obeyspaces \relax \fi \ifdefined\obeyedspace \else \let\obeyedspace \relax \fi \let\obeylualines\relax \newtoks\everyluacode \edef\lua_letter_backslash{\string\\} \edef\lua_letter_bar {\string\|} \edef\lua_letter_dash {\string\-} \edef\lua_letter_lparent {\string\(} \edef\lua_letter_rparent {\string\)} \edef\lua_letter_lbrace {\string\{} \edef\lua_letter_rbrace {\string\}} \edef\lua_letter_squote {\string\'} \edef\lua_letter_dquote {\string\"} \edef\lua_letter_n {\string\n} \edef\lua_letter_r {\string\r} \edef\lua_letter_f {\string\f} \edef\lua_letter_t {\string\t} \edef\lua_letter_a {\string\a} \edef\lua_letter_b {\string\b} \edef\lua_letter_v {\string\v} \edef\lua_letter_s {\string\s} \edef\lua_letter_one {\string\1} \edef\lua_letter_two {\string\2} \edef\lua_letter_three {\string\3} \edef\lua_letter_four {\string\4} \edef\lua_letter_five {\string\5} \edef\lua_letter_six {\string\6} \edef\lua_letter_seven {\string\7} \edef\lua_letter_eight {\string\8} \edef\lua_letter_nine {\string\9} \edef\lua_letter_zero {\string\0} \appendtoks \let\\\lua_letter_backslash \let\|\lua_letter_bar \let\-\lua_letter_dash \let\(\lua_letter_lparent \let\)\lua_letter_rparent \let\{\lua_letter_lbrace \let\}\lua_letter_rbrace \let\'\lua_letter_squote \let\"\lua_letter_dquote \let\n\lua_letter_n \let\r\lua_letter_r \let\f\lua_letter_f \let\t\lua_letter_t \let\a\lua_letter_a \let\b\lua_letter_b \let\v\lua_letter_v \let\s\lua_letter_s \let\1\lua_letter_one \let\2\lua_letter_two \let\3\lua_letter_three \let\4\lua_letter_four \let\5\lua_letter_five \let\6\lua_letter_six \let\7\lua_letter_seven \let\8\lua_letter_eight \let\9\lua_letter_nine \let\0\lua_letter_zero \to \everyluacode \unexpanded\def\obeyluatokens {\setcatcodetable\luacatcodes \the\everyluacode} \edef\luamajorversion{\ctxwrite{_MINORVERSION}} \edef\luaminorversion{\ctxwrite{_MAJORVERSION}} %D \macros %D {definenamedlua} %D %D We provide an interface for defining instances: \def\s!lua{lua} \def\v!code{code} \def\!!name{name} \def\s!data{data} %D Beware: because \type {\expanded} is een convert command, the error %D message will show \type{} as part of the message. \installcorenamespace{luacode} \unexpanded\def\luat_start_named_lua_code#1% {\begingroup \obeylualines \obeyluatokens \csname\??luacode#1\endcsname} \unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet / we could use numbers instead (more efficient) {\ifcsname\??luacode#1\endcsname \else \scratchcounter\ctxlua{lua.registername("#1","#3")}% \normalexpanded{\xdef\csname\??luacode#1\endcsname##1\csname\e!stop#1\v!code\endcsname}% %{\endgroup\noexpand\directlua\the\scratchcounter{local _ENV=protect("#1\s!data")##1}}% {\noexpand\normalexpanded{\endgroup\noexpand\directlua\the\scratchcounter{local _ENV=protect("#1\s!data")##1}}}% \expandafter\edef\csname\e!start#1\v!code\endcsname {\luat_start_named_lua_code{#1}}% \expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{local _ENV=protect("#1\s!data")##1}}% \fi} %D We predefine a few. % \definenamedlua[module][module instance] % not needed \definenamedlua[user] [private user instance] \definenamedlua[third] [third party module instance] \definenamedlua[isolated][isolated instance] %D In practice this works out as follows: %D %D \startbuffer %D \startluacode %D context("LUA") %D \stopluacode %D %D \startusercode %D global.context("USER 1") %D context.par() %D context("USER 2") %D context.par() %D if characters then %D context("ACCESS directly") %D elseif global.characters then %D context("ACCESS via global") %D else %D context("NO ACCESS at all") %D end %D context.par() %D if bogus then %D context("ACCESS directly") %D elseif global.bogus then %D context("ACCESS via global") %D else %D context("NO ACCESS at all") %D end %D context.par() %D \stopusercode %D \stopbuffer %D %D \typebuffer %D We need a way to pass strings safely to \LUA\ without the %D need for tricky escaping. Compare: %D %D \starttyping %D \ctxlua {something("anything tricky can go here")} %D \ctxlua {something([\luastringsep[anything tricky can go here]\luastringsep])} %D \stoptyping \def\luastringsep{===} % this permits \typefile{self} otherwise nested b/e sep problems \edef\!!bs{[\luastringsep[} \edef\!!es{]\luastringsep]} %D We have a the following available as primitive so there is no need %D for it: %D %D \starttyping %D \long\edef\luaescapestring#1{\!!bs#1\!!es} %D \stoptyping \def\setdocumentfilename #1#2{\ctxlua{document.setfilename(#1,"#2")}} \def\setdocumentargument #1#2{\ctxlua{document.setargument("#1","#2")}} \def\setdocumentargumentdefault#1#2{\ctxlua{document.setdefaultargument("#1","#2")}} \def\getdocumentfilename #1{\ctxlua{document.getfilename("#1")}} \def\getdocumentargument #1{\ctxlua{document.getargument("#1")}} \def\getdocumentargumentdefault#1#2{\ctxlua{document.getargument("#1","#2")}} \def\doifdocumentargumentelse #1{\doifsomethingelse{\getdocumentargument{#1}}} \def\doifdocumentargument #1{\doifsomething {\getdocumentargument{#1}}} \def\doifnotdocumentargument #1{\doifnothing {\getdocumentargument{#1}}} \def\doifdocumentfilenameelse #1{\doifsomethingelse{\getdocumentfilename{#1}}} \def\doifdocumentfilename #1{\doifsomething {\getdocumentfilename{#1}}} \def\doifnotdocumentfilename #1{\doifnothing {\getdocumentfilename{#1}}} \let\doifelsedocumentargument\doifdocumentargumentelse %D A handy helper: \def\luaexpanded#1{\luaescapestring\expandafter{\normalexpanded{#1}}} %D Experimental: \unexpanded\def\startluaparameterset[#1]% {\begingroup \obeylualines \obeyluatokens \luat_start_lua_parameter_set{#1}} \def\luat_start_lua_parameter_set#1#2\stopluaparameterset {\ctxlua{parametersets["#1"]={#2}}% \endgroup} \let\stopluaparameterset\relax \def\luaparameterset#1#2{\ctxlua{parametersets["#1"]={#2} context("#1")}} % todo: \mergeparameterset % usage: % % \startluaparameterset [u3d:myset:display:1] % toolbar=false, % tree=true % \stopluaparameterset % % option=u3d:myset:display:1 % % or: % % option=\luaparameterset{u3d:myset:display:1}{toolbar=false,tree=true} %D A Handy helper: \def\luaconditional#1{\ifcase#1tru\else fals\fi e} %D Goodie: %D %D \starttyping %D \ctxluacode{context("%0.5f",1/3)} %D \stoptyping \unexpanded\def\ctxluacode {\begingroup \obeylualines \obeyluatokens \catcode\leftbraceasciicode \plusone \catcode\rightbraceasciicode\plustwo \afterassignment\luat_lua_code \scratchtoks=} % Hm, are we sure that the \* commands work out okay here? We could probably % use \setcatcodetable\luacatcodes instead of \obeyluatokens now. \def\luat_lua_code {\normalexpanded{\endgroup\noexpand\directlua\expandafter{\the\scratchtoks}}} % \zerocount is default \protect \endinput