Search code examples
stringlualatex

Matching and replacing newline character using Lua pattern patch


This is a follow up to a question I asked in the LaTeX community regarding how to format items in the itemize environment. It turns out I got a response to that question using lua, but now I want to extend the lua code so I have a more lua programming centered question.

The answer proposes using string.gsub to replace pattern-matched parts of the string to something else. For example, the below code:

s = string.gsub ( s , '\\sitem%s+(.+)' , '\\item\\makefirstuc{%1},' )

will replace \item hello world to \item\makefirstuc{hello world}.

Here's the problem though, sometimes I have new lines in the string after item, for instance:

\item hello
world

I would like to replace that with:

\item\makefirstuc hello world

Does anyone know how I can do that?

Edit

I just tried the solution proposed by Wiktor but it wouldn't work for the case:

\item hello
world
\end{itemize}

Here's a full script to demonstrate:

-- test.lua
s = "\\sitem  Hello\n\\end{itemize}"

print(s)

result = string.gsub ( s, '\\item%s+(.+)' , function(x) return 
    '\\item\\makefirstuc{' .. string.gsub(x, '\n', ' ') .. '},' 
end )
print("\nAfter gsub")
print(result)

The above script outputs

\sitem  Hello
\end{itemize}

After gsub
\sitem  Hello
\end{itemize}

But I want it to output:

\sitem  Hello
\end{itemize}

After gsub
\item\makefirstuc {Hello},
\end{itemize}

Solution

  • You can use a function as a replacement argument:

    result = string.gsub ( s, '\\sitem%s+(.-)(\n\\)' , '\\item\\makefirstuc {%1},%2')
    

    See the online demo.

    Details:

    • \\sitem - a \sitem fixed string
    • %s+ - one or more whitespaces
    • (.-) - Group 1 (%1): any zero or more chars as few as possible
    • (\n\\) - Group 2 (%2): a newline and a \.