这个问题导致了一个新的方案的出现:
rescansync
假设我想用...替换a
某一部分中的所有内容(源代码中,而不是渲染的输出)b
。
%! TEX program = lualatex
\documentclass{article}
\usepackage{filecontentsdef}
\begin{document}
\begin{filecontentsdefmacro}{\zzz}
abc
abc
abc
\end{filecontentsdefmacro}
\ExplSyntaxOn
\regex_replace_all:nnN {a} {b} \zzz
\ExplSyntaxOff
\filecontentsexec\zzz
\end{document}
它可以工作,但是 synctex 数据丢失(它指向整个块,而不是单个段落/行)
我怎样才能保留 synctex 数据?
仅使用 LuaTeX 的解决方案就可以了。
答案1
有一种方法。有关文档,请参阅texdoc luatex
和texdoc ltluatex
(以及正在导入的包)。
缺点:需要写入真实的外部文件(不是\scantokens
)
!!
在代码中搜索重要部分。(请注意,使用的directlua
是 而不是luacode*
,因此请小心使用 catcode)
%! TEX program = lualatex
\documentclass{article}
\usepackage{currfile} % !! need this package for currfilename to be defined
\begin{document}
% write the content to a separate file
\directlua{magic_offset=1 inputlineno_offset=tex.inputlineno+magic_offset} % !!
\begin{filecontents*}[overwrite]{b.tex}
\typeout{1}
abc
abc
abc
\typeout{2}
\end{filecontents*}
% it's also possible to typeset something between the "write" part and the "rescan" part
first line
\directlua{ --[[ !! ]]
saved_synctex_tag=tex.get_synctex_tag()
function handler()
if token.get_macro("currfilename")=="b.tex" and tex.get_synctex_tag()>0 then
if not (saved_synctex_tag==nil) then
tex.set_synctex_tag(saved_synctex_tag)
saved_synctex_tag=nil
end
tex.set_synctex_line(tex.inputlineno+inputlineno_offset)
end
end
tex.set_synctex_mode(2)
luatexbase.add_to_callback('process_input_buffer', handler, "synctex patch callback")
}\input{b.tex}\directlua{luatexbase.remove_from_callback('process_input_buffer', "synctex patch callback") tex.set_synctex_mode(0) tex.set_synctex_line(0) }
last line
last line
\end{document}
请注意,由于某些奇怪的原因,如果[abspath]
提供了选项来currfile
打包,则处理程序将被调用多次tex.get_synctex_tag()==0
。
因此添加了检查以便它只被调用一次,但针对实际文件。
(我猜是因为原始的仅扩展命令\input
或者别的什么)
删除saved_synctex_tag=nil
线;或者get_macro("currfilename")=="b.tex"
检查会使事情变得更糟,因为(我认为,未测试) 如果 b.tex 包含 egctex,则set_synctex_line
不应运行c.tex
。
回调的替代方法是,在输入文件本身内设置标签总是有效的。