Is there an easy way of ascertaining what packages are loaded by classes and other packages?

My question (or questions, strictly, because I have two) are prompted by an answer to one of the questions listed in this week's newsletter which indicated that there was no point in loading the {hyperref} package because it had already been loaded by the document class or another package (I forget which). So:

Q1: Is there an easy way to ascertain what packages are loaded by classes and other packages? I know 'read the documentation!' is the obvious answer, but let's face it, some of the package documents run for upwards of 100 pages.

Q2: Does it matter if I inadvertently load a package that has already been loaded?

-
S1: Use \listfiles and all loaded packages are listed in the log-file. S2: In general no. –  Marco Daniel Jan 27 '12 at 9:22

You can check the log file to see if a package got loaded or use \listfiles in your preamble to get a formatted list of all packages loaded. You could also check the source code of the class (e.g. grep packagename kpsewich classname.cls under Linux and friends) if you are skilled enough. You can check for a loaded package inside the preamble using \@ifpackageloaded{<name>}{<yes>}{<no>. See Test if a package is loaded for more about that.

In general LaTeX doesn't mind if you request the loading of an already loaded package. The second request is simple skipped. Otherwise it would be difficult to use two packages which both require a specific third package. However, if the same package is requested twice or more with different options you will get an error, because the package can't be loaded a second time.

IMHO it is very good style to explicitly request all used packages. If you of course now for sure that a specific package is loaded by another one you can avoid a manual loading to save you the time and source code space.

-

A \listfiles will insert all files used in your compilation, the log file is usually the same name as your TeX.tex; i.e. TeX.log. This command will only list packages added through commands like documentclass and usepackage, not \input{}.

As far as I know many packages ignore any previously loaded files or packages, such as hyperref, if you use a pdftex option in the documentclass it will ignore that option if placed in hypersetup.

-

If a package is loaded by \usepackage or \RequirePackage then it will not be loaded a second time. If it is loaded with options on the second call that were not used on the first, then you will get an error:

        Options clash for ...
The package ... has already been loaded
with options: ....


If the options are compatible, the second \RequirePackage is silently ignored.

-

To get specifically only a list of loaded packages, and not all loaded files, you can use the following \ltsgetpackagenames command that I found in the development version of ltxtools.sty. Compare its outcome with that of \listfiles.

\makeatletter
\documentclass{article}
\usepackage{catoptions}
% hyperref loads many packages; so let us use it as an example:
\usepackage{hyperref}

\robust@def*\ltsgetpackagenames{%
\let\ltsgetpackagenames\relax
\AtBeginDocument{%
\begingroup
\def\LTS@tempb{%
\def\\{ }\@tempcnta\z@pt
\def\LTS@tempa{}%
\def\siso@do####1{%
\ifnum\@tempcnta>20\relax
\typeout{\LTS@tempa\ifcsnullTF\reserved@f{}{[\reserved@f]}}%
\loopbreak
\else
\edef\LTS@tempa{\LTS@tempa####1}%
\fi
}%
\expandafter\siso@@loop\expandafter{\filename@base
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\}%
}%
\typeout{^^J *** Package List ***}%
\def\csv@do##1{%
\filename@parse{##1}%
\ifxFT\filename@ext\@pkgextension{}{%
\ifcsndefTF{\filename@base}{%
\edef\reserved@e{\expandafter\meaning
\csname\filename@base\endcsname}%
\xifinsetTF{\detokenize{macro:}}\reserved@e{%
\edef\reserved@f{\expandafter\strip@prefix\reserved@e}%
}{%
\let\reserved@f\reserved@e
}%
}{%
\def\reserved@f{}%
}%
\LTS@tempb
}%
}%
\csv@@loop*[,]\@filelist
\typeout{ **************^^J}%
\endgroup
}%
}
\@onlypreamble{\ltsgetpackagenames}

% Example:
\ltsgetpackagenames
\listfiles
\makeatother
\begin{document}
xx
\end{document}

-
@Torbjorn: Please what did you edit here? –  Ahmed Musa Jan 28 '12 at 12:59
Sorry, didn't see your comment before now. As you can see from the revision history, I just put in some backticks to mark the couple of commands at the beginning as code. You find the revision history of a post by clicking the time after the word "edited" at the bottom of the post. E.g., it says "edited 3 hours ago" under this post at the moment, and "3 hours ago" is a link. –  Torbjørn T. Jan 28 '12 at 16:54