2

I've read More than one optional argument for newcommand and I chose the answer with xargs. I would like to pass a second optional argument to the Lua function. But the first of the two commented \drawLUAline lines leads to the error:

./d.tex:39: Package pgfkeys Error: I do not know the key '/tikz/midway {A}' and I am going to ignore it. Perhaps you misspelled it.

Of course, I can here just add the second optional part as I did, but I want to know how to do this right for other cases. And for me the syntax with the double brackets for the optional arguments is not clear.

\documentclass[preview]{standalone}
\usepackage{xargs}
\usepackage{luacode}
\usepackage{tikz}


\begin{document}

\begin{luacode*}
function print_line (x, y, optA, optB)

  -- optA: yes
  if optA~=[[]] then
    tex.sprint("\\draw["..optA.."] (0,0) -- ("..x..","..y..")")
  end

  -- optA: no
  if optA==[[]]  then
    tex.sprint("\\draw (0,0) -- ("..x..","..y..")")
  end

 -- optB: yes
 if optB ~=[[]] then
   tex.sprint(""..optB.."")
 end

end
\end{luacode*}

\newcommandx{\drawLUAline}[4][1, 4]{% 
\directlua{print_line(#2,#3,[[#1]],[[#4]])}
}

\begin{tikzpicture} 
\draw (0,0) grid (3,4);
\drawLUAline{3}{1};
\drawLUAline[red]{3}{2};
\drawLUAline[blue]{3}{2.5} node[midway]{A};
%\drawLUAline[green]{3}{3}[node[midway]{A}]; 
%\drawLUAline{3}{4}[node[midway]{A}];
\end{tikzpicture}
\end{document}

enter image description here

  • Just out of curiosity: Wouldn't it be easier/less cumbersome to specify a Lua function with 4 arguments, with tests for args 3 and/or 4 being empty (and supplying default values if the args are indeed empty)? This Lua function would be invoked by a LaTeX macro whose 3rd and/or 4th args could be empty, say, \drawLUAline{3}{1}{}{}, \drawLUAline{3}{2}{red}{}, and \drawLUAline{3}{3}{green}{"node[midway]{A}"}. – Mico May 13 '18 at 18:51
  • Of course may be there are better ways. But I would like to be able to choose the best way. So I need information about the choices. That's why I asked my question. – Nik May 14 '18 at 9:54
3

The package xargs does not support nested brackets, so a optional arguments ends at the first ]. In your example this means, that for

\drawLUAline[green]{3}{3}[node[midway]{A}];
%                                    ^ This bracket ends the argument

the second optional argument is node[midway. Then the {A}] comes after the macro, so TikZ sees node[midway{A}] which leads to the error. You could avoid this by writing braces around the argument, so call the macro with

\drawLUAline[green]{3}{3}[{node[midway]{A}}];
%                         ^               ^ These "hide" the ].

instead.

If you want your macro to accept the argument without these additional braces, you can use xparse instead:

\documentclass[preview]{standalone}
\usepackage{xparse}
\usepackage{luacode}
\usepackage{tikz}


\begin{document}

\begin{luacode*}
function print_line (x, y, optA, optB)

  -- optA: yes
  if optA~=[[]] then
    tex.sprint("\\draw["..optA.."] (0,0) -- ("..x..","..y..")")
  end

  -- optA: no
  if optA==[[]]  then
    tex.sprint("\\draw (0,0) -- ("..x..","..y..")")
  end

 -- optB: yes
 if optB ~=[[]] then
   tex.sprint(""..optB.."")
 end

end
\end{luacode*}

\NewDocumentCommand{\drawLUAline}{O{} m m O{}}{% 
\directlua{print_line(#2,#3,[[#1]],[[#4]])}
}

\begin{tikzpicture} 
\draw (0,0) grid (3,4);
\drawLUAline{3}{1};
\drawLUAline[red]{3}{2};
\drawLUAline[blue]{3}{2.5} node[midway]{A};
\drawLUAline[green]{3}{3}[node[midway]{A}]; 
\drawLUAline{3}{4}[node[midway]{A}];
\end{tikzpicture}
\end{document}

While this works, there is another problem hidden in this code: Using [[#1]] etc. is unsafe. Especially if the argument could end with a ] or contain ]] this leads to weird errors. Use normal quotes and \luaescapestring instead:

\documentclass[preview]{standalone}
\usepackage{xparse}
\usepackage{luacode}
\usepackage{tikz}


\begin{document}

\begin{luacode*}
function print_line (x, y, optA, optB)

  -- optA: yes
  if optA~="" then
    tex.sprint("\\draw["..optA.."] (0,0) -- ("..x..","..y..")")
  end

  -- optA: no
  if optA==""  then
    tex.sprint("\\draw (0,0) -- ("..x..","..y..")")
  end

 -- optB: yes
 if optB ~= "" then
   tex.sprint(""..optB.."")
 end

end
\end{luacode*}

\NewDocumentCommand{\drawLUAline}{O{} m m O{}}{% 
\directlua{print_line(#2,#3,"\luaescapestring{#1}","\luaescapestring{#4}")}%
}

\begin{tikzpicture} 
\draw (0,0) grid (3,4);
\drawLUAline{3}{1};
\drawLUAline[red]{3}{2};
\drawLUAline[blue]{3}{2.5} node[midway]{A};
\drawLUAline[green]{3}{3}[node[midway]{A}]; 
\drawLUAline{3}{4}[node[midway]{A}];
\end{tikzpicture}
\end{document}
  • Thank you. But what is the meaning of the double braces: [[#1]] ? – Nik May 14 '18 at 9:46
  • @Nik You find more information about the double square brackets at lua.org/pil/2.4.html. They mark string literals, similar to quotation marks. In contrast to quotation marks, no escape sequences are interpreted between them and they can be used for multi-line string literals. – Marcel Krüger May 14 '18 at 14:56

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.