Дополнительные Аргументы LaTeX


Как создать команду с необязательными аргументами в LaTeX? Что-то вроде:

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

тогда, я могу назвать это как

sec{Hello}
%Output: Hello
sec{Hello}{Hi}
%Output: Hello and Hi
6 96

6 ответов:

пример руководство:

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

все вышеперечисленное показывает, что это может быть хорошая, гибкая (или запретить перегруженную) функцию в LaTeX!!! (этот код TeX выглядит как греческий для меня)

ну, просто чтобы добавить мою недавнюю (хотя и не столь гибкую) разработку, вот что я недавно использовал в своей диссертации doc, с

\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, вам все равно пришлось бы отправить 3 пустые аргументы... например.

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

что довольно глупо, я знаю, но это примерно так, как я собираюсь пойти с LaTeX - это просто не так уж и бессмысленно, как только я начинаю смотреть на код TeX... Мне нравится метод xparse Мистера Робертсона, хотя, возможно,я попробую его...

общая идея создания "необязательных аргументов" заключается в том, чтобы сначала определить промежуточную команду, которая сканирует вперед, чтобы определить, какие символы идут дальше в потоке токенов, а затем вставляет соответствующие макросы для обработки аргументов, которые подходят по мере необходимости. Это может быть довольно утомительно (хотя и не сложно) с использованием общего программирования TeX. Латекс-это \@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) может тогда использоваться, чтобы проверить, является ли второй аргумент был действительно присутствует или нет. См. документацию для других типов необязательных аргументов, которые разрешены.

все, что вам нужно, это следующее:

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

дает \dx с необязательным аргументом

вот моя попытка,она не соответствует вашим спецификациям точно. Не полностью протестированы, так что будьте осторожны.

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