Дополнительные аргументы 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, хотя, возможно, я попробую...

Ответ 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"