9

I would like to create a document used to test diverse packages, and I was wondering if it was possible to use a command so that part of the code is read only if the corresponding package is loaded. I've come up with this but it throws an error which I don't know how to fix.

\documentclass{article}
\usepackage[utf8]{inputenc}

\makeatletter
\newcommand{\IfPackageLoaded}[3]{\@ifpackageloaded{#1}{#2}{#3}}
\makeatother

\begin{document}
\IfPackageLoaded{natbib}{natbib loaded}{natbib not loaded}
\end{document}

I get this error:

! LaTeX Error: Can be used only in preamble.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.10 \IfPackageLoaded{natbib}{natbib loaded}
                                            {natbib not loaded}
Your command was ignored.
Type  I <command> <return>  to replace it with another command,
or  <return>  to continue without it.

I also know that the command \ltx@ifpackageloaded exists when loading the package ltxcmds but when I try to use it in

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{ltxcmds}

\begin{document}
\ltx@ifpackageloaded{natbib}{natbib loaded}{natbib not loaded}
\end{document}

I get this error message:

! Undefined control sequence.
l.11 \ltx
         @ifpackageloaded{natbib}{natbib loaded}{natbib not loaded}
The control sequence at the end of the top line
of your error message was never \def'ed. If you have
misspelled it (e.g., `\hobx'), type `I' and the correct
spelling (e.g., `I\hbox'). Otherwise just continue,
and I'll forget about whatever was undefined.

Can someone please point out what I did wrong?

EDIT: changed documentclass from minimal to article.

Lashoun
  • 153

3 Answers3

6

As users Ulrike Fischer and moewe pointed out, this works:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{ltxcmds}

\makeatletter
\newcommand{\IfPackageLoaded}[3]{\ltx@ifpackageloaded{#1}{#2}{#3}}
\makeatother

\begin{document}
\IfPackageLoaded{natbib}{natbib loaded}{natbib not loaded}
\end{document}
Schweinebacke
  • 26,336
Lashoun
  • 153
  • 5
    BTW: The [3] is not needed. You can simply use \newcommand*{\IfPackageLoaded}{\ltx@ifpackageloaded}. – Schweinebacke Apr 10 '19 at 10:08
  • 1
    @Schweinebacke RIght; also \let\IfPackageLoaded\ltx@ifpackageloaded – egreg Apr 10 '19 at 10:43
  • 1
    @egreg Yes, because \ltx@ifpackageloaded is a simple macro. If it would be, e.g., robust, it could be better to use \LetLtxMacro from package letltxmacro. I didn't want to explain all this, so I've only noted about using \newcommand* without arguments. – Schweinebacke Apr 10 '19 at 10:47
  • Thanks for the precisions – Lashoun Apr 10 '19 at 12:10
2

The following commands were added to LaTeX in the November 2021 release, so you no longer need to define your own.

\IfPackageLoadedTF, \IfPackageLoadedWithOptionsTF, \IfClassLoadedTF, \IfClassLoadedWithOptionsTF

\IfPackageLoadedTF{package name}{true code}{false code}
Jasmine
  • 46
1

Although the solution by @Lashoun is probably most robust, I was curious if we can achieve the same thing without loading ltxcmds.

Reading the guts of ltxcmds.sty and latex.ltx, it seems that loading a package (specifically, the \ProvidesPackage command) defines a macro ver@{packagename}. So, we can check whether this is defined as follows:

\documentclass{article}
\usepackage{hyperref} % toggle me!
\newcommand{\ifloaded}[3]{%
  \expandafter\ifx\csname ver@#1\endcsname\relax%
    #3\else#2\fi}
\begin{document}
  \ifloaded{hyperref.sty}{yes}{no}
\end{document}

I'd be interested in experts' thoughts on the limitations of this simple solution. I simplified much of the code from \ltx@ifundefined from ltxcmds, but maybe I simplified too much! Also, this seems to work without \makeatletter and \makeatother ... but does it really?

jessexknight
  • 2,732