0

I am designing pseudo-crosswords for my pupils exercices with the following macro:

\startMPinclusions
% could'nt achieve using the word string length as a first parameter
vardef MotMystere (expr taille,speciale,index) =
   numeric avant,apres;
   path case;
   case:= fullsquare scaled 13;
   avant=speciale-1;
   apres=taille-speciale;
   if avant >= 1:
      for j=1 upto avant:
         draw (case rotated 180
            cutafter point 3 of case rotated 180)
            shifted (-13j,-13*index);
      endfor;
   fi;
   label.lft (index,point 3.5 of 
      case shifted (-13*avant,-13*index));
   draw case yshifted (-13*index);
   fill case yshifted (-13*index)
      withcolor \MPcolor{gray-8};
   if apres > 0:
      for j=1 upto apres:
         draw (case cutafter point 3 of case) 
            shifted (13j,-13*index);
      endfor;
   fi;
enddef;
\stopMPinclusions
\starttext
An example with "enigma"

\startMPcode
MotMystere(6,4,1)
\stopMPcode
\stoptext

I tried to spare some error-prone counts using string.len(). The idea would be to give the word as a first parameter, instead of its manually counted string length, eg MotMystere("enigma",4,1). However I couldn't figure out how should I pass this string parameter to the lua function.

1 Answer 1

2

When in ASCII mode, MetaPost's length should suffice. Otherwise, you might need to use utflen:

\startMPinclusions
vardef MotMystere(expr taille, speciale, index) =
    save avant,apres,case; 
    numeric avant,apres;
    path case;
    case  := fullsquare scaled 13;
    avant := speciale-1;
    %Use parentheses to avoid issues in LMTX
    apres := (length(taille)) - speciale;
   if avant >= 1:
        for j=1 upto avant:
            draw (case rotated 180
            cutafter point 3 of case rotated 180)
            shifted (-13j,-13*index);
      endfor;
   fi;
    label.lft (index,point 3.5 of 
    case shifted (-13*avant,-13*index));
    draw case yshifted (-13*index);
    fill case yshifted (-13*index)
        withcolor \MPcolor{gray-8};
    if apres > 0:
        for j=1 upto apres:
            draw (case cutafter point 3 of case) 
                shifted (13j,-13*index);
        endfor;
    fi;
enddef;
\stopMPinclusions
\starttext
An example with "enigma"

\startMPcode
MotMystere("enigma",4,1)
\stopMPcode
\stoptext

As you ask about the way Lua handles your string, Lua (>=5.3) provides an utf8 library with utf8.len returning the length of an Unicode strings. Additionally, LuaTeX and LuaMetaTeX provide string.utflength and ConTeXt is smart enough to choose either of the functions when available. Although you're able to define your own Unicode functions from Lua and then make them visible to MetaPost, the following are already defined in ConTeXt (mp-luas.mpiv or mp-luas.mpxl): utflen, utfnum and utfsub. See the example below:

\startMPpage
%If any of those doesn't work, just add parentheses until Hans fixes it
string Oracion;
Oracion := "El Perú será grande, el Perú será lo que debe ser, si todos los peruanos nos resolvemos a engrandecerlo.";
draw thetextext(utflen(Oracion),1cm*up);
draw thetextext(utfsub(Oracion,1,19),origin);
draw thetextext(utfnum("Ñ"),1cm*down); %0xD1=209
\stopMPpage

enter image description here

2
  • Thanks for the hint; I didn't know length works also for strings. However I am dealing with UTF-8. I don't have the latest LMTX, so maybe utflen works there. However I'd be interested in an alternative additition involving lua's string.len(), since a better knowledge of metapost/lua interfacing in macros should be useful in the future.
    – sztruks
    Oct 4, 2021 at 6:24
  • 1
    @sztruks Metafun's utflen is based on Lua's string.len (actually utf.len for Unicode strings in ConTeXt)! 😅 You can see the relevant definitions within mp-luas.mpiv and mlib-mpf.lua in case you're interested
    – user226564
    Oct 4, 2021 at 6:36

You must log in to answer this question.

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