考虑这个 MWE test-0.tex
:
\documentclass{article}
\usepackage{filecontents} % tlmgr install filecontents
\usepackage[utf8x]{inputenc}
\begin{filecontents}{test-1.tex}
\usepackage{tikz}
\usepackage{pgfplots}
\end{filecontents}
\input{test-1.tex}
\usepackage{lipsum}
\usepackage{hologo} % tlmgr install oberdiek; http://tex.stackexchange.com/a/7564/2595
\begin{document}
\lipsum[1]
This document was typeset with \hologo{pdfLaTeX}, using packages: \texttt{filecontents}, \texttt{inputenc}, \texttt{tikz}, \texttt{pgfplots}, \texttt{lipsum}, \texttt{hologo}.
\end{document}
我希望以某种方式使用一个宏来自动确定使用的第一级包,所以我可以编写类似伪代码的内容:
This document was typeset with \hologo{pdfLaTeX}, using packages: \typesetUsedPackages.
\usepackage{}
通过第一级包,我指的是通过主.tex
文件或(递归)\input
- 或\include
d文件使用的包.tex
- 但不是可能包含在这些第一级包中的包;MWE 显示了我想要的输出。
(此外,如果可以自动确定和排版可执行徽标和所使用的文档类,那就太好了,例如:
This document was typeset with \typesedUsedExecutable in document class \typesetUsedDocumentclass; using packages: \typesetUsedPackages.
)
那里有类似的东西吗?
答案1
好吧,你可以依赖序言中的策略,人们使用\usepackage
,而在包和类中,它是\RequirePackage
:
\documentclass[a4paper]{article}
\def\usedpackages{}
\let\xusepackage\usepackage
\renewcommand\usepackage[2][]{\edef\usedpackages{\usedpackages#2,}\xusepackage[#1]{#2}}
\usepackage[margin=0pt]{geometry}
\usepackage{pgffor}
\begin{document}
Packages:
\begin{itemize}
\foreach \x in \usedpackages{\ifx\x\empty\else \item \x \fi}
\end{itemize}
And the packages really got loaded with the options passed into it since
foreach is working and we get zero margins here.
\end{document}
答案2
好的,我设法做了一些事情 - 但当然,如果能得到更博学的答案,我将不胜感激。首先,这是使用示例:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass{article}
%%% start scanning
\input{_usedpackages.tex}
\usepackage{filecontents} % tlmgr install filecontents
\usepackage[utf8x]{inputenc}
\begin{filecontents*}{test-1.tex}
\usepackage{tikz}
\usepackage{pgfplots}
\end{filecontents*}
\input{test-1.tex}
\usepackage{lipsum}
\usepackage{hologo} % tlmgr install oberdiek; http://tex.stackexchange.com/a/7564/2595
%%% stop scanning - \typesetUsedPackages should be ready after this:
\stopScanUsedPackages
\begin{document}
\lipsum[1]
This document was typeset with \hologo{pdfLaTeX}, using packages: \typesetUsedPackages.
\typeout{USEDPACK \the\usedpacklinecnt,\the\usedpacklcnt: \typesetUsedPackages}
\end{document}
此代码开始扫描\input{_usedpackages.tex}
,并通过重新定义来实现\usepackage
,因此它首先在文件 中输出包的名称usedpacks.texlog
,每行一个包名称。(由于 .sty 包应该使用\RequirePackage
,我猜这本身就确保了只收集“第一级”包)。
同一个_usedpackages.tex
文件定义了,这基本上停止了文件写入,重新读取它并编写一个新宏,其中每行的内容都使用 中的样式(此处)\stopScanUsedPackages
进行格式化,称为。此宏在终端中输出为:\usedpackstyle
\texttt{#1}
\typesetUsedPackages
USEDPACK 6,6: \texttt {filecontents}, \texttt {inputenc}, \texttt {tikz}, \text
tt {pgfplots}, \texttt {lipsum}, \texttt {hologo}
...排版结果为:
当然,你需要这个_usedpackages.tex
文件 - 它就在这里;只需粘贴此代码片段即可前上例中的方法\documentclass
,就会生成(或者直接复制\begin
/之间的部分\end{filecontents*}
):
\RequirePackage{filecontents}
\begin{filecontents*}{_usedpackages.tex}
% NB: Clearly, these three - as any other \usepackages which
% execute before this code is run - will not show in
% used packages list (\typesetUsedPackages)
% http://stackoverflow.com/a/6677461/277826
\usepackage{ifthen} % provides \ifthenelse test
\usepackage{xifthen} % provides \isempty test; tlmgr install xifthen ifmtarg
\usepackage{xstring}
% this starts the scan at point of inclusion:
\newwrite\usedpackfile
\immediate\openout\usedpackfile=usedpacks.texlog
\let\oldusepackage\usepackage
\def\tempty{}
\renewcommand{\usepackage}[2][]{%
%\immediate\write\usedpackfile{\string\texttt{#2}} % don't style here
\immediate\write\usedpackfile{#2} %
\ifthenelse {\isempty{#1}} %
{ %
%\typeout{EMPTY} %
\oldusepackage{#2} % optional argument empty
} %
{ % else
%\typeout{NOT EMPTY} %
\oldusepackage[#1]{#2} % optional argument not empty
} %
}
\newread\usedpackmyread
\newcount\usedpacklinecnt
\newcount\usedpacklcnt
\def\typesetUsedPackages{}
\def\usedpackstyle#1{\texttt{#1}}
% this stops the scan - insert right before \begin{document}
% (cannot get it to work with \newcommand?!)
\makeatletter
\def\stopScanUsedPackages{%
\immediate\closeout\usedpackfile
% http://tex.stackexchange.com/a/17674/2595
% http://tex.stackexchange.com/a/207108/2595
% if using:
% \readline: ^^M at EOL (must \StrGobbleRight), ^^M at EOF (must \ifx\tmpline\empty)
% \read: "" at EOL, \par at EOF (must \if\tmpline\par)
%
% get number of lines
\immediate\openin\usedpackmyread=usedpacks.texlog
\@whilesw\unless\ifeof\usedpackmyread\fi{%
\readline\usedpackmyread t\expandafter o\csname tmpline\endcsname % this just has to be here to have the loop run; but using it to find non-empty lines
\StrGobbleRight{\tmpline}{1}[\tmpline] % remove the ^^M newline (last char)
\ifx\tmpline\empty\else %
\advance\usedpacklinecnt by \@ne %
\fi %
}
\immediate\closein\usedpackmyread
% now read lines, do formatting & concat into macro \typesetUsedPackages
\immediate\openin\usedpackmyread=usedpacks.texlog
\@whilesw\unless\ifeof\usedpackmyread\fi{%
\read\usedpackmyread to\tmpline %
\if\tmpline\par\else %
\advance\usedpacklcnt by \@ne %
\StrGobbleRight{\tmpline}{1}[\tmpline] % still have to run this, to get rid of a space at end
\protected@edef\typesetUsedPackages{\typesetUsedPackages \usedpackstyle{\tmpline}} %
\typeout{cnts: \the\usedpacklcnt=\the\usedpacklinecnt} %
\ifnum\the\usedpacklcnt=\the\usedpacklinecnt %
\typeout{YES} %
\else % if not on last line
\typeout{NO} %
\protected@edef\typesetUsedPackages{\typesetUsedPackages,\space} %
\fi %
\fi %
}
\immediate\closein\usedpackmyread
} % end \def
\makeatother
\end{filecontents*}
%