15

I'm creating my personal package. I'd like to use an option to turn on/off the line numbering provided by the package lineno.

So, my sty file contains

\RequirePackage{lineno}
\linenumbers

But if one does not have the lineno package installed it will produce an error. It one does have the package installed it will enumerate the lines.

I'd like to check if one does have lineno first and in affirmative case I'd like to be able to use my package as

\usepackage[lineno]{mysty} % to turn on the numbering

or

\usepackage{mysty} % default with no numbering if `lineno` does not exists

I tried this

\RequirePackage{lineno}
\@ifpackageloaded{lineno}{%
\DeclareOption{lineno}{\linenumbers}%
\ProcessOptions%
}{}

and it works if lineno is installed. But what about if it is not?

11
  • Files can be tested via \IfFileExists{file}{yes}{no}.
  • The following snipset uses a switch \if@mysty@lineno that remembers the option setting lineno for package mysty. Package lineno and \linenumbers are only executed, if the option lineno was given. This way, the package lineno is not loaded unnecessarily if it is not needed.
  • Packages cannot be loaded during the option part of package files (because it would lead to reentrance problems of LaTeX's option code).

Snipset for package mysty:

\newif\if@mysty@lineno % default: false

% Option declarations of package `mysty'

\IfFileExists{lineno.sty}{%
  \DeclareOption{lineno}{\@mysty@linenotrue}%
}{%
  \DeclareOption{lineno}{%
    \PackageWarning{mysty}{Package lineno is not installed}%
  }%
}

% Execute package options
\ProcessOptions

% Afterwards it is again safe to load packages
\if@mysty@lineno
  \RequirePackage{lineno}\relax
  \linenumbers
\fi

Answer to comment:

LaTeX's implementation of \IfFileExists puts the second and third argument in a macro definition. Therefore further definitions with parameters in this arguments make trouble, because the # would need doubling. The following workaround can be used:

\IfFileExists{color.sty}\@firstoftwo\@secondoftwo{%
  \RequirePackage{color}\relax
  \newcommand*{\alert}[1]{\textcolor{red}{#1}}%
}{%
  \newcommand*{\alert}[1]{\textbf{#1}}%
}
4
  • I'm comparing your solution with @egregs one. I understand that both work and they only differ on the sequence of statements, that is, they are logically equivalent. Do you agree or do you see some advantage/disadvantage? Thanks.
    – Sigur
    Apr 26 '13 at 0:10
  • 1
    @Sigur Both solutions are not logically equivalent, but pretty much similar. egreg's solution only tests for the file, if needed -- in my case the warning is given earlier. (I would have deleted my solution, but my answer has more remarks/hints.) Apr 26 '13 at 0:14
  • Why is \IfFileExists{color.sty}{\RequirePackage{color}\def\alerta#1{\textcolor{red}{#1}}}{} producing the error Illegal parameter number in definition of \reserved@a {}?
    – Sigur
    Apr 26 '13 at 0:48
  • 3
    @Sigur "Suboptimal" implementation of \IfFileExists in the LaTeX kernel. Instead of \IfFileExists{file}{yes}{no} the workaround \IfFileExists{file}\@firstoftwo\@secondoftwo{yes}{no} can be used. Here \IfFileExists{color.sty}\@firstofone\@gobble{\RequirePackage{color}\newcommand*{\alerta}[1]{\textcolor{red}{#1}}} can be used. Apr 26 '13 at 1:07
8

Here's what you can put in mysty.sty:

\newif\ifmysty@lineno
\DeclareOption{lineno}{\mysty@linenotrue}

[...]

\ProcessOptions\relax

[...]

\ifmysty@lineno
  \IfFileExists{lineno.sty}
    {\RequirePackage{lineno}}
    {\PackageWarningNoLine{mysty}{You requested `lineno.sty' which\MessageBreak
       doesn't exist on your system}}
\fi

Then if you call \usepackage[lineno]{mysty} you'll load the package or will be warned it doesn't exist. Otherwise lineno won't be loaded.

7
  • Just a question: \ifmysty@lineno must have this format or it is only an easy way to remember some names? That is, is necessary to use \if<name of the package>@<name of the option>?
    – Sigur
    Apr 26 '13 at 0:02
  • 1
    @Sigur The conditional can be named as you wish (so long as it begins with if). But it's common (and good) practice to use some kind of prefix for your package's commands to avoid name clashes.
    – egreg
    Apr 26 '13 at 0:07
  • 2
    A switch name that is defined by \newif must start with \if. The rest of the name is free. But \newif does not check, whether the name is already defined. Using the package name (or similar unique prefix) for internal commands make it easier to avoid name clashes. Apr 26 '13 at 0:09
  • 1
    @HeikoOberdiek Actually LaTeX doesn't enforce \newif\if..., but funny things happen if you say \newif\foo. ;-)
    – egreg
    Apr 26 '13 at 0:11
  • 2
    @egreg Yes, I should have used "should" instead of "must". \newif needs to define \<foo>true and \<foo>false for \newif\if<foo>. LaTeX just gobbles the first two characters from if<foo> to get <foo>. The implementation of plain TeX for \newif requires that the switch name starts with if. Otherwise it triggers a TeX error. In LaTeX the setter functions for \newif\foo would become \otrue and \ofalse. Apr 26 '13 at 0:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.