LaTeX อาร์กิวเมนต์เสริม


132

คุณสร้างคำสั่งพร้อมอาร์กิวเมนต์ที่เป็นทางเลือกใน LaTeX ได้อย่างไร? สิ่งที่ต้องการ:

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

จากนั้นฉันสามารถเรียกมันว่า

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

5
คำถามที่เกี่ยวข้อง: คำจำกัดความของคำสั่งที่แตกต่างกันมีและไม่มีข้อโต้แย้งไม่จำเป็น
MS Dousti

คำตอบ:


176

ตัวอย่างจากคู่มือ :

\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
ฉันคิดว่าคำถามนี้เกี่ยวกับวิธีการพิจารณาว่ามีการให้อาร์กิวเมนต์ที่เป็นทางเลือกหรือไม่โดยไม่ได้ระบุค่าเริ่มต้น
คอนราดรูดอล์ฟ

43
แม้ว่าจะเป็นเรื่องจริง แต่ฉันพบคำถามนี้ในขณะที่กำลังมองหาวิธีที่จะให้อาร์กิวเมนต์เริ่มต้นดังนั้นคำตอบนี้จึงเป็นประโยชน์ที่สุดสำหรับฉัน
แทนเนอร์ Swett

26

แนวคิดทั่วไปที่อยู่เบื้องหลังการสร้าง "อาร์กิวเมนต์ที่เป็นทางเลือก" คือขั้นแรกให้กำหนดคำสั่งกลางที่จะสแกนล่วงหน้าเพื่อตรวจจับว่าอักขระใดที่จะเกิดขึ้นต่อไปในสตรีมโทเค็นจากนั้นจึงแทรกมาโครที่เกี่ยวข้องเพื่อประมวลผลอาร์กิวเมนต์ที่ปรากฏขึ้นตามความเหมาะสม สิ่งนี้อาจค่อนข้างน่าเบื่อ (แม้ว่าจะไม่ใช่เรื่องยาก) โดยใช้การเขียนโปรแกรม TeX ทั่วไป LaTeX \@ifnextcharมีประโยชน์มากสำหรับสิ่งเหล่านี้

คำตอบที่ดีที่สุดสำหรับคำถามของคุณคือการใช้xparseแพ็คเกจใหม่ เป็นส่วนหนึ่งของชุดโปรแกรม LaTeX3 และมีคุณสมบัติมากมายสำหรับการกำหนดคำสั่งด้วยอาร์กิวเมนต์ที่เป็นทางเลือก

ในตัวอย่างของคุณคุณมี\secมาโครที่รับอาร์กิวเมนต์วงเล็บปีกกาหนึ่งหรือสองข้อ สิ่งนี้จะถูกนำไปใช้โดยใช้xparseสิ่งต่อไปนี้:

\ documentclass {บทความ}
\ usepackage {} xparse
\ begin {เอกสาร}
\ DeclareDocumentCommand \ วินาที {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {และ # 2}%
    }%
}
(\ วินาที {สวัสดี})
(\ วินาที {สวัสดี} {Hi})
\ end {เอกสาร}

อาร์กิวเมนต์{ m g }กำหนดอาร์กิวเมนต์ของ\sec; mหมายถึง "อาร์กิวเมนต์บังคับ" และgเป็น "อาร์กิวเมนต์ที่เป็นตัวเลือกเสริม" \IfNoValue(T)(F)จากนั้นสามารถใช้เพื่อตรวจสอบว่ามีอาร์กิวเมนต์ที่สองอยู่จริงหรือไม่ ดูเอกสารประกอบสำหรับอาร์กิวเมนต์ทางเลือกประเภทอื่น ๆ ที่อนุญาต


4
จะ! มันไม่ทำงาน. เอาท์พุท:(Hello and ) (Hello and Hi)
Alexey Malistov

ขอบคุณสำหรับคำติชม Alexey ฉันสงสัยว่าคุณกำลังใช้ xparse เวอร์ชันเก่ากว่า เมื่อไม่นานมานี้มีงานที่ต้องทำมากมาย TeX Live 2009 เพิ่งเปิดตัว :)
Will Robertson

24

ทั้งหมดข้างต้นแสดงให้เห็นอย่างหนักว่าสามารถสร้างฟังก์ชันที่ดียืดหยุ่น (หรือห้ามใช้งานมากเกินไป) ใน LaTeX !!! (รหัส TeX นั้นดูเหมือนภาษากรีกสำหรับฉัน)

ดีเพียงเพื่อเพิ่มการพัฒนาล่าสุดของฉัน (แม้ว่าจะไม่ยืดหยุ่นเท่า) นี่คือสิ่งที่ฉันเพิ่งใช้ในเอกสารวิทยานิพนธ์ของฉันด้วย

\usepackage{ifthen}  % provides conditonals...

เริ่มคำสั่งโดยตั้งค่าคำสั่ง "ทางเลือก" ว่างไว้โดยค่าเริ่มต้น:

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

จากนั้นให้มาโครตั้งค่าตัวแปรชั่วคราว \ temp {} ให้แตกต่างกันไปขึ้นอยู่กับว่าอาร์กิวเมนต์ที่เป็นทางเลือกว่างหรือไม่ สิ่งนี้สามารถขยายไปยังอาร์กิวเมนต์ที่ส่งผ่าน

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

จากนั้นฉันเรียกใช้แมโครโดยใช้ตัวแปร \ temp {} สำหรับสองกรณี (ในที่นี้จะตั้งค่าคำบรรยายสั้น ๆ ให้เท่ากับคำอธิบายภาพแบบยาวหากผู้ใช้ไม่ได้ระบุ)

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

ในกรณีนี้ฉันตรวจสอบเฉพาะอาร์กิวเมนต์ "ทางเลือก" เดี่ยวที่ \ newcommand {} ระบุ หากคุณต้องการตั้งค่าให้พูดว่า "ไม่บังคับ" 3 args คุณยังคงต้องส่ง args ว่าง 3 รายการ ... เช่น

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

ซึ่งค่อนข้างงี่เง่าฉันรู้ แต่นั่นก็เป็นเรื่องที่ฉันจะใช้ LaTeX - มันไม่สมเหตุสมผลเลยเมื่อฉันเริ่มดูรหัส TeX ... ฉันชอบวิธี xparse ของนายโรเบิร์ตสันบางทีฉันอาจจะ จะลองดู ...


ฉันชอบแนวทางนี้ "เหมือนการเขียนโปรแกรม" มากกว่าจึงอ่านง่ายกว่า เก่งมาก!
loved.by.Jesus

11

สิ่งที่คุณต้องการมีดังต่อไปนี้:

\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

ฉันคิดว่า TeX เข้าใจว่าเป็นพารามิเตอร์ที่เหมาะสมกับการนับ 'กล่อง' แรกหลังคำสั่ง "กล่อง" นี้เขียนด้วยวงเล็บปีกกาหรือเป็นสัญลักษณ์เดียว กล่าวคือ x^2+1หรือx^{2+1} ฉันมีคำถามคำสั่งของคุณทดสอบการมีวงเล็บปีกกาหรือไม่? เป็นไปได้ไหมที่จะสร้างคำสั่ง LaTeX ที่\secผลิต: "A, b, c และ d" สำหรับคำสั่ง\sec{A}[b,c,d]"A และ b" สำหรับ\sec{A}[b] and "A" for \ sec {A} `
Crowley

คุณมีสองคำถาม 1) ใช่การทดสอบคำสั่งของฉันเกี่ยวกับการจัดฟัน 2) ใช่มันเป็นไปได้ที่จะสร้างแมโครสำหรับ\sec{A}[b,c,d]หรือหรือ\sec{A}[b] \sec{A}
Alexey Malistov

6

ฉันมีปัญหาที่คล้ายกันเมื่อฉันต้องการสร้างคำสั่ง\dxให้ย่อ\;\mathrm{d}x(เช่นใส่ช่องว่างก่อนส่วนต่างของอินทิกรัลและมี "d" ตรงด้วย) แต่ฉันก็ต้องการทำให้ยืดหยุ่นพอที่จะรวมตัวแปรของการรวมเป็นอาร์กิวเมนต์ที่เป็นทางเลือก ฉันใส่รหัสต่อไปนี้ในคำนำ

\usepackage{ifthen}

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

แล้วก็

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

ให้\ dx พร้อมอาร์กิวเมนต์ที่เป็นทางเลือก


-1

นี่คือความพยายามของฉันมันไม่เป็นไปตามข้อกำหนดของคุณอย่างแน่นอน ไม่ได้รับการทดสอบอย่างสมบูรณ์ดังนั้นโปรดใช้ความระมัดระวัง

\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"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.