3

I encounter a problem when I wish to output a text file using a \directlua directive. There where I wish a newline character to be, I run into TeX problems. My solution is to invoke the dofile function to grab a string called myNLChar from an external Lua script. This string can be written to an output file, and it will be a true newline character.

File wrnl2of.lua:

myNLChar = "\n"

File wrnl2of.tex:

This Lua\TeX\ document does not typeset anything
interesting. It outputs a three-line text file
which contains newline characters.\par
\directlua0{
  local myOutFile   = "\jobname.txt"
  local myLuaScript = "\jobname.lua"
  dofile (myLuaScript)
  derDateiname = io.open (myOutFile, "w")
  derDateiname:write ("Alaska"     .. myNLChar)
  derDateiname:write ("California" .. myNLChar)
  derDateiname:write ("Nebraska"   .. myNLChar)
  derDateiname:close ()
}

Although this strategy functions well, I suspect that there are several more elegant solutions to the problem. I am eager to hear some suggestions.

  • 2
    I guess one method would be to externalise the entire Lua block to wrnl2of.lua and only dofile that script in \directlua. (Modulo some handling of \jobname ...) – moewe Jan 29 at 9:49
  • 2
    Why don't you use simply myNLChar="\string\n" in the directlua? (Or "Alaska\string\n". – Ulrike Fischer Jan 29 at 9:57
  • 1
    .. "\string\n" would also work, see mirrors.ctan.org/macros/luatex/latex/luacode/luacode.pdf, p. 2. But I think at a certain point it makes sense to use the .lua script approach. (edit I see Ulrike was quicker than me.) – moewe Jan 29 at 9:57
3

I'd just use \string here for a simple case

This Lua\TeX\ document does not typeset anything
interesting. It outputs a three-line text file
which contains newline characters.\par
\directlua{
  local myOutFile   = "\jobname.txt"
  local myNLChar = "\string\n"
  derDateiname = io.open (myOutFile, "w")
  derDateiname:write ("Alaska"     .. myNLChar)
  derDateiname:write ("California" .. myNLChar)
  derDateiname:write ("Nebraska"   .. myNLChar)
  derDateiname:close ()
}
\bye

You could also change the \catcode of backslash:

This Lua\TeX\ document does not typeset anything
interesting. It outputs a three-line text file
which contains newline characters.\par
\begingroup
\long\def\firstofone#1{#1}
\catcode`\/=0 %
\catcode`/\=12 %
/firstofone{%
/endgroup
/directlua{
  local myOutFile   = "/jobname.txt"
  local myNLChar = "\n"
  derDateiname = io.open (myOutFile, "w")
  derDateiname:write ("Alaska"     .. myNLChar)
  derDateiname:write ("California" .. myNLChar)
  derDateiname:write ("Nebraska"   .. myNLChar)
  derDateiname:close ()
}%
}
\bye

For any Lua code of any length, it's always going to be best to dofile() or require() it. That might look for example like

\begin{filecontents*}{\jobname.lua}
function derDateiname(myOutFile)
  local derDateiname = io.open(myOutFile, "w")
  derDateiname:write("Alaska"     .. "\n")
  derDateiname:write("California" .. "\n")
  derDateiname:write("Nebraska"   .. "\n")
  derDateiname:close()
end
\end{filecontents*}
\documentclass{article}
\begin{document}
This Lua\TeX\ document does not typeset anything
interesting. It outputs a three-line text file
which contains newline characters.\par
\directlua{
  require("\jobname.lua")
  derDateiname("\jobname")
}
\end{document}
  • I'd just been editing my post when the comments appeared on the question: I've made CW to avoid any 'rep farming.' – Joseph Wright Jan 29 at 10:06
  • Imho someone who makes the effort and takes the time to write up a so detailed answer deserves also the reputation - it doesn't matter to me if parts of your answer are in the comments and if you saw or didn't saw them before posting. (And I would never suspect you of rep farming anyway). – Ulrike Fischer Jan 29 at 10:18

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.