2

I've been trying to write a piece of ConTeXt code that fills in a persistent lua array with variables parsed from the ConTeXt end, but for some reason it appears as though every \question{}{}{} call gets executed twice, resulting in the array having twice total value it should, and being twice as long as it should be. Is this expected behaviour, and I've just not understood how ConTeXt parses lua code, or is there a bug I can't see?

\setuppapersize[A4]
\usepath[Assets]

\startluacode
    userdata = userdata or {}

    qVals={}
    table.reduce = function (list, fn)
        local acc
        for k, v in ipairs(list) do
            if 1== k then
                acc = v
            else
                acc = fn(acc, v)
            end
        end
        return acc
    end

    local sumT = function (a, b)
        return a +b
    end

    function userdata.getQval(weight, question)
        qVals[#qVals+1]=tonumber(weight)
        tot = table.reduce(qVals, sumT)
        context("(" .. weight .. " points) " .. question .. " " .. tot)
    end
\stopluacode

\defineenumeration[questionEnumeration]
[
    text={},
    title=yes,
    titlestyle=bold,
    titleright={},
    titleleft={},
]

\def\getQuestionVal#1#2{%
    \ctxlua{userdata.getQval([==[#1]==], [==[#2]==])}%
}

\def\question#1#2#3{%
    \startquestionEnumeration[title=\getQuestionVal{#1}{#2}]
        \doifmodeelse{key}{\startcolor[red]#3\stopcolor}{\blank[#1*2em]}
    \stopquestionEnumeration
}

\starttext
    %\enablemode[key]

    \question{3}{This is the question}{this is its sol}
    \question{7}{Another question}{another sol}
    \question{5}{and another}{yet another sol}
\stoptext

P.S. I've figured out a work around that uses an incrementing number that gets rounded as the array indexing (thus overwritting duplicates) but I would prefer a true solution if it exists.

  • 1
    Your problem is that title= seemingly executes the code twice (maybe in between saving in a box?). Putting the \getQuestionVal outside of title= works. – TeXnician Oct 27 '18 at 7:16
  • Huh, you're right! That's neat. Though I don't understand why title= would cause the code to execute twice, and putting it just afterwards wouldn't? Shouldnt any updating that would cause code to be run twice be done everywhere? – anthsts Oct 27 '18 at 15:42
  • No, just where it's needed. Usually, these kinds of interaction are caused by saving the content in an intermediate box (i.e. typesetting it in a hidden box) to measure it (e.g. to get the width, height, depth). I don't know whether ConTeXt does this for title, but I guess so. – TeXnician Oct 27 '18 at 15:46
5

To get the correct dimensions for the title length when you use the width=fit setting for enumerations or descriptions ConTeXt has to do a trial run in the complete content of the title.

When you have now a case where a value is incremented with the title you have to use the trialtypesetting conditional or mode to prevent the value to be incremented.

\defineenumeration [question] [text=Question ,title=yes]

\definecounter[testcounter]

\starttext

\startquestion[title={Testcounter: \incrementedcounter[testcounter]}]
First question
\stopquestion

\startquestion[title={Testcounter: \incrementedcounter[testcounter]}]
Second question
\stopquestion

\startquestion[title={Testcounter: \iftrialtypesetting\else\incrementedcounter[testcounter]\fi}]
Third question
\stopquestion

\startquestion[title={Testcounter: \doifnotmode{*trialtypesetting}{\incrementedcounter[testcounter]}}]
Fourth question
\stopquestion

\stoptext

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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