我想将子文档的部分内容(由行号范围指定)作为 LaTeX 输入,同时生成有用的 SyncTeX 信息。还应该可以重新包含主文档中已有的行。
例子
给定输入文件
% -- main.tex
..: ...
20: Before input.\par
21: \inputlines{2}{4}{child.tex}
22: After input.\par
23: Repeat: \inputlines{22}{22}{main.tex}
..: ...
% -- child.tex
1: 1 First line.\par
2: 2 Second line.\par
3: 3 Third line.\par
4: 4 Fourth line.\par
5: 5 Fifth line.\par
我希望输出包含
...
Before input.
2 Second line.
3 Third line.
4 Fourth line.
After input.
Repeat: After input.
...
并对“2 秒行”调用反向搜索。实际上应该将编辑器引导至 中的正确行child.tex
。
现有的部分解决方案
相关问题。
在 ”\仅输入文件的一部分“,提供了一个解决方案,可以满足我的要求。除了用于 SyncTeX 支持。据我所知,这是使用该\read
机制处理文件的一个不幸的副作用。
至关重要的是,该解决方案在包含多行构造(例如多行\def
或equation
环境)的情况下非常强大。
包裹“清单”。\lstinputlisting
该包的 命令listings
提供了选项firstline
和lastline
,执行所需的过滤,同时提供 SyncTeX 支持。
然而,它专门用于包含文件逐字 我无法核实
- 他们的逐行过滤是如何工作的,以及
- 如果它可以在不破坏多行构造或 SyncTeX 的情况下转换为 LaTeX 输入。
包“catchbetweentags”。
该catchfilebetweentags
软件包提供了一种包含明确标记的文件内容的机制。但是,对于我的目的而言,要求明确
%<*tag> ... %</tag>
注释是不可取的,而且 SyncTeX 信息无论如何都会丢失。
目的
我正在研究这方面的选项,以便重写apxproof
支持 SyncTeX 的软件包。目前,此软件包会创建一个辅助文件,该文件稍后会被包含进去,从而创建指向该辅助文件的垃圾 SyncTeX 信息。
如果可能的话,在不失去 SyncTeX 支持的情况下部分读取文件,将允许在不同的基础上构建功能。
MWE 与 apxproof 一起演示问题
\makeatletter\input{filecontents.sty}\makeatother
\begin{filecontents*}{\jobname.child.tex}
This proof has its contents stored in a child document.
SyncTeX will correctly point to this file
but
\begin{itemize}
\item It doesn't fix the loss of precision in \verb|thmrep|.
\item With many proofs, the large number of child documents
can become rather inconvenient.
\end{itemize}
\end{filecontents*}
\documentclass{article}
\usepackage{apxproof}
\usepackage{etoolbox}
\let\appendixprelim\relax % Prevent newpage before typesetting proofs.
\newtheoremrep{thm}{Theorem}
\preto\appendix{\noindent\hrulefill Appendix starts here}
\begin{document}
\section{Start}
\begin{thmrep}
This is a theorem, that will be repeated in the appendix.
SyncTeX sort of works here, for
It does however point only to the end of the environment,
not to individual paragraphs.
\end{thmrep}
\begin{appendixproof}
This is the proof, which will be put into the appendix via \verb|\VerbatimOut| mechanism.
\textsf{apxproof} defers it to the appendix,
by writing it out to \verb|\jobname.axp|
and then \verb|\input|ing it in the appendix.
Sadly, this mechanism causes SyncTeX to consider
the auxiliary file \verb|\jobname.axp| to be
the source of the contents.
\end{appendixproof}
\begin{appendixproof}
\input{\jobname.child.tex}
\end{appendixproof}
\end{document}
答案1
我找到了一个解决方案,但限制条件是,想要重读的内容受环境限制。现在没有时间清理它,所以我只发布了原始示例。
该工作由宏完成\InputPartialFile
。
%% == filterfiles-selfreparse.tex
\documentclass[12pt]{article}
\usepackage{etoolbox}
\newenvironment{fold}{}{}
\makeatletter
\begin{document}
Line \the\inputlineno.
Line \the\inputlineno.
Line \the\inputlineno.
Line \the\inputlineno.
Line \the\inputlineno.
Line \the\inputlineno.
\newcount\startline
\startline=\inputlineno
\begin{fold}
First paragraph inside fold.
\ifcsname IPF@nesting\endcsname\the\IPF@nesting\fi
\begin{fold}
Stuff inside nested fold.
\begin{equation}
content...
\end{equation}
\end{fold}
Second paragraph inside fold = end of fold.
\end{fold}After fold, same line.
After fold, next line.
%% Must use line-skipping instead of \@gobble, because
%% \@gobble updates \inputlineno only after the first character
%% of the line has been lost.
\begingroup
\global\long\def\IPF@skipline#1{%
\begingroup
\catcode`\^^M=13\relax
\IPF@skipline@b{#1}%
}
% next lines are whitespace-sensitive.
\catcode`\^^M=13
\global\long\def\IPF@skipline@b#1#2^^M{\endgroup#1}\endgroup
\def\InputPartialFile#1#2{
%% Usage: \InputPartialFile{STARTLINE}{FILENAME}
%%
%% Read FILENAME from STARTLINE until a balanced \end{ENV} form.
%% Technical limitation: Anything after the \end{..} on the same
%% line will be included.
%%
%% Currently NOT nestable.
%%
\begingroup
\newcount\startline
\startline=#1\relax
\begingroup
\long\def\@@gobble##1{\global\long\def\@@gobbled{##1}}
\def\IPF@skip{%
\ifnumcomp{\inputlineno+1}{<}{\startline}{%
\IPF@skipline\IPF@skip
}{%
\endgroup
\newcount\IPF@nesting
\IPF@nesting=0
\pretocmd{\begin}{%
\advance\IPF@nesting by 1
}{}{\errmessage{Failure to patch \string\begin}}%
\apptocmd{\end}{%
\advance\IPF@nesting by -1
\ifnum\IPF@nesting=0
\endinput
\fi
}{}{\errmessage{Failure to patch \string\end}}%
}%
}
\ttfamily\noindent
\expandafter\IPF@skip
\@@input #2\relax
\endgroup
%\endgroup
}
\framebox[\linewidth]{\parbox{\linewidth}{
\texttt{\string\InputPartialFile\{16\}\{filterfiles-selfreparse\}}
\par\hrulefill\par
\InputPartialFile{16}{filterfiles-selfreparse}
\par\hrulefill\par
\texttt{\string\InputPartialFile\{17\}\{\string\jobname\}}
\par\hrulefill\par
\InputPartialFile{17}{\jobname}
}}
\end{document}
答案2
使用 LuaLaTeX,可以使用回调来实现这一点。请参阅在 LuaLaTeX 中,如何将环境的内容逐字传递给 Lua?其他示例。
%! TEX program = lualatex
\documentclass[12pt]{article}
\usepackage[paper=a4paper,margin=0.6cm]{geometry}
\usepackage{currfile}
\iffalse
line 1
line 2
line 3
\fi
\directlua{
saved_synctex_tag=tex.get_synctex_tag()
function readbuf(buf)
if not (saved_synctex_tag==nil) then
--[[ this code should only be executed once after the \\input ]]
tex.set_synctex_tag(saved_synctex_tag)
tex.set_synctex_no_files(0)
saved_synctex_tag=nil
end
if 7<=tex.inputlineno and tex.inputlineno<=11 then
return nil
else
return ""
end
end
}
\begin{document}
start
\directlua{
tex.set_synctex_no_files(1)
saved_synctex_tag=tex.get_synctex_tag()
luatexbase.add_to_callback('process_input_buffer', readbuf, 'readbuf')
}\input{\currfilename}\directlua{luatexbase.remove_from_callback('process_input_buffer', 'readbuf')}
end
\end{document}
...只是为了演示\iffalse
。\fi
那里不需要命令,行号就足够了。
向前和向后搜索都很好用。如果你不需要在子文件外进行向前搜索,可以删除 synctex 部分。
关于向前搜索,这里的问题是,如果有多个标签对应于同一个文件,synctex 实用程序将仅输出对应于最后一个标签(阅读man 5 synctex
和其他来源以了解 synctex 文件格式的详细信息)。
为了解决这个问题,可以tex.set_synctex_tag
在 LuaTeX 中使用与父文件相同的标签,并且不要记录子文件的标签条目(用 表示set_synctex_no_files
)。
还要确保 与\input
在同一行\directlua
,否则一次性调用将在 之前执行\input
。
也可以看看https://tex.stackexchange.com/a/632368/250119作为前一个函数用法的示例。