Lua를 사용하여 tex 파일을 다시 작성하는 방법

Lua를 사용하여 tex 파일을 다시 작성하는 방법

나는 구조 트리에 추가하는 것을 포함하여 수식에 대한 자동 태그 지정을 수행하기 위해 수식 과 $관련된 문제를 해결하려고 노력합니다 . 예를 들어 를 사용하려고 할 때 오류가 발생하기 때문에 or $$의 변형이 작동하지 않습니다 . 최근에 . 먼저 간단히 바꾸려고 했는데 이전에 문자가 없으면 작동하지 않을 뿐만 아니라 다시 쓰려고 할 때 파일이 손상되어 이상한 줄이 새로 추가됩니다.\grabinline\grabdisplayequationlualatex$$$\

도와주세요. 이 문제를 어떻게 해결할 수 있습니까? 파일 손상 문제를 의미하며 왜 그런 일이 발생하는지 설명해 주세요.

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

답변1

문제는 TeX와 관련된 것이 아니며 동일한 파일을 읽고 쓸 때 발생하는 일반적인 문제입니다. 무슨 일이 일어나고 있는 걸까요?

아마도 얻을 수있는 결과는 다음과 같습니다.

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

이는 원본 파일을 연 후 첫 번째 줄의 첫 번째 바이트에 있기 때문에 발생합니다. 그런 다음 을 사용하여 lines첫 번째 줄을 읽습니다 \documentclass{article}. 그 이후에는 줄에서의 자신의 위치가 두 번째 줄의 시작 부분이 됩니다. 여기에서 발행하면 f:write수정되지 않은 첫 번째 줄이 파일의 현재 위치인 두 번째 줄에 기록됩니다. 기존 콘텐츠를 덮어씁니다.

이제 파일에는 다음이 포함됩니다.

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

현재 위치는 두 번째 끝 부분에 있습니다 \documentclass{article}. 이제 다음 lines반복에서는 나머지 줄을 읽으므로 t.lua")}. 그런 다음 세 번째 줄의 시작 부분에 있고 방금 읽은 텍스트로 덮어쓰면 다음과 같은 결과를 얻을 수 있습니다.

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

관찰한 파일을 얻을 때까지 모든 줄에 대해 이 작업이 반복됩니다.

여기서 배울 수 있는 교훈은 무엇입니까? 파일을 읽는 동안 파일을 덮어쓰지 마십시오!

대조적으로 일부 다른 프로그래밍 언어에는 Python with 와 같은 함수가 포함되어 있는데 readlines, 언뜻 보면 Lua의 와 비슷해 보입니다 io.lines. 그러나 예를 들어 Python은 readlines모든 줄을 배열로 직접 읽는 반면 Lua는 루프를 반복할 때마다 한 번에 한 줄만 읽습니다. 따라서 읽기와 쓰기가 명확하게 분리되어 있기 때문에 유사한 코드에서는 그다지 명백한 문제가 나타나지 않습니다. 즉 readline, 동안만 읽고 나중에 쓰기입니다.

어쨌든 TeX 실행 중에 TeX 소스 파일을 다시 작성하는 것은 매우 위험하며 호환되지도 않습니다(열린 파일을 편집할 때는 Windows가 합리적입니다).

process_input_buffer한 번에 한 줄만 변경하려는 경우 훨씬 안전하고 사용하기 쉽습니다 . 특정 파일의 행에만 영향을 주는 데 사용할 수 있습니다 status.input_ptr. (프로세스에서 패턴을 수정했습니다.)

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

이것이 훨씬 덜 위험하더라도 입력 줄을 다시 작성하지 않고 목표를 보관할 수 있는 방법을 찾는 것이 좋습니다.

답변2

(파티에 조금 늦었지만 여전히 유용하길 바랍니다)

새 텍스트 파일을 생성하지 않는 솔루션은 다음과 같습니다. 대신 본질적으로 전처리기처럼 "즉시" 작동하며 일치하는 $$및 의 쌍을 $각각 LaTeX에서 선호하는 표현식으로 바꿉니다.~ 전에TeX는 매크로 등을 확장하는 일반적인 작업을 시작합니다.

입력 내용의 즉석 수정 내용을 기록하기 위해 새 출력 텍스트 파일을 만드는 것은 별도의 연습으로 남습니다.

이를 개념 증명 단계에서 실제 작업에 충분히 견고할 수 있는 것으로 가져오려면 전처리기에 의해 검사되는 자료가 축어 모드로 발생하는지 또는 포함되어 있는지 테스트하는 코드도 추가해야 합니다. URL 문자열에서. 이와 유사한 경우에는 교체를 수행해서는 안 됩니다. 그렇죠?

여기에 이미지 설명을 입력하세요

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

관련 정보