7

How do I find out the package that enable the compilation of a tex file containing a given \begin{X}...\end{X} environment?

luchonacho
  • 4,161

1 Answers1

6

I came up with this macro \findpackagebycommand:

\makeatletter
% patched command of loading a package
\def\find@load#1[#2]#3[#4]{%
    % load the package
    \find@fileswith@pti@ns{#1}[#2]{#3}[#4]%
    % check if commands exists now
    \ifcsname\find@command\endcsname
        \typeout{Package #3 introduces command \find@command.}%
        % command has been found, revert to original version without checks
        \let\@fileswith@pti@ns\find@fileswith@pti@ns
    \else
        % somehow, \@fileswith@pti@ns is restored after loading a package
        % thus, patch it again
        \let\@fileswith@pti@ns\find@load
    \fi
}%

\newcommand*{\findpackagebycommand}[1]{%
    % using this multiple times - esp. when the package has not been found yet -
    % will break things. Thus, check first that \find@command has never been defined before
    \ifx\find@command\undefined
        \def\find@command{#1}%
        % first, check if this command is already defined
        \ifcsname\find@command\endcsname
            % in this case, just issue a warning and do nothing
            \@latex@warning@no@line{Command \find@command \space is already defined}%
        \else
            % overwrite the internal \@fileswith@pti@ns command, which does the actual loading
            % \@fileswith@pti@ns is used internally by \usepackage and \RequirePackage
            \let\find@fileswith@pti@ns\@fileswith@pti@ns
            \let\@fileswith@pti@ns\find@load
        \fi
    \else
        % used multiple times - prevent and give a warning
        \@latex@warning@no@line{You can use \protect\findpackagebycommand \space only once}%
        \errmessage{Invalid use of command findpackagebycommand.}%
    \fi
}

\makeatother

It overwrites an internal command used by \usepackage with a simple test if the name of the command/environment is defined after loading the package.

This is not perfect and has some drawbacks:

  • it does not separate the packages if you use \usepackage{foo,bar,baz}. It simply shows you that this command is loaded by one of these packages.
  • It cannot be used multiple times. Some more logic will be required to enable searching for multiple commands at once.

Use it like this, before loading any other packages (and the document class, if you wish):

\makeatletter
\newcommand*{\findpackagebycommand}[1]{
    … like above …
}
\makeatother

\findpackagebycommand{lstlisting}

\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{listings}
\usepackage[T1]{fontenc}

\begin{document}

Test

\end{document}

The name of the package will be shown in the latex output, line "Package listings introduces command lstlisting.":

This is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016/Arch Linux) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./packagetest.tex
[…]
(/usr/share/texmf-dist/tex/latex/base/inputenc.sty […])
(/usr/share/texmf-dist/tex/latex/amsmath/amsmath.sty […])
(/usr/share/texmf-dist/tex/latex/listings/listings.sty
(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texmf-dist/tex/latex/listings/lstmisc.sty)
(/usr/share/texmf-dist/tex/latex/listings/listings.cfg))
Package listings introduces command lstlisting.
(/usr/share/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texmf-dist/tex/latex/base/t1enc.def))
[…]

(When loaded by an indirect package loading (e.g. \define@key defined by some package loading keyval), it prints the chain of loaded packages backwards, but at different lines. This can be improved.)

  • Cool! This is basically what I was looking for. The limitations are fairly easy to overcome. Yet, it requires the package to be loaded in advance (which make sense given the internal logic of compiling), so it is not helpful to look for commands when package is unknown. Also, I still don't get the "Command huge is already defined" problem. Is defined by the default packages included? Can I not identify them? – luchonacho Aug 17 '16 at 05:47
  • What do you mean by "not helpful to look for commands when package is unknown"? If you are searching for a specific command you do not use in your document, and want to know which package to load, simple do a web search. ;) — Yes, \huge is usually defined by the document class. I updated the code a bit so you can use it even before that. – Martin Nyolt Aug 17 '16 at 08:20
  • You're right. You do not loop up within tex for new commands hehe. Thanks for the update. That is what I wanted! – luchonacho Aug 17 '16 at 08:27
  • 1
    This is roughly the same as latexdef --find. – user202729 Dec 11 '22 at 08:09