Options de classe et création

Quand les classes toutes faites ne suffisent plus, vous pouvez écrire la vôtre. Cette page traite de la création d’une classe. Nous commençons par les options standard qu’une classe accepte en général (taille de police, papier, colonnes, etc.), puis nous construisons le contenu d’un fichier .cls ou .sty : identification avec \ProvidesClass, déclaration d’options avec \DeclareOption, exécution avec \ProcessOptions, appui sur une classe existante avec \LoadClass, jusqu’à un exemple complet qui étend article. Pour utiliser les options côté document, voyez “Document class & preamble”.

Classe ou package ?

Avant d’écrire quoi que ce soit, décidez si vous créez une classe (.cls) ou un package (.sty). Une classe définit le type même du document et se charge exactement une fois, avec \documentclass ; elle fournit l’ossature générale et l’apparence par défaut d’un article, d’un livre ou de diapositives. Un package, lui, se charge avec \usepackageautant que nécessaire — et ajoute des fonctions indépendantes du type de document (amsmath pour les maths, graphicx pour les figures, etc.).

Pour reprendre le clsguide officiel, le critère est simple : si la fonction peut être utilisée avec n’importe quelle classe de document, faites-en un package ; sinon, faites-en une classe. Définir toute une apparence : classe. Ajouter seulement une fonction : package. Les conventions d’écriture sont presque identiques ; seuls les noms de commandes ont une variante Class et une variante Package (\ProvidesClass\ProvidesPackage, \LoadClass\RequirePackage, \PassOptionsToClass\PassOptionsToPackage).

Les options standard acceptées par votre classe

Les utilisateurs passeront des options à votre classe comme à une classe standard. Au minimum, il faut donc prendre en charge les options habituelles : 10pt / 11pt / 12pt pour la taille de base, a4paper / letterpaper pour le papier, onecolumn / twocolumn pour les colonnes, oneside / twoside pour le recto seul ou recto verso, et draft (qui marque les lignes débordantes par une barre noire ; son opposé est final). Il n’est pas nécessaire de les implémenter vous-même : comme on le verra dans “transmettre les options à une classe de base”, l’usage consiste simplement à les forwarder vers une classe de base telle que article.

OptionSignificationDéfaut
10pt / 11pt / 12ptTaille de base du corps10pt
a4paper / letterpaperFormat du papier (aussi b5paper, legalpaper, etc.)letterpaper
onecolumn / twocolumnUne colonne / deux colonnesonecolumn
oneside / twosideMise en page recto seul / recto versooneside (mais twoside pour book)
draft / finalMarquer ou non les lignes débordantes par une barre noirefinal

Pour des exemples concrets de spécification et d’utilisation de ces options côté \documentclass[...], ainsi que des options propres à book comme openright, consultez la page sœur “Document class & preamble”. À partir d’ici, nous nous concentrons sur l’écriture de la classe qui les reçoit.

Identifier le fichier dès le début

Les deux premières lignes d’un fichier de classe (myclass.cls) sont presque du boilerplate. D’abord, \NeedsTeXFormat{LaTeX2e} déclare que le fichier est destiné à LaTeX2e ; le charger avec un format plus ancien déclenche un avertissement. Ensuite, \ProvidesClass{myclass}[2026/01/01 v1.0 ...] annonce le nom de classe, la date de publication, la version et une brève description. La partie entre crochets est facultative, mais elle permet aux utilisateurs de demander une version minimale par la date, au format YYYY/MM/DD, comme \documentclass{...}[2026/01/01], et l’identification est inscrite dans le log.

Si vous écrivez un package, la commande correspondante est \ProvidesPackage{mypackage}[2026/01/01 v1.0 ...] ; \NeedsTeXFormat est commun aux deux. Règle ferme : le nom dans \ProvidesClass / \ProvidesPackage doit correspondre au vrai nom de fichier ; dans myclass.cls, on écrit donc toujours \ProvidesClass{myclass}.

latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}[2026/01/01 v1.0 My example class]

Déclarer des options — \DeclareOption

Chaque option acceptée par votre classe se déclare avec \DeclareOption{option}{code}. Quand l’utilisateur spécifie cette option, son code s’exécute au moment où \ProcessOptions est atteint (voir plus bas). Par exemple, vous pouvez fournir votre propre interrupteur draft qui met en place un booléen.

Le réceptacle pour les options que vous n’avez pas déclarées est la forme étoilée \DeclareOption*{code}. À l’intérieur, \CurrentOption se développe en nom de l’option en cours de traitement. La ligne la plus fréquente dans une classe personnalisée transmet toute option inconnue directement à la classe de base. Grâce à elle, les utilisateurs peuvent passer naturellement des options standard comme 10pt ou a4paper, même si vous ne les avez jamais déclarées vous-même.

latex
% pass anything we do not handle ourselves on to article
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}

Dans un package, on utilise l’équivalent \PassOptionsToPackage{\CurrentOption}{base}. Si vous voulez appliquer des valeurs par défaut avant \ProcessOptions, écrivez \ExecuteOptions{a4paper,11pt} : le code de ces options s’exécute d’abord, même si l’utilisateur ne précise rien.

Traiter les options, puis passer à une classe de base

Déclarer des options ne fait rien tout seul ; leur code ne s’exécute que lorsque vous appelez \ProcessOptions. En pratique, on écrit presque toujours \ProcessOptions\relax. Comme il existe aussi une forme étoilée \ProcessOptions*, le \relax final est l’idiome qui sélectionne sûrement la forme non étoilée. \ProcessOptions non étoilé traite les options dans l’ordre de leur déclaration ; la forme étoilée les traite dans l’ordre où l’appelant les a données.

Construire une mise en page de zéro demande beaucoup de travail ; la plupart des classes personnalisées s’appuient donc sur une classe existante. C’est le rôle de \LoadClass[options]{article}, qui charge toutes les commandes et le style de article.cls (vous pouvez aussi passer twocolumn et autres dans les crochets). \LoadClass ne s’utilise qu’à l’intérieur d’un fichier de classe. L’ordre compte : pour que les options données par l’utilisateur dans \documentclass[...] atteignent la classe de base, placez \LoadClass après le traitement des options (\ProcessOptions). Configurez d’abord la transmission, laissez \ProcessOptions répartir les options, puis chargez la base.

Si vous voulez simplement donner à la classe de base exactement les mêmes options que celles reçues par votre classe, \LoadClassWithOptions{article} est pratique : il transmet telles quelles les options globales de la classe. Pour écrire un package, utilisez \RequirePackage à la place de \LoadClass (l’équivalent côté auteur de \usepackage dans le préambule), et \RequirePackageWithOptions pour tout transmettre.

Tout ce qui suit \LoadClass est l’endroit où s’exprime enfin le caractère de votre classe : redéfinir les titres avec \renewcommand, ajuster les marges avec \setlength, définir de nouvelles commandes et environnements avec \newcommand / \newenvironment, et charger les packages supplémentaires nécessaires avec \RequirePackage.

Exemple complet : une classe minimale qui étend article

En réunissant tout cela, on obtient ce .cls minimal. Il s’appuie sur article, ajoute sa propre option draft, transmet les options inconnues à article, puis règle les marges et définit une commande maison. Enregistrez-le sous myclass.cls et utilisez-le depuis un document avec \documentclass[11pt,a4paper]{myclass}.

latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}[2026/01/01 v1.0 My example class]

% --- declare options ---
\newif\ifmy@draft
\DeclareOption{draft}{\my@drafttrue}
% forward everything else to article
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}

% --- execute and load the base class ---
\ExecuteOptions{a4paper}      % a default if the user gives none
\ProcessOptions\relax
\LoadClass{article}

% --- this class's own setup ---
\RequirePackage[margin=25mm]{geometry}
\setlength{\parindent}{0pt}
\newcommand{\version}{v1.0}
\ifmy@draft \RequirePackage{draftwatermark}\fi

\endinput

Le \endinput final indique à LaTeX de ne plus rien lire dans ce fichier ; il est d’usage de l’inclure. Pour créer un package à la place, remplacez l’ouverture par \ProvidesPackage et \LoadClass par \RequirePackage : le même squelette devient un fichier .sty.

La méthode moderne : options clé-valeur (expl3)

Le mécanisme \DeclareOption ci-dessus reste parfaitement valable, mais il est surtout conçu pour des options de type interrupteur présent/absent. Pour du nouveau code qui veut des options clé-valeur naturelles comme name=value, l’approche recommandée aujourd’hui est l’interface du noyau LaTeX : déclarer les clés avec \DeclareKeys et les traiter avec \ProcessKeyOptions. Bâtie sur l3keys d’expl3 (LaTeX3), elle fait partie des noyaux LaTeX récents.

On faisait autrefois cela avec le package l3keys2e, mais le cœur de cette fonctionnalité a été intégré au noyau ; le nouveau code peut donc appeler \ProcessKeyOptions directement, sans charger le package. Cela dit, de nombreux tutoriels et packages existants restent centrés sur le style \DeclareOption, donc comprendre le squelette présenté ici reste utile. Pour passer aux options clé-valeur, consultez la section correspondante du clsguide actuel (“LaTeX2e for class and package writers”).

Un test minimal avant diffusion

Une classe affecte tout le document dès son chargement ; stabilisez donc son comportement avec un tout petit document de test avant d’écrire du vrai contenu. Vérifiez d’abord que les options standard comme 10pt, 11pt, a4paper et draft atteignent la classe de base, tandis que seules vos options propres sont traitées par votre code. Si cela échoue, la cause est généralement la position de \ProcessOptions / \ProcessKeyOptions, la transmission des options inconnues ou l’ordre de \LoadClass.

latex
\documentclass[11pt,a4paper,draft]{myclass}
\begin{document}
\section{Smoke test}
本文の基準サイズ、用紙、下書き表示、見出し、余白を確認する。
\end{document}
  • Le log identifie-t-il la classe ? Vérifiez que la date et la version de \ProvidesClass apparaissent dans le .log. Un désaccord entre nom de fichier et nom de classe crée de la confusion plus tard.
  • Les options standard sont-elles préservées ? Si 11pt ou twocolumn est ignoré, revoyez le gestionnaire qui transmet les options inconnues à la classe de base.
  • Les macros de document se comportent-elles bien dans le préambule et le corps ? Compilez un titre, une note, une figure et un tableau, car ce sont les premiers éléments que les vrais utilisateurs toucheront.
  • Gardez tout ce qui suit \endinput inerte. Des notes ou exemples laissés après peuvent être lus par surprise si le marqueur manque ou est déplacé.

Penser aussi à la forme de diffusion

Une classe personnalisée n’est vraiment testée non pas quand elle fonctionne pour vous, mais quand quelqu’un d’autre la charge dans un autre environnement. Au minimum, gardez le .cls, un court document d’exemple, un README et un historique ensemble, et assurez-vous que l’exemple compile tel quel. Dans le README, séparez les options transmises à la classe de base des options traitées par votre classe, afin que les utilisateurs voient où 11pt ou a4paper prennent effet. Placez dans l’exemple un titre, une liste, une figure ou un tableau et une bibliographie, pour vérifier ensemble les éléments qu’une classe casse le plus souvent en premier.

terminal
myclass/
  myclass.cls
  sample.tex
  README.md
  CHANGELOG.md

Avant diffusion, ajoutez \listfiles à l’exemple afin que le log enregistre les fichiers et versions chargés. Cela aide à diagnostiquer si un utilisateur possède un vieux myclass.cls local, ou si les packages requis sont bien chargés comme prévu. Comme une classe est le fondement de tout le document, un ordre de chargement, un traitement des options et des informations de log soigneux comptent davantage à long terme qu’une macro de corps supplémentaire.