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.

3
  • 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
    Commented Oct 27, 2018 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
    Commented Oct 27, 2018 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
    Commented Oct 27, 2018 at 15:46

1 Answer 1

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .