Définir son propre package permet :
\usepackage[francais]{babel} \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphicx} \usepackage{amsmath} \usepackage{amssymb}
Nous allons créer un fichier « mon_package.sty
» (ou
tout autre nom qui ne crée de doublon) qui comportera les instructions
qui permettront :
%% Informations générales \NeedsTeXFormat{LaTeX2e}[1999/01/01] \ProvidesPackage{mon_package}[2003/01/01] %% Chargement des extensions \RequirePackage{graphicx} %% Déclaration des options \DeclareOption{option}{...} \DeclareOption*{...} \ProcessOptions %% Définition des commandes \newcommand{\blabla}{Super commande} %% Fin du package \endinput
\NeedsTeXFormat{<format>}[<version>]
:
informe TeX du format (LaTeX2e, donc refus de LaTeX2.09, plain TeX,
eplain TeX, AMS-TeX, etc.) nécessaire pour l'utilisation du
package, on peut spécifier un argument optionnel (entre crochets)
permettant d'utiliser des versions récentes dudit format ;\ProvidesPackage{<package>}[<version>]
:
le package s'identifie (là encore on peut donner en argument
optionnel une date de version) ;\RequirePackage[<options>]{<package>}
:
équivalent de \usepackage
pour l'écriture d'un package
ou d'une classe, on peut passer des options au package comme
habituellement ;\DeclareOption{<option>}{<action>}
:
déclare une option qui peut être passée lors de l'appel du
package, lorsque l'option <option>
est passée
<action>
est exécutée ;\DeclareOption*{<action>}
:
comportement adopté par le package quand il est confronté à une
option passée qui n'est pas déclarée ;\ProcessOptions
: exécute le code des options
passées, si cette commande n'existe pas dans le package les options
seront sans effet (bien prendre conscience que les declarations
n'exécutent pas de code!) ;\newcommand{\commande}{<code>}
:
définition d'une nouvelle commande (voir la page sur les
macros) ;\endinput
: fin du package.Supposons qu'il m'arrive d'écrire des documents sans algorithmes et
d'autres avec. Lorsque j'en ai besoin je charge les packages
algorithm
et algorithmic
qui permettent de
mettre en forme des algorithmes, d'en faire une « liste des
algorithmes » et de les rendre flottants (voir la page...). Je peux
encore utiliser mon propre package pour gérer ces cas, il suffit
d'introduire une option « algo » quand on a besoin des fonctionnalités
idoines. Voilà comment :
%% (...) \NeedsTeXFormat et \ProvidesPackage \newif\if@algo \@algofalse \DeclareOption{algo}{\@algotrue} \DeclareOption*{}%% Ne rien faire quand une option est inconnue \ProcessOptions \if@algo \RequirePackage{algorithm} \RequirePackage{algorithmic} \RequirePackage{mes-commandes-algo} \newcommand{\algorithme}{Blabla} \fi %% (...) \newcommand's et \endinput
La commande \newif\ifquelquechose
crée trois
commandes :
\ifquelquechose
à utiliser ainsi (la
partie « else » est facultative)
\ifquelquechose Code si oui \else Code si non \fi
\quelquechosetrue
\ifquelquechose
devient
équivalent à if true ;\quelquechosefalse
\ifquelquechose
devient
équivalent à if false.Dans notre exemple on crée une instruction conditionnelle
\if@algo
qui est équivalente à if false (à cause
de \@algofalse
). Cependant, si l'option « algo » est
passée au package, on exécute \@algotrue
qui a pour effet
de rendre \if@algo
équivalent à if true. Les
packages relatifs à l'algo (et les commandes définies dans le bloc)
seront chargés si et seulement si l'option « algo » aura été passée dans
le fichier .tex
:
\usepackage
\documentclass[a4paper]{article} \usepackage[algo]{mon_package} \begin{document} . . . \end{document}
\documentclass
\documentclass[a4paper, algo]{article} \usepackage{mon_package} \begin{document} . . . \end{document}
Remarque : notons que dans les packages « @ » est une lettre
(contrairement aux document .tex
où « @ » est un symbole)
et que donc on peut écrire des noms de commandes avec « @ ». D'où les
noms \makeatletter
et \makeatother
utilisées
dans des cas un peu exceptionnels. Dans un fichier .tex
,
« \if@algo
» aurait été interprétée comme la commande
\if
suivie de « @algo ».
\NeedsTeXFormat{LaTeX2e}[1999/01/01] \ProvidesPackage{mon_package}[2003/01/01] \newif\if@algo \@algofalse \newif\if@listings \@listingsfalse \DeclareOption{listings}{\@listingstrue} \DeclareOption{algo}{\@algotrue} \DeclareOption*{\PassOptionsToPackage{\CurrentOption}{babel}} \ProcessOptions \RequirePackage{babel} \if@algo \RequirePackage{algorithm} \RequirePackage{algorithmic} \RequirePackage{mes-commandes-algo} \fi \if@listings \RequirePackage{listings} \RequirePackage{verbatim} \RequirePackage{moreverb} \RequirePackage{mes-commandes-listings} \fi \endinput
On déclare comme précédemment deux options « normales » :
algo
et listings
mais quand on est face à
une option inconnue on la passe à babel, ainsi :
\documentclass[a4paper]{article} \usepackage[algo, listings, english, greek, francais]{mon_package} \begin{document} . . . \end{document}
sera équivalent à charger les modules d'algorithmiques, les modules de
d'écriture de programmes, et babel avec les options
english
, greek
et francais
(dans cet ordre). La commande \PassOptionsToPackage{<options>}{<package>}
ne charge pas le package
<package>
, elle rajoute les
<options>
à la liste d'options qui seront passées
au package <package>
lors de l'appel
\RequirePackage{<package>}
.
Remarque : les options déclarées avec
\DeclareOption{...}{...}
peuvent être passées comme
options globales du document comme dans :
\documentclass[a4paper, algo, listings]{article} \usepackage[english, greek, francais]{mon_package} \begin{document} . . . \end{document}
En revanche les langages doivent être passés au package lui-même (notamment babel n'a pas tenté de trouver un langage nommé « a4paper » ce qui aurait abouti à une erreur).
D'une part on ne peut pas utiliser ce mécanisme pour plusieurs
packages auquel on passerait les options non déclarées avec
\DeclareOption{...}{...}
et d'autre part on ne peut pas
s'abstenir de passer au moins une option de langage au package.
keyval
de David Carliste (ou
peut-être prochainement une page tuteurs à ce sujet) ;\@ifundefined{commande}{<then>}{<else>}
: si
\commande
(avec le backslash contrairement à l'argument
de \@ifundefined
) n'est pas définie alors exécute
<then>
sinon exécute
<else>
(LaTeX interne) ;\PackageWarning{<package>}{<texte>}
: produit un warning lors de la
compilation (par opposition à \PackageError{...}{...}
) ;\CurrentOption
: l'option en cours de
traitement ;\NeedsTeXFormat{LaTeX2e}[1999/01/01] \ProvidesPackage{mon_package}[2003/01/01] \RequirePackage{keyval} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Pour gérer les deux types d'options : % % 1. les options normales (\DeclareOption{...}{...}) % % 2. les options type key-val option=value (\define@key{...}{...}{...}) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \@ifundefined{my@unusedlist}{% \let\my@unusedlist\@empty}{} \@ifundefined{my@extractkey}{% \def\my@extractkey#1=#2\my@extractkey{#1}}{} \newcommand{\ProcessUnusedOptions}[1]{% \let\my@tempa\@empty \let\my@tempb\@empty \@for\CurrentOption:=\my@unusedlist\do{% \expandafter\expandafter\expandafter\def \expandafter\expandafter\expandafter\my@key \expandafter\expandafter\expandafter{% \expandafter\my@extractkey\CurrentOption=\my@extractkey}% \@ifundefined{KV@#1@\my@key}{% \edef\my@tempa{\my@tempa,\CurrentOption,}}{% \edef\my@tempb{\my@tempb,\CurrentOption,}}}% \@for\CurrentOption:=\my@tempa\do{% \ifx\CurrentOption\@empty\else \PackageWarning{mypack}{`\CurrentOption' not defined.}\fi}% \edef\my@tempb{% \noexpand\setkeys{#1}{\my@tempb}}% \my@tempb \AtEndOfPackage{\let\@unprocessedoptions\relax}} \DeclareOption*{% \expandafter\expandafter\expandafter\def \expandafter\expandafter\expandafter\my@unusedlist \expandafter\expandafter\expandafter{% \expandafter\my@unusedlist\expandafter,% \CurrentOption}} %%%%%%%%%%%%%%% % Fin du bloc % %%%%%%%%%%%%%%% %% Options «normales» \DeclareOption{foo}{<action foo>} \DeclareOption{bar}{<action bar>} %% Options passées sous forme key=val \define@key{mypack}{<key1>}{<action 1> dépendant de #1} \define@key{mypack}{<key2>}[<default>]{<action 2> dépendant de #1} \ProcessOptions \ProcessUnusedOptions{mypack} \endinput
Dans l'exemple suivant
\documentclass[foo]{article} \usepackage[foo, key1=value1, key2=value2]{mypack} \begin{document} . . . \end{document}
l'option foo
va agir comme dans les exemples simples,
key1=value1
va exécuter le code <action 1>
en utilisant value1
en lieu et place de #1
. Idem
pour key2=value2
sauf que on peut omettre la partie
« =value2
» auquel cas <action 2>
est exécuté
en utilisant <default>
à la place de #1
.
Par exemple si mon_package.sty
contient :
%% (...) \newcounter{nombre} \define@key{mypack}{number}[14]{% \setcounter{nombre}{#1}} %% (...)
on pourra l'appeler ainsi
\documentclass[foo]{article} \usepackage[number=10]{mypack} \begin{document} . \thenombre\ affiche 10. . . \end{document}
ou encore comme cela
\documentclass[foo]{article} \usepackage[number]{mypack} \begin{document} . \thenombre\ affiche 14. . . \end{document}
ou bien sûr sans option du tout (auquel cas le code
\setcounter
ne sera pas exécuté et donc le compteur
nombre
vaudra zéro).
Si mon_package
contient :
\newcommand{\pack@languages}{francais} \define@key{mypack}{language}{% \renewcommand{\pack@languages}{#1}} \RequirePackage[\pack@languages]{babel}
alors on peut l'appeler ainsi
\documentclass[a4paper]{article} \usepackage[language={english, francais}]{mon_package} \newcommand{\option}{\texttt} \begin{document} . \paragraph{Remarque} Noter les accolades pour que l'option \option{francais} ne soit pas passée comme une option à part. . . \end{document}
ou encore ainsi :
\documentclass[a4paper]{article} \usepackage{mon_package} \newcommand{\option}{\texttt} \begin{document} . Babel chargé avec l'option \option{francais}. . . \end{document}
Là encore les options de langages ne pourront pas être spécifiées
globalement avec la commande \documentclass
. (La raison en est
que les options globales qui ne correspondent pas à des options déclarées
avec \DeclareOption
ne sont pas transmises à
\DeclareOption*
.)
Le package mon_package
doit pouvoir être trouvé par LaTeX,
pour cela on peut :
mon_package
dans le même répertoire que
les fichier .tex
qui l'utilisent ;~/texmf/tex/latex/perso/
et créer la variable d'environnement
export TEXINPUTS=$HOME/texmf//:
(certaines distributions
permettent de créer un fichier ls-R grâce à la commande
texhash
) ;mktexlsr
.Pour une documentation concernant l'écriture de classe et de
packages : clsguide
(à noter également les documentations
fntguide
, usrguide
) pour une documentation
générale sur LaTeX : source2e
ou plus soft The not so
short introduction to LaTeX (disponible en français !).
Sur internet : CTAN, les
newsgroup fr.comp.text.tex
et comp.text.tex
auxquels on peut accéder via Google. Par
exemple comment réaliser le symbole « 1 » avec une double
barre pour désigner une fonction indicatrice ? La réponse s'y trouve
en cherchant « 1 barre
indicatrice
». C'est une source d'informations inépuisable.
Un autre site utile est le site StackExchange dédié à TeX et LaTeX.