I'm quite new to this language and can't figure out the error in following code. Any help would be appreciated !



u := 10mm;
v := 0.8u;

for i=1 upto 5:
    pickup pensquare scaled 0.6pt;
    draw (-v*i,-0.1u)..(-v*i,0.1u)
        withcolor(0.5, 0.5, 0.5);
    draw (v*i,-0.1u)..(v*i,0.1u)
        withcolor(0.5, 0.5, 0.5);

    label.bot(textext("$" & (decimal (-v*i)) & "$"), (-v*i, -0.2u))
        withcolor(0.5, 0.5, 0.5);
    label.bot(textext("$" & (decimal (v*i)) & "$"), (v*i, -0.2u))
        withcolor(0.5, 0.5, 0.5);


gives following error:

! Missing `,' has been inserted.
<to be read again> 
<for(1)> ...hcolor(0.5,0.5,0.5);label.bot(textext(
l.59     endfor
  • Where is textext defined? – Andrew Swann Jan 21 at 7:58
  • textext is a MetaFun macro, so you have to process the file with mpost '&metafun' test.mp. Unfortunately, the output will only contain “unknown”. I asked on the mailing list why this is happening: mailman.ntg.nl/pipermail/ntg-context/2019/093806.html – Henri Menke Jan 21 at 7:59
  • @AndrewSwann I think it is part of metafun, which is part of ConTeXt. – flowian Jan 21 at 8:00
  • It is also in latexmp, perhaps that has not been loaded. – Andrew Swann Jan 21 at 8:01
  • How are you compiling the document? – Aditya Jan 21 at 13:18

The error

The "some reason" is that in your MWE (as given) the textext macro is not defined, so MetaPost reads "textext" as a variable name token instead, in the hope that it will be able to expand it into an appropriate parameter for the label macro. When the tokenizer gets to the ( token, it can't add this to the variable name token that it's just read in any legal way, so it assigns the token to the first parameter for label and moves on to look for the next parameter. But label is defined (in plain.mp) with a comma token to separate the parameters, so the next thing in the input should be a , but it in fact is is a (. At this point the tokenizer admits defeat and throws the error that you see.

What can you do about it?

  1. As you have already discovered you can abandon textext altogether and just get a plain label. But that's a bit disappointing because it means the negative numbers in your loop get hyphens instead of mathematical minus signs (see the hack below for a quick way round this).

  2. As suggested in the comments, you can call mpost with the &metafun option so that it loads all the useful macros written for Context, including textext().

  3. You can put "input TEX" at the top of your program, and then replace your calls to textext() with calls to TEX() -- this works with plain mpost

  4. You can wrap your code up in an mplib shell like this, with the immensely useful \mplibtextextlabel{enable} option and compile with lualatex:

    u := 10mm; v := 0.8u;
    drawoptions(withcolor 1/2 white);
    for i=-5 upto 5:
        if i <> 0:
            draw (v*i, -1/10 u) .. (v*i, 1/10 u);
            label.bot("$" & decimal i & "$", (v*i, -1/5 u));
    draw (left--right) scaled 5.5v;

    (I made a couple of trivial tidy-ups...). Notice that this has the (great) advantage that you don't need a verbatimtex block. You just put your normal latex preamble in, to get: enter image description here

You may be able to guess by now that I would recommend option 4.

The promised hack

If you want to stick with plain MP, but you still want typographical minus signs in a loop, then here is a hack. First you need to choose a default font that is not cmr10. If you want Computer Modern then do

defaultfont := "texnansi-lmr10";  % for Computer Modern Roman

if you want Times (as in the OP) then do

defaultfont := "ptmr8r";

then you can try the following:

string minus_sign;
minus_sign := char 143; % if you are using the texnansi encoding
minus_sign := char 12;  % if you are using the 8r encoding
for x=-10 upto 10: 
   label(if x<0: minus_sign & fi decimal abs(x), (x*u,-5)); 

This is similar in spirit to Thruston's answer, but uses ConTeXt (rather than LaTeX). ConTeXt can directly compile Metapost files using

context filename.mp

provided you don't have any latexism in your code. This is roughly equivalent to compiling a ConTeXt document


So, if you want to change fonts etc., you can set a ConTeXt environment with all the relevant setups, and then run

context --environment=<name-of-environment-file> <name-of-mp-file>
  • I was thinking about this as well (of course) but keep in mind that OP is using the mathptmx package. I don't know whether there is an equivalent in ConTeXt. – Henri Menke Jan 21 at 20:30
  • Isn't \setupbodyfont[pagella] functionally equivalent? – Aditya Jan 21 at 21:24
  • It's more similar to TeX Gyre Termes but not quite the same and only applies to math mode. – Henri Menke Jan 21 at 22:09

For some reason textext caused the problem.

Following simple label worked well inside for cycle.

label.bot(decimal (-0.8*i), (-v*i, -0.2u))

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.