Arguments facultatifs LaTeX

Réponses:

176

Exemple du 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.
Miku
la source
21
Je pense que la question était de savoir comment déterminer si un argument facultatif a été donné, sans fournir de valeur par défaut.
Konrad Rudolph
43
Bien que ce soit vrai, j'ai trouvé cette question en cherchant un moyen de fournir un argument par défaut, donc cette réponse a été la plus utile pour moi.
Tanner Swett
26

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 scanne en avant pour détecter quels caractères viennent ensuite dans le flux de jetons, puis insère les macros appropriées pour traiter le ou les arguments à venir. Cela peut être assez fastidieux (mais pas difficile) en utilisant la programmation TeX générique. LaTeX \@ifnextcharest très utile pour de telles choses.

La meilleure réponse à votre question est d'utiliser le nouveau xparsepackage. 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 une \secmacro qui prend un ou deux arguments contreventés. Cela serait implémenté en utilisant xparseles éléments suivants:

\ documentclass {article}
\ usepackage {xparse}
\ begin {document}
\ DeclareDocumentCommand \ sec {mg} {%
    {#1%
        \ IfNoValueF {# 2} {et # 2}%
    }%
}
(\ sec {Bonjour})
(\ sec {Bonjour} {Salut})
\ end {document}

L'argument { m g }définit les arguments de \sec; msignifie "argument obligatoire" et gest "argument optionnel avec accolades". \IfNoValue(T)(F)peut alors être utilisé pour vérifier si le deuxième argument était bien présent ou non. Consultez la documentation pour les autres types d'arguments facultatifs autorisés.

Will Robertson
la source
4
Volonté! Ça ne marche pas. Sortie:(Hello and ) (Hello and Hi)
Alexey Malistov
Merci pour les commentaires, Alexey. Je soupçonne que vous utilisez une ancienne version de xparse; il y a eu beaucoup de travail à ce sujet récemment. TeX Live 2009 vient de sortir :)
Will Robertson
24

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

Eh bien, juste pour ajouter mon développement récent (mais pas aussi flexible), voici ce que j'ai récemment utilisé dans ma thèse, avec

\usepackage{ifthen}  % provides conditonals...

Démarrez la commande, avec la commande "facultative" vide par défaut:

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

J'ai alors la macro définir une variable temporaire, \ temp {}, différemment selon que l'argument optionnel est vide ou non. Cela 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 variable \ temp {} pour les deux cas. (Ici, il définit simplement la légende courte pour qu'elle soit é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 le seul argument "optionnel" fourni par \ newcommand {}. Si vous deviez le configurer pour, disons, 3 arguments "optionnels", vous devrez toujours envoyer les 3 arguments vides ... par exemple.

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

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

Demis
la source
J'aime cette approche. Est plus «programmatique» et donc plus facile à lire. Bon travail!
aimé.par.Jesus
11

Tout ce dont vous avez besoin est ce qui suit:

\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
Alexey Malistov
la source
Je pensais que TeX comprend comme paramètres le nombre approprié de premières «boîtes» après la commande. cette «boîte» est écrite entre accolades ou c'est un symbole. C'est à dire. x^2+1ou x^{2+1} Alors j'ai une question, votre commande teste-t-elle la présence d'accolades? Est-il possible de créer une commande LaTeX \secproduisant: "A, b, c et d" pour la commande \sec{A}[b,c,d], "A et b" pour \sec{A}[b] and "A" for \ sec {A} `?
Crowley
Vous avez deux questions. 1) Oui, ma commande teste la présence d'accolades. 2) Oui, il est possible de créer une macro pour \sec{A}[b,c,d]ou \sec{A}[b]ou \sec{A}.
Alexey Malistov
6

J'ai eu un problème similaire, quand je voulais créer une commande, \dxabréger \;\mathrm{d}x(c'est-à-dire mettre un espace supplémentaire avant le différentiel de l'intégrale et avoir le «d» à la verticale également). Mais j'ai également voulu le rendre suffisamment flexible pour inclure la variable d'intégration comme argument optionnel. J'ai mis le code suivant dans le préambule.

\usepackage{ifthen}

\newcommand{\dx}[1][]{%
   \ifthenelse{ \equal{#1}{} }
      {\ensuremath{\;\mathrm{d}x}}
      {\ensuremath{\;\mathrm{d}#1}}
}

ensuite

\begin{document}
   $$\int x\dx$$
   $$\int t\dx[t]$$
\end{document}

donne \ dx avec un argument optionnel

csar
la source
-1

Voici ma tentative, cela ne suit pas exactement vos spécifications. Pas entièrement testé, alors 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"
dreamlax
la source