Đối số tùy chọn LaTeX


132

Làm thế nào để bạn tạo một lệnh với các đối số tùy chọn trong LaTeX? Cái gì đó như:

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

Sau đó, tôi có thể gọi nó như

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

Câu trả lời:


176

Ví dụ từ hướng dẫn :

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

21
Tôi nghĩ rằng câu hỏi là về cách xác định liệu một đối số tùy chọn đã được đưa ra, không cung cấp mặc định.
Konrad Rudolph

43
Mặc dù đó là sự thật, tôi đã tìm thấy câu hỏi này trong khi tìm cách cung cấp một đối số mặc định, vì vậy câu trả lời này là câu hỏi hữu ích nhất đối với tôi.
Tanner Swett

26

Ý tưởng chung đằng sau việc tạo "đối số tùy chọn" là trước tiên xác định một lệnh trung gian quét trước để phát hiện các ký tự nào sẽ xuất hiện tiếp theo trong luồng mã thông báo và sau đó chèn các macro có liên quan để xử lý (các) đối số sắp tới phù hợp. Điều này có thể khá tẻ nhạt (mặc dù không khó) bằng cách sử dụng lập trình TeX chung. LaTeX \@ifnextcharlà khá hữu ích cho những điều như vậy.

Câu trả lời tốt nhất cho câu hỏi của bạn là sử dụng xparsegói mới . Nó là một phần của bộ lập trình LaTeX3 và chứa các tính năng mở rộng để xác định các lệnh với các đối số tùy chọn khá tùy ý.

Trong ví dụ của bạn, bạn có một \secmacro có một hoặc hai đối số giằng. Điều này sẽ được thực hiện bằng cách sử dụng xparsenhư sau:

\ document class {article}
\ usepackage {xparse}
\ bắt đầu {tài liệu}
\ DeclareDocumentCommand \ sec {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {và # 2}%
    }%
}
(\ giây {Xin chào})
(\ giây {Xin chào} {Hi})
\ end {tài liệu}

Đối số { m g }xác định các đối số của \sec; mcó nghĩa là "đối số bắt buộc" và glà "đối số giằng tùy chọn". \IfNoValue(T)(F)sau đó có thể được sử dụng để kiểm tra xem đối số thứ hai có thực sự hiện diện hay không. Xem tài liệu cho các loại đối số tùy chọn khác được phép.


4
Sẽ! Nó không hoạt động. Đầu ra:(Hello and ) (Hello and Hi)
Alexey Malistov

Cảm ơn đã phản hồi, Alexey. Tôi nghi ngờ bạn đang sử dụng phiên bản cũ hơn của xparse; gần đây đã có rất nhiều công việc được thực hiện. TeX Live 2009 vừa được phát hành :)
Will Robertson

24

Tất cả những điều trên cho thấy khó có thể tạo ra một chức năng đẹp, linh hoạt (hoặc cấm quá tải) trong LaTeX !!! (mã TeX trông giống Hy Lạp đối với tôi)

tốt, chỉ để thêm sự phát triển gần đây (mặc dù không linh hoạt) của tôi, đây là những gì tôi đã sử dụng gần đây trong tài liệu luận án của mình, với

\usepackage{ifthen}  % provides conditonals...

Bắt đầu lệnh, với lệnh "tùy chọn" được đặt trống theo mặc định:

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

Sau đó, tôi có macro đặt một biến tạm thời, \ temp {}, khác nhau tùy thuộc vào việc đối số tùy chọn có trống hay không. Điều này có thể được mở rộng cho bất kỳ đối số thông qua.

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

Sau đó, tôi chạy macro bằng biến \ temp {} cho hai trường hợp. (Ở đây, nó chỉ đặt chú thích ngắn bằng với chú thích dài nếu nó không được người dùng chỉ định).

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

Trong trường hợp này, tôi chỉ kiểm tra đối số "tùy chọn" duy nhất mà \ newcommand {} cung cấp. Nếu bạn định thiết lập nó, giả sử, 3 đối số "tùy chọn", bạn vẫn phải gửi 3 đối số trống ... ví dụ:

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

Điều này khá là ngớ ngẩn, tôi biết, nhưng đó là về việc tôi sẽ đi với LaTeX - thật không hợp lý khi tôi bắt đầu nhìn vào mã TeX ... Mặc dù vậy, tôi thích phương pháp xparse của ông Robertson sẽ thử nó ...


Tôi thích cách tiếp cận này. Là "giống như lập trình" hơn và do đó dễ đọc hơn. Làm tốt lắm!
yêu.by.Jesus

11

Tất cả bạn cần là như sau:

\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

Tôi nghĩ TeX hiểu là tham số thích hợp của 'hộp' đầu tiên sau lệnh. 'hộp' này được viết bằng dấu ngoặc nhọn hoặc là một ký hiệu. I E. x^2+1hoặc x^{2+1} Vì vậy, tôi có câu hỏi, lệnh của bạn kiểm tra sự hiện diện của niềng răng? Có thể tạo lệnh LaTeX tạo ra \sec: "A, b, c và d" cho lệnh \sec{A}[b,c,d], "A và b" cho \sec{A}[b] and "A" for \ sec {A} `?
Crowley

Bạn có hai câu hỏi. 1) Có, sự hiện diện kiểm tra lệnh của tôi của niềng răng. 2) Có, nó có thể tạo macro cho \sec{A}[b,c,d]hay \sec{A}[b]hay \sec{A}.
Alexey Malistov

6

Tôi đã có một vấn đề tương tự, khi tôi muốn tạo một lệnh, \dxđể viết tắt \;\mathrm{d}x(nghĩa là đặt thêm một khoảng trắng trước vi phân của tích phân và cũng có "d" thẳng đứng). Nhưng sau đó tôi cũng muốn làm cho nó đủ linh hoạt để bao gồm biến tích hợp làm đối số tùy chọn. Tôi đặt đoạn mã sau vào phần mở đầu.

\usepackage{ifthen}

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

Sau đó

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

cung cấp cho \ dx với đối số tùy chọn


-1

Đây là nỗ lực của tôi, nó không theo thông số kỹ thuật của bạn chính xác mặc dù. Không được kiểm tra đầy đủ, vì vậy hãy thận trọng.

\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"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.