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

2
  • 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
    Commented May 13, 2018 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
    Commented May 14, 2018 at 9:54

1 Answer 1

2

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}
2
  • Thank you. But what is the meaning of the double braces: [[#1]] ?
    – Nik
    Commented May 14, 2018 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. Commented May 14, 2018 at 14:56

You must log in to answer this question.

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