%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{<inserted text>} 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
