Argumen Opsional LaTeX

132

Bagaimana Anda membuat perintah dengan argumen opsional di LaTeX? Sesuatu seperti:

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

Lalu, saya bisa menyebutnya seperti

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
Verhogen
sumber
5
Pertanyaan yang relevan: Definisi perintah berbeda dengan dan tanpa argumen opsional .
MS Dousti

Jawaban:

176

Contoh dari panduan ini :

\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
sumber
21
Saya pikir pertanyaannya adalah tentang bagaimana menentukan apakah argumen opsional diberikan, tidak memberikan default.
Konrad Rudolph
43
Meskipun itu benar, saya menemukan pertanyaan ini sambil mencari cara untuk memberikan argumen default, jadi jawaban ini adalah yang paling berguna bagi saya.
Tanner Swett
26

Gagasan umum di balik pembuatan "argumen opsional" adalah untuk pertama-tama mendefinisikan perintah perantara yang memindai ke depan untuk mendeteksi karakter apa yang muncul berikutnya dalam aliran token dan kemudian memasukkan makro yang relevan untuk memproses argumen yang muncul dengan tepat. Ini bisa sangat membosankan (walaupun tidak sulit) menggunakan pemrograman TeX generik. LaTeX's \@ifnextcharcukup berguna untuk hal-hal seperti itu.

Jawaban terbaik untuk pertanyaan Anda adalah menggunakan xparsepaket baru . Ini adalah bagian dari rangkaian pemrograman LaTeX3 dan berisi fitur luas untuk mendefinisikan perintah dengan argumen opsional yang cukup arbitrer.

Dalam contoh Anda, Anda memiliki \secmakro yang mengambil satu atau dua argumen yang diperkuat. Ini akan diterapkan xparsedengan menggunakan hal berikut:

\ documentclass {article}
\ usepackage {xparse}
\ begin {document}
\ DeclareDocumentCommand \ sec {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {dan # 2}%
    }%
}
(\ dtk {Halo})
(\ dtk {Halo} {Hai})
\ end {document}

Argumen { m g }mendefinisikan argumen \sec; mberarti "argumen wajib" dan g"argumen menguatkan opsional". \IfNoValue(T)(F)kemudian dapat digunakan untuk memeriksa apakah argumen kedua memang ada atau tidak. Lihat dokumentasi untuk jenis argumen opsional lain yang diperbolehkan.

Will Robertson
sumber
4
Akan! Tidak bekerja. Output:(Hello and ) (Hello and Hi)
Alexey Malistov
Terima kasih atas umpan baliknya, Alexey. Saya menduga Anda menggunakan versi xparse yang lebih lama; ada banyak pekerjaan yang dilakukan baru-baru ini. TeX Live 2009 baru saja dirilis :)
Will Robertson
24

Semua hal di atas menunjukkan kesulitan untuk membuat fungsi yang bagus, fleksibel (atau melarang kelebihan beban) di LaTeX !!! (kode TeX itu terlihat seperti Yunani bagi saya)

baik, hanya untuk menambahkan pengembangan saya baru-baru ini (walaupun tidak sefleksibel), inilah yang baru-baru ini saya gunakan dalam dokumen tesis saya, dengan

\usepackage{ifthen}  % provides conditonals...

Mulai perintah, dengan perintah "opsional" dikosongkan secara default:

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

Saya kemudian meminta makro mengatur variabel sementara, \ temp {}, berbeda tergantung pada apakah argumen opsional kosong atau tidak. Ini bisa diperluas ke argumen yang disahkan.

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

Kemudian saya menjalankan makro menggunakan variabel \ temp {} untuk dua kasus. (Di sini ia hanya mengatur teks pendek untuk sama dengan teks panjang jika tidak ditentukan oleh pengguna).

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

Dalam hal ini saya hanya memeriksa argumen "opsional" tunggal yang disediakan oleh \ newcommand {}. Jika Anda mengaturnya untuk, katakanlah, 3 argumen "opsional", Anda masih harus mengirim 3 argumen kosong ... mis.

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

yang cukup konyol, saya tahu, tapi itu tentang sejauh yang saya akan pergi dengan LaTeX - hanya saja tidak masuk akal begitu saya mulai melihat kode TeX ... Saya suka metode xparse Mr. Robertson, mungkin saya akan mencobanya ...

Demis
sumber
Saya suka pendekatan ini. Lebih "seperti pemrograman" dan karenanya lebih mudah dibaca. Kerja bagus!
loved.by.Yesus
11

Yang Anda butuhkan adalah sebagai berikut:

\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
sumber
Saya pikir TeX mengerti sebagai parameter yang sesuai dengan jumlah 'kotak' pertama setelah perintah. 'kotak' ini ditulis dalam kurung kurawal atau itu salah satu simbol. Yaitu. x^2+1atau x^{2+1} Jadi saya punya pertanyaan, apakah perintah Anda menguji keberadaan kawat gigi? Apakah mungkin membuat perintah LaTeX yang \secmenghasilkan: "A, b, c dan d" untuk perintah \sec{A}[b,c,d], "A and b" untuk \sec{A}[b] and "A" for \ sec {A} `?
Crowley
Anda punya dua pertanyaan. 1) Ya, perintah saya menguji keberadaan kawat gigi. 2) Ya, itu adalah mungkin untuk membuat makro untuk \sec{A}[b,c,d]atau \sec{A}[b]atau \sec{A}.
Alexey Malistov
6

Saya memiliki masalah yang sama, ketika saya ingin membuat perintah, \dxuntuk menyingkat \;\mathrm{d}x(yaitu menempatkan ruang ekstra sebelum diferensial integral dan memiliki "d" tegak juga). Tetapi kemudian saya juga ingin membuatnya cukup fleksibel untuk memasukkan variabel integrasi sebagai argumen opsional. Saya memasukkan kode berikut di pembukaan.

\usepackage{ifthen}

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

Kemudian

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

memberikan \ dx dengan argumen opsional

csar
sumber
-1

Inilah upaya saya, itu tidak mengikuti spesifikasi Anda dengan tepat. Tidak sepenuhnya diuji, jadi berhati-hatilah.

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