16

The \listfiles command will give the list of all loaded files (and therefore also packages) at the end of the .log file, but how do I determine from inside LaTeX, whether package A was loaded before package B or vice versa?

1
  • Please note: While the question is about packages, the answers are also usable for other files!
    – Stephen
    Feb 25, 2012 at 13:51

3 Answers 3

15

You can access the list as a comma separated list of filenames in \@filelist

If you need this check after \begin{document} use \listfiles so LaTeX saves that information.

\listfiles does

  \@for\@currname:=\@filelist\do{%
      .....

to iterate over this list.

So for example you could define

\makeatletter

\def\test#1#2{%
\def\hmma{#1.sty}%
\let\hmmb\@empty
\@for\@currname:=\@filelist\do{%
   \ifx\@currname\hmma
     \def\hmmb{#2.sty}%
   \fi
   \ifx\@currname\hmmb
       \typeout{#1 loaded before #2}%
   \fi}}

then using this as:

\test{marginnote}{geometry}

will type out

marginnote loaded before geometry

if that is in fact the case.

As noted in the comments you might want to use different comand names in production code, also if the two .sty are removed from the test you can test other files such as class and def files that are listed by LaTeX, but would need to explicitly use the extension, so \test{marginnote.sty}{geometry.sty}

4
  • \@filelist was the information I was missing! Thanks! \@currname collides with the hyperref package: ! Undefined control sequence. \@currname ->\@nil Replacing \@currname by \@dc (or something longer, which is probably better to make sure it is not used elsewhere) works (got that \hmma/\hmmb ;-)). \newcommand{\test}[2] instead of \def\test#1#2 might be considered, too.
    – Stephen
    Feb 25, 2012 at 13:47
  • While my question was about packages, you might want to add a note that your answer also works for any files, if .sty is removed from the code and \test{marginnote.sty}{geometry.sty} is used. For other files e.g. \test{subdocumentabcd.tex}{subdocumentzyxw.tex} or checking for .cfg or included .pdf or whatsoever is then possible. Your solution is robust but not complicated. A really nice answer. (Your new badge already says so.) +1 (yesterday) and now also accepted.
    – Stephen
    Feb 25, 2012 at 13:47
  • This answer is responsible for this bug, according to comments in the package file ;).
    – cfr
    Aug 14, 2015 at 23:14
  • @cfr I'm sure I've never been responsible for a package bug, the comment must be in error! Aug 15, 2015 at 16:12
9

Here's a way: the code from \usepackage{xparse} to \ExplSyntaxOff should go before checking any package, of course. The definition of the \test command is just for showing that the code works, though, and can be removed.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_pkgfirst_list_seq
\bool_new:N \l_pkgfirst_tmpa_bool
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\NewDocumentCommand{\ifpackagefirst}{mmmm}
  {
   \bool_set_false:N \l_pkgfirst_tmpa_bool
   \seq_set_split:Nnx \l_pkgfirst_list_seq {,} { \use:c { @filelist} }
   \seq_if_in:NnT \l_pkgfirst_list_seq {#1} { \bool_set_true:N \l_pkgfirst_tmpa_bool }
   \seq_if_in:NnT \l_pkgfirst_list_seq {#2} { \bool_set_true:N \l_pkgfirst_tmpa_bool }
   \bool_if:NTF \l_pkgfirst_tmpa_bool
     { \pkgfirst_compare:nnnn {#1}{#2}{#3}{#4} }
     { \msg_term:x {OOPS,~packages~not~both~loaded} }
  }
\cs_new:Npn \pkgfirst_compare:nnnn #1 #2 #3 #4
  {
   \bool_set_false:N \l_pkgfirst_tmpa_bool
   \seq_map_inline:Nn \l_pkgfirst_list_seq
     {
      \str_if_eq:nnT { #1 } { ##1 }
        { \prg_map_break:n { \bool_set_true:N \l_pkgfirst_tmpa_bool } }
      \str_if_eq:nnT { #2 } { ##1 }
        { \prg_map_break:n { \bool_set_false:N \l_pkgfirst_tmpa_bool } }
     }
   \bool_if:NTF \l_pkgfirst_tmpa_bool {#3} {#4}
  }


\NewDocumentCommand\test{m m}
  {\ifpackagefirst{#1}{#2}{\msg_term:x {#1~before~#2}}{\msg_term:x {#1~after~#2}}}

\ExplSyntaxOff

\usepackage{graphicx}
\usepackage{imakeidx}
\usepackage{kantlipsum}


\test{graphicx.sty}{imakeidx.sty}

\test{imakeidx.sty}{kantlipsum.sty}

\test{kantlipsum.sty}{graphicx.sty}

\test{pippo.sty}{pluto.sty}

\stop

This is the output:

*************************************************
* graphicx.sty before imakeidx.sty
*************************************************
*************************************************
* imakeidx.sty before kantlipsum.sty
*************************************************
*************************************************
* kantlipsum.sty after graphicx.sty
*************************************************
*************************************************
* OOPS, packages not both loaded
*************************************************

Usage:

\ifpackagefirst{package1.sty}{package2.sty}
  {code to be executed if 1 has been loaded before 2}
  {code to be executed if 2 has been loaded before 1}

If the packages are not both loaded, no code will be executed.

1
  • It is good to have a completely different kind of solution for the problem.
    – Stephen
    Feb 25, 2012 at 13:48
9

A way to check for file order is to check the order of the files loaded in the @filelist.

\documentclass{book}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{verse}
\usepackage{hyperref}
\usepackage{caption}
\newcounter{ctr}
\makeatletter
\let\afilelist\@filelist
\begin{document}
% Just to see files
\@for\next:=\afilelist\do{%
 \next, \par
}
% Command factory
\stepcounter{ctr}
\@for\next:=\afilelist\do{%
      \expandafter\edef\csname @\next\endcsname{\thectr}
     \stepcounter{ctr}
}

% Define macro to check order
\def\checkpkgorder#1#2{%
   \edef\X{\csname @#1\endcsname}
    \edef\Y{\csname @#2\endcsname}
    \expandafter\ifnum\X\expandafter<\Y
      Yes loaded earlier \X, \Y
     \else
      No loaded later \X, \Y
   \fi
}

\checkpkgorder{book.cls}{ifxetex.sty}
\end{document}
2
  • For checking after \begin{document} and to cover a before b as well as b before a in one step your code is really useful, but because I need neither of those I accepted the answer of David Carlisle.
    – Stephen
    Feb 25, 2012 at 13:48
  • @Stephen Not to worry, David's answer was very elegant. It deserved to be accepted. Upvoted it myself also.
    – yannisl
    Feb 25, 2012 at 15:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .