Comment utiliser d’autres délimiteurs que les crochets et les accolades dans une commande ?#

Vous avez sans doute remarqué que certaines commandes ont leurs arguments délimités par d’autres caractères que des crochets ou des accolades. Par exemple, avec TikZ, vous pouvez tracer une ligne avec la commande :

\draw (0,0) to[line to] (1,0);

qui utilise des parenthèses, des virgules, un point-virgule et le mot-clef to.

Imaginons que nous voulions définir une commande qui nous permet de mettre en forme des définitions. Si l’argument optionnel note est spécifié, la définition est placée dans une note de bas de page, sinon elle est mise dans le corps du texte entre crochets. Le résultat pourrait ressembler à ceci :

Les commandes de \TeX{} sont en réalité des
\emph{macros} [\textsc{macro} =
  chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres],
ce qui ouvre des perspectives fort intéressantes.

On pourrait, bien sûr créer une macro avec \newcommand qui permettrait d’écrire :

Les commandes de \TeX{} sont en réalité des
\definir{macros}{macro}
  {chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres},
ce qui ouvre des perspectives fort intéressantes.

Toutefois, le codage suivant serait plus expressif et faciliterait la lecture :

Les commandes de \TeX{} sont en réalité des
\definir{macros -> macro =
  chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres},
ce qui ouvre des perspectives fort intéressantes.

Note

On utilise = plutôt que : car celui-ci est redéfini par babel, ce qui empêche de l’utiliser comme délimiteur.

Voyons cela.

1.  Avec \def#

Par défaut, la primitive de \def prend comme argument la première unité qui suit (caractère, groupe ou commande).

\def\madef#1#2{}

\madef Le toutou % #1 = L, #2 = e

\madef {Le} {toutou} % #1 = Le, #2 = toutou

Cependant, on peut aussi introduire des délimiteurs dans la liste des arguments. Il peut s’agir de caractères ou de commandes (lesquelles ne seront pas interprétées). Une commande qui s’approcherait de ce que l’on souhaite pourrait donc être :

\def\definition[#1] #2 -> #3 = #4\findedefinition{%
  \def\literalnote{note}%
  \def\optionarg{#1}%
  \ifx\optionarg\literalnote
    \textit{#2}\footnote{\textsc{#3} = #4.}%
  \else
    \textit{#2} [\textsc{#3} = #4]%
  \fi
}

Comme la commande \findedefinition n’est pas interprétée par mais simplement utilisée comme délimiteur, elle n’a pas besoin d’être définie. Notez que les espaces sont aussi prises en compte comme délimiteurs.

À ce stade, on peut donc écrire :

Les commandes de \TeX{} sont en réalité des
\definition[] macros -> macro =
  chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres\findedefinition,
ce qui ouvre des perspectives fort intéressantes.

ou

Les commandes de \TeX{} sont en réalité des
\definition[note] macros -> macro =
  chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres\findedefinition,
ce qui ouvre des perspectives fort intéressantes.

On peut ensuite définir la commande \definir présentée ci-dessus comme suit, avec un argument optionnel, en utilisant la macro \newcommand :

\newcommand*{\definir}[2][]{\definition[#1] #2\findedefinition}

Voici donc l’implémentation complète, où la commande intermédiaire n’est plus accessible par l’utilisateur :

%!TEX lualatex

\documentclass[french]{article}
\usepackage[a5paper]{geometry}
\usepackage{babel}

\makeatletter

\newcommand*{\definir}[2][]{\definiti@n[#1] #2\findedefiniti@n}

\def\definiti@n[#1] #2 -> #3 = #4\findedefiniti@n{%
  \def\literalnote{note}%
  \def\optionarg{#1}%
  \ifx\optionarg\literalnote
    \textit{#2}\footnote{\textsc{#3} : #4.}%
  \else
    \textit{#2} [\textsc{#3} : #4]%
  \fi
}

\makeatother

\begin{document}

Les commandes de \TeX{} sont en réalité des
\definir{macros -> macro =
  chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres},
ce qui ouvre des perspectives fort intéressantes.

Par exemple, ce document utilise des
\definir[note]{macros -> macro =
  Faut-il vraiment répéter ? D'accord, mais en note.
  Chaîne de caractères que le processeur doit remplacer
  par une autre chaîne de caractère ou par une autre macro,
  éventuellement en substituant des paramètres}.
  
\end{document}

Sources

  • Victor Eijkhout, by topic, chap. 11