Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Can anyone explain why the macro \makequesone below fails and/or suggest a fix? The verbatim option works (as in the MWE) but I would like the content of the argument to be able to contain relatively arbitrary text and mathematical content so I don't think the verbatim option is ideal.

The basic point is to store a list of questions in a lua table, and then to generate exams by randomly selecting questions from the bank. Right now, I'm just getting the storage retrieval part working.

The fourth argument will contain an exam question and I have the understanding that \luatexluaescapestring should be used to prevent bad things from happening. In the working code below, I used a v type argument, but using an m type argument and just storing the args in token lists and doing nothing with them generates no errors, so I have the feeling that the issue is with \luatexluaescapestring which doesn't seem to like a \par somewhere. A "fix" would allow me to pass the content of that 4th argument to lua relatively freely and to retrieve it with \getquestion. In either case, an explanation of what's going on would be nice :)

\documentclass{article}
\usepackage{xparse}
\usepackage{luacode}
\begin{luacode*}

cats = {}
function makequestion(c,id,pt,q)
    -- if question category doesn't exist, then create a table for it
    if not cats[c] then 
      cats[c] = {}
    end
    -- add new question with tag "id" to category "c" table.
    -- question worth "pt" points, and has content "q"
    -- some questions may have entries for the parts subtable
    cats[c][id]={points = pt, ques = q, parts = {}}
end

function getquestion (c,id)
    tex.sprint(cats[c][id].ques)
end

\end{luacode*}

% Adds a question of category #1 and question id #2 to the table.
% the question point value is #3 and the actual question is #4.
% in use, there will be a 5th field for question parts.
% 
% #1 = category
% #2 = id
% #3 = points
% #4 = question

\NewDocumentCommand{\makequesone}{ m m m +m }
    {
        \directlua{makequestion("\luatexluaescapestring{#1}","\luatexluaescapestring{#2}","\luatexluaescapestring{#3}","\luatexluaescapestring{#4}")}
    }

\NewDocumentCommand{\makequestwo}{ m m m v }
    {
        \directlua{makequestion("\luatexluaescapestring{#1}","\luatexluaescapestring{#2}","\luatexluaescapestring{#3}","\luatexluaescapestring{#4}")}
    }

\NewDocumentCommand{\getquestion} { m m }
    {
        \directlua{getquestion("\luatexluaescapestring{#1}","\luatexluaescapestring{#2}")}
    }

\begin{document}
hi
% fails
%\makequesone{factor}{id1}{1}{\begin{itemize}\item fish\end{itemize}}


% works
\makequestwo{factor}{id1}{1}!Here is my question \begin{itemize}\item fish\end{itemize}!

\getquestion{factor}{id1}

\end{document}
share|improve this question
    
If you use \unexpanded{#4} there will be no error; I can't say there's success, because I don't know what the thing is supposed to do and how to check for success/failure. –  egreg Oct 19 '12 at 6:48
    
@egreg I elaborated a bit, hopefully it's a little more clear now. –  Scott H. Oct 19 '12 at 8:06
    
Just some thoughts: I wouldn't give the string "Here is my ..." as an argument to Lua only to give it back later from Lua to TeX. Because you have to be careful to mask special chars on the way from TeX to Lua and you also have to mask some special chars on the way back from Lua to Tex. This could be tricky. An other reason is that you store every time the same string in Lua just with a small difference in it. I would give only the important value (fish) to Lua and create the output string in a separate function. Maybe here are other hints for you tex.stackexchange.com/a/55321/10570 –  Holle Oct 19 '12 at 14:22
    
Just some more thoughts: If it is not necessary to create the questions in the TeX-file it is easier to put all data (large strings) in a separate (.csv) file and just read the file via Lua and store all items in one table (something like this tex.stackexchange.com/a/41499/10570). So there is no need to mix up TeX and Lua (and vice versa) in such a way and the data is keep separated from form/design. –  Holle Oct 19 '12 at 14:49
    
@Holle, thanks for the tips! If don't mind, would you be able to elaborate a bit on "you also have to mask some special chars on the way back from Lua to Tex". What might come back from Lua that I would need to worry about? –  Scott H. Oct 19 '12 at 18:59
show 2 more comments

1 Answer

up vote 3 down vote accepted

Add \unexpanded: \directlua does macro expansion before passing the result to Lua. Also, be careful with spaces in macro definitions.

\NewDocumentCommand{\makequesone}{ m m m +m }
 {%
  \directlua{makequestion(%
    "\luatexluaescapestring{#1}",
    "\luatexluaescapestring{#2}",
    "\luatexluaescapestring{#3}",
    "\luatexluaescapestring{\unexpanded{#4}}")}%
 }
share|improve this answer
    
Thanks egreg, I keep forgetting that \directlua expands things. Thanks for the spaces advice as well....I had that all in \ExplSyntaxOn tags but deleted them without taking care of the spaces, that probably would have bit me a little later on :) –  Scott H. Oct 19 '12 at 18:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.