输出/排版文档中使用的(第一级)包的名称?

输出/排版文档中使用的(第一级)包的名称?

考虑这个 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- 或\included文件使用的包.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}

...排版结果为:

测试-0.png

当然,你需要这个_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*}
%

相关内容