Pergunta

Como você cria um comando com argumentos opcionais em LaTeX? Algo como:

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

Então, eu posso chamá-lo assim

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
Foi útil?

Solução

Exemplo de o guia :

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

Outras dicas

A idéia geral por trás da criação "argumentos opcionais" é a primeira a definir um comando intermediário que scans antes de detectar o que os personagens são chegando próximo no fluxo de token e, em seguida, insere as macros relevantes para processar o argumento (s) chegando como apropriada. Isso pode ser bastante tedioso (embora não seja difícil) utilizando programação TeX genérico. \@ifnextchar do LaTeX é bastante útil para essas coisas.

A melhor resposta para sua pergunta é usar o novo pacote xparse. É parte da suíte de programação LaTeX3 e contém recursos extensos para definir os comandos com bastante arbitrárias argumentos opcionais.

No seu exemplo você tem uma macro \sec que ou leva um ou dois argumentos apoiados. Este seria implementado utilizando xparse com o seguinte:

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

O { m g } argumento define os argumentos de \sec; meios m "argumento obrigatório" e g é "argumento braced opcional". \IfNoValue(T)(F) pode, então, ser utilizado para verificar se o segundo argumento era de facto presente ou não. Consulte a documentação para os outros tipos de argumentos opcionais que são permitidos.

Todos do show acima ele pode ser duro para fazer um bom, flexível (ou proibir uma sobrecarregada) função em LaTeX !!! (Que TeX olhares código como grego para mim)

bem, apenas para adicionar minha recente (embora não tão flexível) de desenvolvimento, aqui está o que eu usei recentemente em minha tese doc, com

\usepackage{ifthen}  % provides conditonals...

Iniciar o comando, com o "opcional" conjunto de comandos em branco por padrão:

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

Em seguida, tenho o conjunto macro uma variável temporária, \ temp {}, de forma diferente, dependendo se ou não o argumento opcional é em branco. Isso pode ser estendido a qualquer argumento passado.

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

Então eu executar a macro usando a variável \ temp {} para os dois casos. (Aqui ele só define o curto-caption para igualar a longo legenda, se não foi especificado pelo usuário).

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

Neste caso eu só verificar o, argumento single "opcional" que \ newcommand {} fornece. Se você fosse para configurá-lo para, digamos, 3 args "opcionais", você ainda tem que enviar os 3 args em branco ... por exemplo.

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

que é muito bobo, eu sei, mas isso é quase tão longe como eu estou indo para ir com LaTeX - ele só não é que sensical uma vez que eu começar a olhar para o código TeX ... Eu gosto método xparse do Sr. Robertson embora , talvez eu vou tentar ...

Tudo que você precisa é o seguinte:

\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

Eu tive um problema semelhante, quando eu queria criar um comando, \dx, para abreviar \;\mathrm{d}x (ou seja, colocar um espaço extra antes do diferencial da integral e ter a "d" em pé também). Mas então eu também queria torná-lo o suficiente flexível para incluir a variável de integração como um argumento opcional. Eu coloquei o seguinte código no preâmbulo.

\usepackage{ifthen}

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

Em seguida

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

\ dx com opcional argumento

Aqui está a minha tentativa, ele não segue suas especificações exatamente embora. Não totalmente testada, para ser cauteloso.

\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"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top