2009-11-28 19 views
88

¿Cómo se crea un comando con argumentos opcionales en LaTeX? Algo así como:LaTeX Argumentos opcionales

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

A continuación, se puede llamar así como

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

pregunta relevante: [Diferentes definiciones de comandos con y sin argumento opcional] (http://tex.stackexchange.com/q/308/1347) . –

Respuesta

111

Ejemplo 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. 
+15

Creo que la pregunta era sobre cómo determinar * si * se proporcionó un argumento opcional, no proporcionando un valor predeterminado. –

+28

Aunque es cierto, encontré esta pregunta mientras buscaba una manera de proporcionar un argumento predeterminado, por lo que esta respuesta fue la más útil para mí. –

18

La idea general detrás de la creación de "argumentos opcionales" es definir primero un comando intermedio que explora adelante para detectar qué caracteres aparecen a continuación en la secuencia de tokens y luego inserta las macros relevantes para procesar los argumentos que se aproximan según sea apropiado. Esto puede ser bastante tedioso (aunque no difícil) al usar programación TeX genérica. El \@ifnextchar de LaTeX es bastante útil para tales cosas.

La mejor respuesta para su pregunta es usar el nuevo paquete xparse. Es parte del paquete de programación LaTeX3 y contiene amplias funciones para definir comandos con argumentos opcionales bastante arbitrarios.

En su ejemplo tiene una macro \sec que toma uno o dos argumentos reforzados. Esto se implementa utilizando xparse con lo siguiente:

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

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

+4

Will! No funciona. Salida: '(Hola y) (Hola y Hola)' –

+0

Gracias por los comentarios, Alexey. Sospecho que estás usando una versión anterior de xparse; ha habido mucho trabajo hecho recientemente. TeX Live 2009 acaba de ser lanzado :) –

12

Todo lo que necesita es la siguiente:

\makeatletter 
\def\sec#1{\def\tempa{#1}\futurelet\next\[email protected]}% Save first argument 
\def\[email protected]{\ifx\next\bgroup\expandafter\[email protected]\else\expandafter\[email protected]\fi}%Check brace 
\def\[email protected]#1{\section*{\tempa\ and #1}}%Two args 
\def\[email protected]{\section*{\tempa}}%Single args 
\makeatother 

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

Pensé que TeX entiende como parámetros el conteo apropiado de las primeras 'cajas' después del comando. esta 'caja' está escrita con llaves o es un símbolo. Es decir. 'x^2 + 1' o' x^{2 + 1} ' Tengo una pregunta, ¿su comando prueba la presencia de llaves? ¿Es posible crear el comando LaTeX '\ sec' produciendo: " A, b, c y d "para el comando' \ sec {A} [b, c, d] ', " A y b "para' \ sec {A} [b] y "A" para '\ sec {A}'? – Crowley

+0

Tiene 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}'. –

-1

Aquí está mi intento, no se sigue exactamente sus especificaciones sin embargo. No se ha probado completamente, 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" 
17

Todo el espectáculo por encima de difícil que puede ser para hacer una buena y flexible (o prohibir una sobrecarga) en función del látex !!! (Que el código TeX parece griego para mí)

así, sólo para añadir mi desarrollo reciente (aunque no tan flexible), esto es lo que he usado recientemente en mi documento de tesis, con

\usepackage{ifthen} % provides conditonals... 

de inicio el comando, con el comando "opcional" conjunto blanco de forma predeterminada:

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

entonces tengo la macro establece una variable temporal, \ temp {}, de manera diferente dependiendo de si o no el argumento opcional está en blanco. Esto podría extenderse a cualquier argumento pasado.

\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 utilizando la variable \ temp {} para los dos casos. (Aquí solo establece el subtítulo para igualar el 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 único argumento "opcional" que \ newcommand {} proporciona. Si tuviera que configurarlo para, digamos, 3 argumentos "opcionales", todavía tendría que enviar los 3 argumentos en blanco ... por ejemplo.

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

que es bastante tonto, lo sé, pero eso es por lo que yo voy a ir con LaTeX - no se trata sólo de que sensical una vez que empezar a buscar en código TeX ... me gusta el Sr. xparse método de Robertson embargo, tal vez voy a intentarlo ...

+0

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

1

tuve un problema similar, cuando quería crear un comando, \dx, para abreviar \;\mathrm{d}x (es decir, poner un espacio extra antes de que el 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 un 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}} 
} 

Entonces

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

da \dx with optional argument

Cuestiones relacionadas