Argumentos opcionais do LaTeX

Respostas:

176

Exemplo do 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.
miku
fonte
21
Eu acho que a pergunta era sobre como determinar se um argumento opcional foi fornecido, não fornecendo um padrão.
21430 Konrad Rudolph
43
Embora isso seja verdade, eu encontrei essa pergunta enquanto procurava uma maneira de fornecer um argumento padrão; portanto, essa resposta foi a mais útil para mim.
quer
26

A idéia geral por trás da criação de "argumentos opcionais" é definir primeiro um comando intermediário que avança para detectar quais caracteres serão apresentados a seguir no fluxo de tokens e, em seguida, insere as macros relevantes para processar os argumentos apresentados conforme apropriado. Isso pode ser bastante tedioso (embora não seja difícil) usando a programação TeX genérica. O LaTeX's \@ifnextcharé bastante útil para essas coisas.

A melhor resposta para sua pergunta é usar o novo xparsepacote. Faz parte do conjunto de programação LaTeX3 e contém recursos abrangentes para definir comandos com argumentos opcionais bastante arbitrários.

No seu exemplo, você tem uma \secmacro que aceita um ou dois argumentos entre chaves. Isso seria implementado usando xparseo seguinte:

\ documentclass {article}
\ usepackage {xparse}
\ begin {document}
\ DeclareDocumentCommand \ sec {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {e # 2}%
    }%
}
(\ seg {Olá})
(\ seg {Olá} {Olá})
\ end {document}

O argumento { m g }define os argumentos de \sec; msignifica "argumento obrigatório" e gé "argumento opcional". \IfNoValue(T)(F)pode então ser usado para verificar se o segundo argumento estava realmente presente ou não. Consulte a documentação para os outros tipos de argumentos opcionais permitidos.

Will Robertson
fonte
4
Vai! Não funciona. Saída:(Hello and ) (Hello and Hi)
Alexey Malistov
Obrigado pelo feedback, Alexey. Eu suspeito que você esteja usando uma versão mais antiga do xparse; Muito trabalho foi feito recentemente. TeX Live 2009 acaba de ser lançado :)
Will Robertson
24

Todas as opções acima mostram que pode ser difícil criar uma função agradável e flexível (ou proibir uma sobrecarga) no LaTeX !!! (esse código TeX parece grego para mim)

bem, apenas para adicionar meu desenvolvimento recente (embora não tão flexível), eis o que eu usei recentemente no meu documento de tese, com

\usepackage{ifthen}  % provides conditonals...

Inicie o comando, com o comando "opcional" definido em branco por padrão:

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

Em seguida, a macro define uma variável temporária, \ temp {}, de maneira diferente, dependendo se o argumento opcional está em branco ou não. 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 executo a macro usando a variável \ temp {} para os dois casos. (Aqui, apenas define a legenda curta para igualar a legenda longa, se não tiver sido especificada pelo usuário).

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

Nesse caso, só verifico o argumento único "opcional" fornecido por \ newcommand {}. Se você configurá-lo para, digamos, 3 args "opcionais", ainda precisará enviar os 3 args em branco ... por exemplo.

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

o que é bem bobo, eu sei, mas é o mais longe que eu vou usar o LaTeX - não é tão sensato assim que começo a olhar para o código TeX ... Eu gosto do método xparse do Sr. Robertson, talvez eu vou tentar ...

Demis
fonte
Eu gosto dessa abordagem. É mais "parecido com a programação" e, portanto, mais fácil de ler. Bom trabalho!
precisa saber é o seguinte
11

Tudo o 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
Alexey Malistov
fonte
Eu pensei que o TeX entende como parâmetros a contagem apropriada das primeiras 'caixas' após o comando. essa 'caixa' está escrita entre chaves ou é um símbolo. Ou seja. x^2+1ou x^{2+1} então eu tenho uma pergunta, seu comando testa a presença de chaves? É possível criar um comando LaTeX \secproduzindo: "A, b, c e d" para o comando \sec{A}[b,c,d], "A e b" para \sec{A}[b] and "A" for \ s {A} `?
30511 Crowley
Você tem duas perguntas. 1) Sim, meu comando testa a presença de chaves. 2) Sim, é possível criar macro para \sec{A}[b,c,d]ou \sec{A}[b]ou \sec{A}.
Alexey Malistov
6

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

\usepackage{ifthen}

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

Então

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

\ dx com argumento opcional

csar
fonte
-1

Aqui está minha tentativa, mas não segue exatamente suas especificações. Não totalmente testado, portanto, tenha 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
fonte