8

I have never tried to include Lua code in a document before so please be gentle. I am after a pattern matching expression that will eventually take (stuff1)->(stuff2) and replace it with !(stuff1)||(stuff2) but baby steps first...

At the bottom of this page: Programming In Lua is a mention of a pattern for matching balanced strings. After modifying some code I found on site I decided to try the following:

\documentclass{article}

\def\swap#1{%
    \directlua{%
      local s, _ = string.gsub("#1","%b()%b()","%2%1")
      tex.sprint(s)}
}

\begin{document}

\swap{(a)(b)}

\end{document}

Which does not work at all. Can anyone explain what I've done wrong?

Scott H.
  • 11,047

1 Answers1

12

The pattern %b()%b() does not contain captures, therefore %1 and %2 are not assigned. You need an additional pair of parentheses

(%b())(%b())

The next problem is that the percent character is a comment character in TeX usually. There are lots of ways to deal with this, the example below defines the string with the percent chars separately in a group where the catcode of the percent char is changed to the catcode of symbols like digits. See also package luacode.

Using "#1" is risky, #1 might contain stuff that breaks the syntax of the string. Therefore I have added \luatexluaescapestring (the name in LuaLaTeX for \luaescapestring).

\documentclass{article}

\begingroup
  \catcode`\%=12\relax
  \gdef\swapgsubargs{"(%b())(%b())","%2%1"}
\endgroup
\def\swap#1{%
  \directlua{%
    local s, _ = string.gsub("\luatexluaescapestring{#1}",\swapgsubargs)
    tex.sprint(s)%
  }%
}

\begin{document}

\swap{(a)(b)}

\end{document}

Result

Heiko Oberdiek
  • 271,626
  • Thank you kindly, that helps to clear up a number of misunderstandings I had (although I'm sure that there are many more). I'll have a look at the luacode package as well. – Scott H. Sep 15 '12 at 00:49
  • It is worth noting that \string\% is an easier way to get a percent character in a Lua string (it will be escaped by a backslash), so \swapgsubargs could be replaced by "(\string\%b())(\string\%b())","\string\%2\string\%1", avoiding any catcode change. – Bruno Le Floch Sep 03 '14 at 12:00
  • @BrunoLeFloch \string\% depends on the correct setting of \escapechar. Another alternative is LaTeX's \@percentchar. – Heiko Oberdiek Sep 03 '14 at 16:17
  • @HeikoOberdiek: You are right. – Bruno Le Floch Sep 04 '14 at 12:22