So schreiben Sie eine Tex-Datei mit Lua neu

So schreiben Sie eine Tex-Datei mit Lua neu

Ich versuche das Problem mit $und $$in Formeln zu lösen, indem ich eine automatische Markierung dieser Formeln vornehme, einschließlich der Einfügung in den Strukturbaum. Die Variante mit \grabinlineoder \grabdisplayfunktioniert bei mir nicht, da ich equationbeispielsweise beim Versuch, zu verwenden, eine Fehlermeldung erhalte. Kürzlich habe ich gelesen, dass ich über mit meinen eigenen Dateien arbeiten kann lualatex. Zuerst habe ich versucht, einfach $$und zu ersetzen, $wenn davor kein Zeichen steht \, aber das funktioniert nicht nur nicht, sondern meine Datei ist beschädigt, wenn ich versuche, sie neu zu schreiben, d. h. es werden neue seltsame Zeilen hinzugefügt.

Helfen Sie mir bitte, wie ich dieses Problem beheben kann. Ich meine das Problem mit der Beschädigung der Datei und erklären Sie mir bitte, warum das passiert.

test.tex

\documentclass{article}
\directlua{require("test.lua")}
\pagestyle{empty}
\begin{document}
test
$$a+b=a^b$$ $a-b=a/b$
\end{document}

test.lua

f=io.open(tex.jobname..".tex","r+")
lines=f:lines()
for line in lines do
line=line:gsub("([^\\]?)$$(.+-)$$","%1\\[%2\\]")
line=line:gsub("([^\\]?)$(.+-)$","%1\\(%2\\)")
texio.write_nl("line of file "..line)
f:write(line)
end
f:close()

Antwort1

Das Problem hat nichts mit TeX zu tun, es ist ein allgemeines Problem beim Lesen und Schreiben derselben Datei. Was ist also los?

Die Ausgabe, die Sie wahrscheinlich erhalten, ist

\documentclass{article}
\documentclass{article}t.lua")}
t.lua")}le{empty}
le{empty}cument}
cument}a+b=a^b$$ $a-b=a/b$
a+b=a^b$$ $a-b=a/b$

Dies liegt daran, dass Sie sich nach dem Öffnen Ihrer Originaldatei beim ersten Byte der ersten Zeile befinden. Dann lineslesen Sie mit die erste Zeile: \documentclass{article}. Danach ist Ihre Position in der Zeile der Anfang der zweiten Zeile. Hier geben Sie ein f:write, sodass die erste, unveränderte Zeile an die aktuelle Position in der Datei geschrieben wird, also in die zweite Zeile. Sie überschreibt den vorhandenen Inhalt.

Die Datei enthält jetzt:

\documentclass{article}
\documentclass{article}t.lua")}
\pagestyle{empty}
\begin{document}
test
$$a+b=a^b$$ $a-b=a/b$
\end{document}

und Ihre aktuelle Position ist am Ende der zweiten \documentclass{article}. Jetzt liest Ihre nächste linesIteration den Rest der Zeile, sodass Sie erhalten t.lua")}. Dann sind Sie am Anfang der dritten Zeile und überschreiben diese mit dem gerade gelesenen Text, sodass Sie erhalten

documentclass{article}
\documentclass{article}t.lua")}
t.lua")}le{empty}
\begin{document}
test
$$a+b=a^b$$ $a-b=a/b$
\end{document}

Dies wird für jede Zeile wiederholt, bis Sie die beobachtete Datei erhalten.

Welche Lektion können Sie hieraus lernen: Überschreiben Sie keine Datei, während Sie diese noch lesen!

Im Gegensatz dazu gibt es in anderen Programmiersprachen Funktionen, wie Python mit readlines, die auf den ersten Blick ähnlich aussehen wie Luas io.lines. Aber Python readlinesliest beispielsweise alle Zeilen direkt in ein Array ein, während Lua bei jedem Schleifendurchlauf immer nur eine Zeile auf einmal liest. Bei ähnlichem Code treten dort also nicht ganz so offensichtliche Probleme auf, weil Lesen und Schreiben klar getrennt sind: Lesen nur während readline, Schreiben danach.

Das Neuschreiben Ihrer TeX-Quelldatei während der Ausführung von TeX ist jedoch sehr gefährlich und außerdem nicht kompatibel (Windows ist beim Bearbeiten geöffneter Dateien sensibel).

Es ist viel sicherer und einfacher zu verwenden, process_input_bufferwenn Sie jeweils nur eine Zeile ändern möchten. Sie können verwenden, status.input_ptrum nur Zeilen aus bestimmten Dateien zu beeinflussen: (Ich habe das Muster dabei korrigiert)

luatexbase.add_to_callback("process_input_buffer", function(line)
  if status.input_ptr ~= 1 then return end -- Only change lines of the main file
  texio.write_nl("line of file "..line)
  print(line:match("([^\\]?)$$(.-)$%$"))
  return line:gsub("([^\\]?)$$(.-)$%$","%1\\[%2\\]")
             :gsub("([^\\]?)$(.-)%$","%1\\(%2\\)")
end, "my_math_rewrite")

Auch wenn dies viel weniger gefährlich ist, würde ich dennoch empfehlen, nach Möglichkeiten zu suchen, Ihre Ziele zu erreichen, ohne die Eingabezeilen neu schreiben zu müssen.

Antwort2

(etwas spät zur Party, aber hoffentlich immer noch nützlich)

Hier ist eine Lösung, die keine neue Textdatei erstellt. Stattdessen arbeitet sie „on the fly“, im Wesentlichen wie ein Präprozessor, und ersetzt passende Paare von $$bzw. $durch ihre von LaTeX bevorzugten Ausdrücke: Dies geschiehtVorTeX beginnt mit seiner üblichen Arbeit, dem Erweitern von Makros usw.

Das Erstellen einer neuen Ausgabetextdatei zum Ausgeben des im laufenden Betrieb geänderten Inhalts der Eingabedatei bleibt eine separate Übung.

Um dies vom Proof-of-Concept-Stadium zu etwas zu bringen, das für die Arbeit in der Praxis ausreichend robust sein könnte, müsste man sicherlich auch Code hinzufügen, um zu testen, ob das vom Präprozessor untersuchte Material zufällig im Verbatim-Modus vorliegt oder in einer URL-Zeichenfolge enthalten ist. In diesen und ähnlichen Fällen sollten keine Ersetzungen vorgenommen werden, oder?

Bildbeschreibung hier eingeben

% !TEX TS-program = lualatex

%% Create external file to store Lua code:
\RequirePackage{filecontents}
\begin{filecontents*}{test.lua}
function substitute_dollar_symbols ( line )
    line = line:gsub ( "([^\\]?)$$(.+-)$$" , "%1\\[%2\\]" )
    line = line:gsub ( "([^\\]?)$(.+-)$"   , "%1\\(%2\\)" )
    return line
end
\end{filecontents*}

\documentclass{article}
%% Load Lua code from external file:
\directlua{require("test.lua")}

%% Create two LaTeX utility macros to (a) assign Lua 
%% function to the "process_input_buffer" callback 
%% and (b) remove the function from that callback:
\newcommand\SubstituteDollarSymbolsOn{%
  \directlua{luatexbase.add_to_callback (
    "process_input_buffer", 
    substitute_dollar_symbols , 
    "substitute_dollar_symbols" )}}
\newcommand\SubstituteDollarSymbolsOff{%
  \directlua{luatexbase.remove_from_callback (
    "process_input_buffer",
    "substitute_dollar_symbols" )}}

%% Activate the Lua function at start of document:
\AtBeginDocument{\SubstituteDollarSymbolsOn}

\begin{document}
test
$$a+b=a^b$$ $a-b=a/b$ % $$ $
abc $$uvw$$
\end{document}

verwandte Informationen