Дополнительные аргументы LaTeX
Как вы создаете команду с необязательными аргументами в LaTeX?
Что-то вроде:
\newcommand{\sec}[2][]{
\section*{#1
\ifsecondargument
and #2
\fi}
}
}
Тогда я могу назвать это как
\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
Ответы
Ответ 1
Пример из guide:
\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.
Ответ 2
Общая идея создания "необязательных аргументов" заключается в том, чтобы сначала определить промежуточную команду, которая сканирует вперед, чтобы определить, какие символы появляются дальше в потоке токенов, а затем вставляет соответствующие макросы для обработки аргументов (-ов), следующих вверх подходящее. Это может быть довольно утомительно (хотя и не сложно) с использованием общего программирования TeX. LaTeX \@ifnextchar
весьма полезен для таких вещей.
Лучший ответ на ваш вопрос - использовать новый пакет xparse
. Он является частью пакета программирования LaTeX3 и содержит обширные функции для определения команд с довольно произвольными необязательными аргументами.
В вашем примере у вас есть макрос \sec
, который либо принимает один, либо два аргумента. Это будет реализовано с помощью xparse
со следующим:
\documentclass{article}
\usepackage{xparse}
\begin{document}
\DeclareDocumentCommand\sec{ m g }{%
{#1%
\IfNoValueF {#2} { and #2}%
}%
}
(\sec{Hello})
(\sec{Hello}{Hi})
\end{document}
Аргумент { m g }
определяет аргументы \sec
; m
означает "обязательный аргумент", а g
- "необязательный согласованный аргумент". \IfNoValue(T)(F)
затем может использоваться для проверки наличия или отсутствия второго аргумента. См. Документацию для других типов необязательных аргументов, которые разрешены.
Ответ 3
Все вышеперечисленное показывает, что это может быть сделано, чтобы сделать приятную, гибкую (или запретить перегруженную) функцию в 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 "необязательных" аргумента, вам все равно придется отправить 3 пустых аргумента... например.
\MyCommand {first arg} {} {} {}
который довольно глупый, я знаю, но это касается того, насколько я собираюсь пойти с LaTeX - это не так уж и смутно, как только я начну смотреть на TeX-код... Мне нравится метод г-на Роберсона xparse, хотя, возможно, я попробую...
Ответ 4
Все, что вам нужно, это следующее:
\makeatletter
\def\sec#1{\def\tempa{#1}\futurelet\next\[email protected]}% Save first argument
\def\[email protected]{\ifx\next\bgroup\expandafter\[email protected]\else\expandafter\[email protected]\fi}%Check brace
\def\[email protected]#1{\section*{\tempa\ and #1}}%Two args
\def\[email protected]{\section*{\tempa}}%Single args
\makeatother
\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
Ответ 5
У меня была аналогичная проблема, когда я хотел создать команду \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 с необязательным аргументом
Ответ 6
Здесь моя попытка, это точно не соответствует вашим спецификациям. Не полностью протестированы, поэтому будьте осторожны.
\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"