Необязательные аргументы в «семьях»... Когда и как?

Необязательные аргументы в «семьях»... Когда и как?

Редактировать: О награде Я доволен вопросом ниже, и эта награда за этот вопрос. Я не думаю, что я могу взять что-то лучшее

Я немного поразмыслил над использованием необязательных аргументов в LaTeX, но некоторые вещи мне пока не совсем понятны.

Когда

Мой вопрос касается не только команд или пакетов, но и того и другого.

Иногда нам нужно указать один или несколько необязательных аргументов для пакета или для команды. Мы можем найти такие команды:

\Foo[OptArg1,OptArg2]{Arg1}{Arg2}

и нравится:

\Foo[OptArg1][OptArg2]{Arg1}{Arg2}

Для первого я вижу одно семейство с двумя необязательными аргументами, разделенными запятой. Для второго я вижу два семейства с одним необязательным аргументом для каждого.

Полагаю, что-то в этих двух способах отличается, но я не совсем понимаю, когда моей команде следует использовать первый, а когда — второй способ.

Например, предположим, что нам нужна команда, которая будет использовать наш первый необязательный аргумент для разделения первого необязательного аргумента на части. Тогда я предпочитаю второй способ, потому что в первом случае моя запятая как разделитель не будет понята (она уже разделитель). Но я все равно мог бы использовать команду типа:

\Foo[separator={,},OptArg2]{Arg1}{Arg2}

сделать то же самое.

Конечно, если бы я хотел разделить необязательные аргументы второго семейства, мой способ с \Foo[separator={//}][OptArg2//OptArg3] был бы единственным (или, по крайней мере, лучшим) выбором, поскольку мне нужно определить разделитель до чтения аргументов второго семейства.

Как

Также иногда команда должна вести себя по-разному, если заданы два семейства, и по-разному, если задано одно. Например, в моем примере выше, если первый аргумент не задан, запятая будет использоваться для разделения необязательных аргументов второго семейства. Но если задан, то она будет использоваться в качестве разделителя, и команда будет вести себя по-разному при чтении аргументов.

В таких ситуациях я думаю, что \def является более общим вариантом для написания команды, чем newcommand, потому что у нас больше вариантов выбора при чтении аргументов. (\newcommand разобьет вторые аргументы до того, как прочитает первые или что-то в этом роде. Рассмотрите также включение ']' во вторые семейства аргументов...)

У меня есть вопросы:

  1. Когда (стандартный LaTeX) мне следует использовать первый способ, а когда второй?
  2. Является ли \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}

Связанный контент