125 votes

Arguments optionnels de LaTeX

Comment créer une commande avec des arguments optionnels dans LaTeX ? Quelque chose comme :

\newcommand{\sec}[2][]{
    \section*{#1
        \ifsecondargument
            and #2
        \fi}
    }
}

Ensuite, je peux l'appeler comme

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi

165voto

miku Points 63392

Exemple de la guide :

\newcommand{\example}[2][YYY]{Mandatory arg: #2;
                                 Optional arg: #1.}

This defines \example to be a command with two arguments, 
referred to as #1 and #2 in the {<definition>}--nothing new so far. 
But by adding a second optional argument to this \newcommand 
(the [YYY]) the first argument (#1) of the newly defined 
command \example is made optional with its default value being YYY.

Thus the usage of \example is either:

   \example{BBB}
which prints:
Mandatory arg: BBB; Optional arg: YYY.
or:
   \example[XXX]{AAA}
which prints:
Mandatory arg: AAA; Optional arg: XXX.

26voto

Will Robertson Points 19581

L'idée générale derrière la création d'"arguments optionnels" est de définir d'abord une commande intermédiaire qui analyse l'avenir pour détecter les caractères suivants dans le flux de jetons et qui insère ensuite les macros appropriées pour traiter le(s) argument(s) suivant(s). Cela peut être assez fastidieux (mais pas difficile) en utilisant la programmation TeX générique. LaTeX \@ifnextchar est très utile pour ce genre de choses.

La meilleure réponse à votre question est d'utiliser le nouvel outil de gestion de l'information de l'entreprise. xparse paquet. Il fait partie de la suite de programmation LaTeX3 et contient des fonctionnalités étendues pour définir des commandes avec des arguments optionnels assez arbitraires.

Dans votre exemple, vous avez un \sec qui prend un ou deux arguments entre crochets. Ceci serait implémenté en utilisant xparse avec les éléments suivants :

\\documentclass{article}
\\usepackage{xparse}
\\begin{document}
\\DeclareDocumentCommand\\sec{ m g }{%
    {#1%
        \\IfNoValueF {#2} { and #2}%
    }%
}
(\\sec{Hello})
(\\sec{Hello}{Hi})
\\end{document}

L'argument { m g } définit les arguments de \sec ; m signifie "argument obligatoire" et g est "argument optionnel entre crochets". \IfNoValue(T)(F) peut alors être utilisé pour vérifier si le second argument était bien présent ou non. Consultez la documentation pour connaître les autres types d'arguments optionnels autorisés.

23voto

Demis Points 81

Tout ce qui précède montre qu'il peut être difficile de faire une fonction agréable et flexible (ou, à défaut, surchargée) en LaTeX ! !! (ce code TeX ressemble à du grec pour moi)

Pour ajouter mon développement récent (bien que moins flexible), voici ce que j'ai récemment utilisé dans mon document de thèse, avec

\usepackage{ifthen}  % provides conditonals...

Lance la commande, avec le paramètre "optionnel" vide par défaut :

\newcommand {\figHoriz} [4] []  {

Je demande ensuite à la macro de définir une variable temporaire, \temp {}, différemment selon que l'argument optionnel est vide ou non. Ceci pourrait être étendu à tout argument passé.

\ifthenelse { \equal {#1} {} }  %if short caption not specified, use long caption (no slant)
    { \def\temp {\caption[#4]{\textsl{#4}}} }   % if #1 == blank
    { \def\temp {\caption[#1]{\textsl{#4}}} }   % else (not blank)

Ensuite, j'exécute la macro en utilisant la fonction \temp {} pour les deux cas. (Ici, la légende courte est simplement égale à la légende longue si elle n'a pas été spécifiée par l'utilisateur).

\begin{figure}[!]
    \begin{center}
        \includegraphics[width=350 pt]{#3}
        \temp   %see above for caption etc.
        \label{#2}
    \end{center}
\end{figure}
}

Dans ce cas, je ne vérifie que l'unique argument "facultatif" que l'on peut utiliser. \newcommand {} fournit. Si vous deviez le configurer pour, disons, 3 args "optionnels", vous devriez toujours envoyer les 3 args vides... ex.

\MyCommand {first arg} {} {} {}

ce qui est assez stupide, je sais, mais c'est à peu près tout ce que je vais faire avec LaTeX - ce n'est tout simplement pas si sensé une fois que je commence à regarder le code TeX... J'aime bien la méthode xparse de M. Robertson, je vais peut-être l'essayer...

12voto

Alexey Malistov Points 13526

Tout ce dont vous avez besoin est le suivant :

\makeatletter
\def\sec#1{\def\tempa{#1}\futurelet\next\sec@i}% Save first argument
\def\sec@i{\ifx\next\bgroup\expandafter\sec@ii\else\expandafter\sec@end\fi}%Check brace
\def\sec@ii#1{\section*{\tempa\ and #1}}%Two args
\def\sec@end{\section*{\tempa}}%Single args
\makeatother

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi

0voto

dreamlax Points 47152

Voici ma tentative, elle ne suit pas exactement vos spécifications. Pas entièrement testé, donc soyez prudent.

\newcount\seccount

\def\sec{%
    \seccount0%
    \let\go\secnext\go
}

\def\secnext#1{%
    \def\last{#1}%
    \futurelet\next\secparse
}

\def\secparse{%
    \ifx\next\bgroup
        \let\go\secparseii
    \else
        \let\go\seclast
    \fi
    \go
}

\def\secparseii#1{%
    \ifnum\seccount>0, \fi
    \advance\seccount1\relax
    \last
    \def\last{#1}%
    \futurelet\next\secparse
}

\def\seclast{\ifnum\seccount>0{} and \fi\last}%

\sec{a}{b}{c}{d}{e}
% outputs "a, b, c, d and e"

\sec{a}
% outputs "a"

\sec{a}{b}
% outputs "a and b"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X