Cómo reescribir un archivo tex usando lua

Cómo reescribir un archivo tex usando lua

Intento resolver el problema con $y $$en fórmulas, para realizar el etiquetado automático de estas fórmulas, incluida la adición en el árbol de estructura. La variante con \grabinlineo \grabdisplayno me funciona porque me sale un error al intentar usar equation, por ejemplo. Recientemente leí que puedo trabajar con mis propios archivos mediante lualatex. Primero intenté simplemente reemplazar $$y $si no hay ningún \carácter antes, pero no solo no funciona, sino que mi archivo se corrompe cuando intento reescribirlo, es decir, agrega nuevas líneas extrañas.

Por favor ayúdenme, ¿cómo puedo solucionar este problema, me refiero al problema con la corrupción del archivo, y explíquenme por qué sucede?

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()

Respuesta1

El problema no está relacionado con TeX, es un problema general al leer y escribir el mismo archivo. ¿Entonces qué está pasando?

El resultado que probablemente obtenga es

\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$

Esto sucede porque después de abrir su archivo original, se encuentra en el primer byte de la primera línea. Luego usando lines, lees la primera línea: \documentclass{article}. Después de eso, tu posición en la línea es el comienzo de la segunda línea. Aquí usted emite f:write, por lo que la primera línea, sin modificar, se escribe en la posición actual en el archivo, que es la segunda línea. Sobrescribe el contenido existente.

Ahora, el archivo contiene:

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

y su posición actual está al final del segundo \documentclass{article}. Ahora tu próxima linesiteración lee el resto de la línea, por lo que obtienes t.lua")}. Luego estás al comienzo de la tercera línea y la sobrescribes con el texto recién leído, por lo que obtienes

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

Esto se repite para cada línea, hasta que obtenga el archivo que observó.

¿Qué lección puedes aprender aquí? ¡No sobrescribas un archivo mientras todavía lo estás leyendo!

Por el contrario, algunos otros lenguajes de programación contienen funciones, como Python con readlines, que a primera vista parecen similares a las de Lua io.lines. Pero, por ejemplo, Python readlineslee directamente todas las líneas en una matriz, mientras que Lua solo lee una línea a la vez en cada iteración del bucle. Por lo tanto, no aparecen problemas tan obvios con código similar porque la lectura y la escritura están claramente separadas: leer solo durante readliney escribir después.

De todos modos, reescribir su archivo fuente TeX durante la ejecución de TeX es muy peligroso y tampoco es compatible (Windows es sensato cuando se trata de editar archivos abiertos).

Es mucho más seguro y fácil de usar process_input_buffersi sólo desea cambiar una línea a la vez. Puedes usarlo status.input_ptrpara afectar solo líneas de archivos específicos: (arreglé el patrón en el proceso)

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")

Incluso si esto es mucho menos peligroso, recomendaría buscar formas de archivar sus objetivos sin reescribir las líneas de entrada.

Respuesta2

(un poco tarde para la fiesta, pero espero que siga siendo útil)

Aquí hay una solución que no crea un nuevo archivo de texto. En cambio, funciona "sobre la marcha", esencialmente como un preprocesador, y reemplaza los pares coincidentes de $$y $, respectivamente, con sus expresiones preferidas en LaTeX: Esto sucedeantesTeX inicia su trabajo habitual de expandir macros, etc.

La creación de un nuevo archivo de texto de salida, para escribir el contenido modificado sobre la marcha de la entrada, se deja como un ejercicio separado.

Para llevar esto de la etapa de prueba de concepto a algo que pueda ser lo suficientemente sólido para el trabajo en el mundo real, ciertamente también habría que agregar código para probar si el material que examina el preprocesador ocurre en modo palabra por palabra o está contenido. en una cadena de URL. En estos y otros casos similares no se deben realizar sustituciones, ¿verdad?

ingrese la descripción de la imagen aquí

% !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}

información relacionada