Необязательные аргументы LaTeX
-
06-07-2019 - |
Вопрос
Как создать команду с необязательными аргументами в LaTeX?Что -то вроде:
\newcommand{\sec}[2][]{
\section*{#1
\ifsecondargument
and #2
\fi}
}
}
Тогда я могу назвать это следующим образом
\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
Решение
Пример из руководства
\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.
Другие советы
Общая идея создания " необязательных аргументов " состоит в том, чтобы сначала определить промежуточную команду, которая сканирует вперед, чтобы определить, какие символы появляются в потоке токенов, а затем вставляет соответствующие макросы для обработки подходящего аргумента (аргументов). Это может быть довольно утомительно (хотя и не сложно) при использовании общего программирования TeX. \ @ ifnextchar
от LaTeX весьма полезен для таких вещей.
Лучший ответ на ваш вопрос - использовать новый пакет 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)
, чтобы проверить, действительно ли присутствовал второй аргумент или нет. См. Документацию для других типов необязательных аргументов, которые разрешены.
Все вышесказанное показывает, насколько сложно создать красивую, гибкую (или запретить перегруженную) функцию в LaTeX!!!(этот текстовый код для меня выглядит как греческий)
что ж, просто чтобы добавить мою недавнюю (хотя и не такую гибкую) разработку, вот что я недавно использовал в своем дипломном документе, с
\usepackage{ifthen} % provides conditonals...
Запустите команду с "необязательной" командой, по умолчанию установленной пустой:
\newcommand {\figHoriz} [4] [] {
Затем я прошу макрос установить временную переменную emp{} по-разному в зависимости от того, является ли необязательный аргумент пустым.Это может быть распространено на любой переданный аргумент.
\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)
Затем я запускаю макрос, используя переменную emp{} для этих двух случаев.(Здесь он просто устанавливает короткий заголовок равным длинному заголовку, если он не был указан пользователем).
\begin{figure}[!]
\begin{center}
\includegraphics[width=350 pt]{#3}
\temp %see above for caption etc.
\label{#2}
\end{center}
\end{figure}
}
В этом случае я проверяю только один "необязательный" аргумент, который предоставляет ewcommand{}.Если бы вы настроили его, скажем, для 3 "необязательных" аргументов, вам все равно пришлось бы отправить 3 пустых аргумента...например.
\MyCommand {first arg} {} {} {}
это довольно глупо, я знаю, но это примерно все, что я собираюсь сделать с LaTeX - просто это не так уж и бессмысленно, как только я начинаю смотреть на TeX-код...Мне действительно нравится мистерХотя, возможно, я попробую метод xparse Робертсона...
Все, что вам нужно, это следующее:
\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
У меня была похожая проблема, когда я хотел создать команду \ 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}
Вот моя попытка, она не совсем соответствует вашим спецификациям. Проверено не полностью, поэтому будьте осторожны.
\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"