如何使用lua重寫tex文件

如何使用lua重寫tex文件

$我嘗試用​​公式和公式來解決問題$$,對這些公式執行自動標記,包括在結構樹中添加。帶有\grabinline或 的變體\grabdisplay對我不起作用,因為equation例如在嘗試使用時出現錯誤。最近我讀到我可以透過lualatex.首先,我嘗試簡單地替換$$$如果之前沒有\字符,但它不僅不起作用,而且當我嘗試重寫它時我的文件已損壞,我的意思是,它添加了新的奇怪行。

請幫助我,我該如何解決這個問題,我的意思是文件損壞的問題,請向我解釋為什麼會發生這種情況?

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 的readlines,乍看之下與 Lua 的 類似io.lines。但是,例如,Pythonreadlines直接將所有行讀取到數組中,而 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}

相關內容