10

If I wrote a new package foo, how would I identify all packages that foo could potentially clash with? Sure, I could test against some of the major ones, but there are so many packages doing so many wildly different things....


EDIT

Ok. If you write a new package, what steps do you take to minimize the potential for clashes with other packages?

  • 1
    I suspect this is borderline 'too broad': depending on what you are doing, you could conflict with a lot of packages (as TeX is a macro language). – Joseph Wright Aug 20 '16 at 16:02
  • Ok. If you write a new package, what steps do you take to minimize the potential for clashes with other packages? – JPi Aug 20 '16 at 16:05
10

In terms of package clashes, a prominent issue is command duplication. As an example, consider

\documentclass{article}

\usepackage{txfonts}
\usepackage{amsmath}

\begin{document}

Lorem ipsum \ldots

\end{document}

And you're probably going to run into problems more often if you write a package that could span an entire document (like a math- or symbol-related package) as opposed to providing something more specialised (like a new tabular-like construction, say).

You can take the following steps to minimise the potential for such clashes with other packages:

  • Use a namespace for your commands. That is, instead of a command \something, use (say) \Awesome@something for your Awesome package. Examples of packages using this approach include xkeyval and algorithm2e.

    Historically using @ in commands was sufficient to identify the content as "internal", but it may be better to tie it to the actual package through a namespace identifier as well.

  • Create your namespace commands using an interface macro. That is, instead of using \newcommand{\<cmd>} in your style file, define (say) \awesome@newcommand{<cmd>} that creates \Awesome@<cmd>. It will allow you to easily change your mind later, if you decide Awesome wasn't as awesome.

    You could also consider writing a \nameuse{<cmd>} equivalent to use your namespace commands.

  • Another, more recent development, is to use a CamelCase naming convention for command definition, even at the user interface level.


If you know some packages that are incompatible with your foo, write those components that cause the problem using package loading conditionals.

7

This is a supplement to Werner's answer. While conflicting macro definitions is probably the first issue to consider, it is not the only one.

It is also important to think about how your package can cooperate with others. In avoiding clashing macro definitions, the key is to isolate your macros as much as possible. In thinking about how your package can cooperate with others, things are a bit more complex.

  • Do not require the loading of packages which are not essential to the functioning of your package.

  • Don't load the package with options which are not required.

  • If your package depends heavily on the other, think about whether it makes sense to pass unrecognised options onto the other package.

  • Avoid loading packages which are engine dependent. If unavoidable, load them conditionally unless your package requires a particular engine.

  • Do not impose languages on users unless these are essential to the core functioning of your package (e.g. your package is designed to typeset Outer Mongolian).

  • Do not impose font configurations on users unless these are essential to the core functioning of your package (e.g. your package is a font-support package or only works with a specialist set of fonts).

  • If another package can enhance yours, but is not essential, use one of the following methods.

    • Advise users to load the other package in the documentation or issue a console/log warning recommending it, if applicable.

    • Offer a package option to enable/disable loading the other package.

    • Use hooks provided by the other package to execute code if the other package provides them (e.g. microtype). This code should usually be deferred (see next point).

    • Defer code which relies on the package until all packages are loaded, then execute it only if the other package has been loaded.

Some of the above do not apply to cases in which the package is designed only for personal use, but many of them do.

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.