Редактировать: О награде Я доволен вопросом ниже, и эта награда за этот вопрос. Я не думаю, что я могу взять что-то лучшее
Я немного поразмыслил над использованием необязательных аргументов в LaTeX, но некоторые вещи мне пока не совсем понятны.
Когда
Мой вопрос касается не только команд или пакетов, но и того и другого.
Иногда нам нужно указать один или несколько необязательных аргументов для пакета или для команды. Мы можем найти такие команды:
\Foo[OptArg1,OptArg2]{Arg1}{Arg2}
и нравится:
\Foo[OptArg1][OptArg2]{Arg1}{Arg2}
Для первого я вижу одно семейство с двумя необязательными аргументами, разделенными запятой. Для второго я вижу два семейства с одним необязательным аргументом для каждого.
Полагаю, что-то в этих двух способах отличается, но я не совсем понимаю, когда моей команде следует использовать первый, а когда — второй способ.
Например, предположим, что нам нужна команда, которая будет использовать наш первый необязательный аргумент для разделения первого необязательного аргумента на части. Тогда я предпочитаю второй способ, потому что в первом случае моя запятая как разделитель не будет понята (она уже разделитель). Но я все равно мог бы использовать команду типа:
\Foo[separator={,},OptArg2]{Arg1}{Arg2}
сделать то же самое.
Конечно, если бы я хотел разделить необязательные аргументы второго семейства, мой способ с \Foo[separator={//}][OptArg2//OptArg3] был бы единственным (или, по крайней мере, лучшим) выбором, поскольку мне нужно определить разделитель до чтения аргументов второго семейства.
Как
Также иногда команда должна вести себя по-разному, если заданы два семейства, и по-разному, если задано одно. Например, в моем примере выше, если первый аргумент не задан, запятая будет использоваться для разделения необязательных аргументов второго семейства. Но если задан, то она будет использоваться в качестве разделителя, и команда будет вести себя по-разному при чтении аргументов.
В таких ситуациях я думаю, что \def является более общим вариантом для написания команды, чем newcommand, потому что у нас больше вариантов выбора при чтении аргументов. (\newcommand разобьет вторые аргументы до того, как прочитает первые или что-то в этом роде. Рассмотрите также включение ']' во вторые семейства аргументов...)
У меня есть вопросы:
- Когда (стандартный LaTeX) мне следует использовать первый способ, а когда второй?
- Является ли \def единственным или лучшим способом определения наших команд в общих ситуациях, например, в ситуациях, когда мы еще не знаем количество аргументов, или в ситуациях, подобных описанной выше с разделителем или символом ']'?
PS: Во втором вопросе учтите, что я хочу, чтобы моя команда позволяла мне обрабатывать множество ситуаций, считывая следующий символ. (Например, я хочу считывать символы после команды один за другим и останавливаться только в том случае, если я найду два обычных аргумента или команду \stop и т. д. Не спрашиваю код этого, просто спрашиваю, может ли \newcommand сделать это - и является ли это хорошим выбором - или \def является единственным выбором)
решение1
Ваш вопрос смешивает две отдельные вещи. LaTex2e имеет необязательные аргументы []
и обязательные аргументы, {}
поэтому
\Foo[OptArg1,OptArg2]{Arg1}{Arg2}
имеет один необязательный аргумент и два обязательных аргумента.
\Foo[OptArg1][OptArg2]{Arg1}{Arg2}
имеет два необязательных аргумента и два обязательных аргумента.
Вторая проблема — это список, разделенный запятыми. Возможно, это вообще не часть синтаксиса, просто запятая рассматривается как символ, например, после
\newcommand\Foo[3][]{(#1)-(#2)(#3)}
тогда #1
было бы OptArg1,OptArg2
, #2
было бы Arg1
и #3
было бы Arg2
и результатом было бы набрать
(ОптАрг1,ОптАрг2)-(Арг1)-(Арг2)
с запятыми никаких особых правил не существует.
Конечно, команда может делать с аргументами все, что ей вздумается, и это может включать итерацию по запятым. Для этого в формате latex есть средства ( \@for
) или несколько пакетов предлагают макросы для разбора списков, разделенных запятыми. Однако это не зависит от обнаружения необязательного аргумента. В примере (допустимого) синтаксиса
\usepackage[foo,bar]{array,longtable}[2015/01/01 packages by you, me and someone]
есть два необязательных аргумента и один обязательный аргумент, первый необязательный аргумент и обязательный аргумент позже, как часть обработки \usepackage
, разделены запятыми. Второй необязательный аргумент не разделен запятыми, но фактически разделен на/
и пробел для извлечения даты из начала аргумента.
Что касается определения, если у вас есть только один необязательный аргумент в начале, вы можете использовать \newcommand
Если у вас есть два или более, вы также можете использовать, \newcommand
но вам нужно определить макрос поэтапно, но, вероятно, проще использовать xparse
или аналогичные пакеты, чтобы обеспечить более простую спецификацию и автоматически справляться с определением необходимых внутренних макросов. Однако лучше не иметь слишком много последовательных необязательных аргументов, как если бы у вас было
\Foo[OptArg1][OptArg2]{Arg1}{Arg2}
then OptArg1
на самом деле не является необязательным, если вам нужно указать OptArg2
. Синтаксис, такой как
\Foo[opt1=a,opt2=b]{Arg1}
позволяет независимо опускать каждую опцию. Но опять же такой парсинг ключ=значение может быть применен к любой строке токенов, будь то обязательный или необязательный аргумент. Например, graphicx
использует keyval
пакет для парсинга ,
и =
в его необязательном аргументе
\includegraphics[width=10pt,height=8pt]{image}
и hyperref
использует тот же самый разбор для разбора того же самого синтаксиса в обязательном аргументе
\hypersetup{colorlinks=false,plainpages=true}