Argumenty opcjonalne LaTeX


Odpowiedzi:


180

Przykład z przewodnika :

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

23
Myślę, że chodziło o to, jak określić, czy podano opcjonalny argument, a nie domyślny.
— Konrad Rudolph

45
Chociaż to prawda, znalazłem to pytanie, szukając sposobu na podanie domyślnego argumentu, więc ta odpowiedź była dla mnie najbardziej przydatna.
— Tanner Swett

26

Ogólną ideą tworzenia „argumentów opcjonalnych” jest najpierw zdefiniowanie polecenia pośredniego, które skanuje naprzód, aby wykryć, jakie znaki pojawią się jako następne w strumieniu tokenów, a następnie wstawia odpowiednie makra, aby odpowiednio przetworzyć nadchodzące argumenty. Może to być dość żmudne (choć nie trudne) przy użyciu ogólnego programowania TeX. LaTeX \@ifnextcharjest całkiem przydatny do takich rzeczy.

Najlepszą odpowiedzią na Twoje pytanie jest skorzystanie z nowego xparsepakietu. Jest częścią pakietu programowania LaTeX3 i zawiera rozbudowane funkcje definiowania poleceń z dość dowolnymi opcjonalnymi argumentami.

W twoim przykładzie masz \secmakro, które przyjmuje jeden lub dwa argumenty stężone. Zostałoby to zaimplementowane przy użyciu xparse:

\ documentclass {artykuł}
\ usepackage {xparse}
\ begin {document}
\ DeclareDocumentCommand \ sec {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {i # 2}%
    }%
}
(\ sec {Cześć})
(\ sec {Cześć} {Cześć})
\ end {document}

Argument { m g }definiuje argumenty \sec; moznacza „argument obowiązkowy” i gjest „opcjonalnym argumentem napiętym”. \IfNoValue(T)(F)można następnie użyć do sprawdzenia, czy drugi argument był rzeczywiście obecny, czy nie. Zobacz dokumentację dla innych typów opcjonalnych argumentów, które są dozwolone.


4
Będzie! To nie działa. (Hello and ) (Hello and Hi)
— Wynik

Dzięki za opinię, Alexey. Podejrzewam, że używasz starszej wersji xparse; ostatnio wykonano nad tym dużo pracy. Właśnie ukazał się TeX Live 2009 :)
— Will Robertson

24

Wszystko to pokazuje, że ciężko jest stworzyć ładną, elastyczną (lub zabronić przeciążonej) funkcji w LaTeX !!! (ten kod TeX wygląda dla mnie jak grecki)

cóż, żeby dodać mój niedawny (aczkolwiek nie tak elastyczny) rozwój, oto czego ostatnio użyłem w mojej pracy doktorskiej, z

\usepackage{ifthen}  % provides conditonals...

Uruchom polecenie, domyślnie ustawiane jako puste polecenie „opcjonalne”:

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

Następnie każę makro ustawić zmienną tymczasową \ temp {}, w różny sposób w zależności od tego, czy opcjonalny argument jest pusty. Można to rozszerzyć na dowolny przekazany argument.

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

Następnie uruchamiam makro przy użyciu zmiennej \ temp {} w dwóch przypadkach. (Tutaj po prostu ustawia krótki podpis tak, aby był równy długiemu podpisowi, jeśli nie został określony przez użytkownika).

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

W tym przypadku sprawdzam tylko pojedynczy, „opcjonalny” argument, który dostarcza \ newcommand {}. Gdybyś miał ustawić to dla, powiedzmy, 3 "opcjonalnych" argumentów, nadal musiałbyś wysłać 3 puste argumenty ... np.

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

co jest dość głupie, wiem, ale to mniej więcej na tyle, na ile mam zamiar posunąć się do LaTeX-a - po prostu nie jest to aż tak sensowne, kiedy zacznę patrzeć na kod TeX-a ... Podoba mi się jednak metoda xparse pana Robertsona, być może ja spróbuję ...


Podoba mi się to podejście. Jest bardziej „programistyczny” i dlatego jest bardziej czytelny. Dobra robota!
— kochany.by.Jezus

11

Wszystko, czego potrzebujesz, to:

\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

Myślałem, że TeX rozumie jako parametry odpowiednią liczbę pierwszych „pudełek” po poleceniu. to „pudełko” jest zapisane w nawiasach klamrowych lub jest to jeden symbol. To znaczy. x^2+1lub x^{2+1} Mam pytanie, czy twoje polecenie sprawdza obecność szelek? Czy jest możliwe utworzenie polecenia LaTeX, które będzie \secdawało: „A, b, c i d” dla polecenia \sec{A}[b,c,d], „A i b” dla \sec{A}[b] and "A" for \ sec {A} `?
— Crowley

Masz dwa pytania. 1) Tak, moje polecenie sprawdza obecność szelek. 2) Tak, jest możliwe utworzenie makra dla \sec{A}[b,c,d]lub \sec{A}[b]lub \sec{A}.
— Alexey Malistov

6

Miałem podobny problem, gdy chciałem utworzyć polecenie, \dxaby skrócić \;\mathrm{d}x(tj. Wstawić dodatkową spację przed różniczką całki i ustawić „d” w pozycji pionowej). Ale chciałem też uczynić go na tyle elastycznym, aby zawierał zmienną integracji jako opcjonalny argument. W preambule umieściłem następujący kod.

\usepackage{ifthen}

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

Następnie

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

daje \ dx z opcjonalnym argumentem


-1

Oto moja próba, ale nie jest dokładnie zgodna z twoimi specyfikacjami. Nie w pełni przetestowany, więc bądź ostrożny.

\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"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.