Argumentos opcionales de LaTeX

Respuestas:

176

Ejemplo de la guía :

\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
fuente
21
Creo que la pregunta era sobre cómo determinar si se proporcionó un argumento opcional, sin proporcionar un valor predeterminado.
Konrad Rudolph, el
43
Aunque eso es cierto, encontré esta pregunta mientras buscaba una forma de proporcionar un argumento predeterminado, por lo que esta respuesta fue la más útil para mí.
Tanner Swett
26

La idea general detrás de la creación de "argumentos opcionales" es definir primero un comando intermedio que escanea hacia adelante para detectar qué caracteres aparecerán a continuación en la secuencia de tokens y luego inserta las macros relevantes para procesar los argumentos que surjan según corresponda. Esto puede ser bastante tedioso (aunque no difícil) con la programación genérica de TeX. LaTeX \@ifnextchares bastante útil para tales cosas.

La mejor respuesta para su pregunta es usar el nuevo xparsepaquete. Forma parte de la suite de programación LaTeX3 y contiene amplias funciones para definir comandos con argumentos opcionales bastante arbitrarios.

En su ejemplo, tiene una \secmacro que toma uno o dos argumentos entre paréntesis. Esto se implementaría usando xparselo siguiente:

\ documentclass {artículo}
\ usepackage {xparse}
\ begin {document}
\ DeclareDocumentCommand \ sec {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {y # 2}%
    }%
}
(\ sec {Hola})
(\ sec {Hola} {Hola})
\ end {documento}

El argumento { m g }define los argumentos de \sec; msignifica "argumento obligatorio" y ges "argumento entre paréntesis opcional". \IfNoValue(T)(F)entonces se puede usar para verificar si el segundo argumento estaba realmente presente o no. Consulte la documentación para los otros tipos de argumentos opcionales que están permitidos.

Will Robertson
fuente
44
¡Será! No funciona. Salida:(Hello and ) (Hello and Hi)
Alexey Malistov
Gracias por los comentarios, Alexey. Sospecho que estás usando una versión anterior de xparse; Ha habido mucho trabajo recientemente. TeX Live 2009 acaba de ser lanzado :)
Will Robertson
24

¡Todo lo anterior muestra que puede ser una función agradable, flexible (o prohibir una sobrecarga) en LaTeX! (ese código TeX me parece griego)

bueno, solo para agregar mi desarrollo reciente (aunque no tan flexible), esto es lo que he usado recientemente en mi documento de tesis, con

\usepackage{ifthen}  % provides conditonals...

Inicie el comando, con el comando "opcional" en blanco por defecto:

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

Luego hago que la macro establezca una variable temporal, \ temp {}, de manera diferente dependiendo de si el argumento opcional está en blanco o no. Esto podría extenderse a cualquier argumento aprobado.

\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)

Luego ejecuto la macro usando la variable \ temp {} para los dos casos. (Aquí solo establece el título corto para que sea igual al título largo si no fue especificado por el usuario).

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

En este caso, solo verifico el argumento único "opcional" que proporciona \ newcommand {}. Si tuviera que configurarlo para, digamos, 3 args "opcionales", todavía tendría que enviar los 3 args en blanco ... por ejemplo.

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

lo cual es bastante tonto, lo sé, pero eso es lo más lejos que voy a ir con LaTeX: simplemente no es tan sensato una vez que empiezo a mirar el código TeX ... Sin embargo, me gusta el método xparse del Sr. Robertson, quizás Lo intentaré ...

Demis
fuente
Me gusta este enfoque. Es más "similar a la programación" y, por lo tanto, más fácil de leer. ¡Buen trabajo!
amado.por.Jesús
11

Todo lo que necesitas es lo siguiente:

\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
fuente
Pensé que TeX entiende como parámetros el recuento apropiado de los primeros 'cuadros' después del comando. esta 'caja' está escrita entre llaves o es un símbolo. Es decir. x^2+1o x^{2+1} Entonces tengo una pregunta, ¿su comando prueba la presencia de llaves? ¿Es posible crear un comando LaTeX que \secproduzca: "A, b, c y d" para el comando \sec{A}[b,c,d], "A y b" para \sec{A}[b] and "A" for \ sec {A} `?
Crowley
Tienes dos preguntas 1) Sí, mi comando prueba la presencia de llaves. 2) Sí, es posible crear macro para \sec{A}[b,c,d]o \sec{A}[b]o \sec{A}.
Alexey Malistov el
6

Tuve un problema similar, cuando quería crear un comando, \dxpara abreviar \;\mathrm{d}x(es decir, poner un espacio adicional antes del diferencial de la integral y tener la "d" en posición vertical también). Pero también quería hacerlo lo suficientemente flexible como para incluir la variable de integración como argumento opcional. Puse el siguiente código en el preámbulo.

\usepackage{ifthen}

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

Luego

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

da \ dx con argumento opcional

zar
fuente
-1

Aquí está mi intento, aunque no sigue exactamente tus especificaciones. No completamente probado, así que tenga cuidado.

\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
fuente