Макрос для проверки расширяемости команды

Макрос для проверки расширяемости команды

Я хотел бы создатькоманда, которая проверяет, является ли выражение полностью расширяемым, и завершается сбоем, если нет(в идеале вывести сообщение об ошибке). Я бы хотел это сделатьбез учета конкретного движка TeX. Я думаю, это связано с этим вопросом.Проверьте, полностью ли расширяем макрос., но для предоставленного ответа требуется LuaTeX.


Тестовый код

Тестовый код будет выглядеть так:

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xstring}

\NewDocumentCommand{\checkexpandability}{m}{
    % CODE HERE
}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}

\begin{document}
\checkexpandability{\expandable{test}} % Should be OK
\checkexpandability{\notexpandable{test}} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}} % Should CRASH
\end{document}

На случай, если это слишком сложно

Если это невозможно, то я могу изменить сигнатуру команды, включив параметр, во что должна расширяться команда:

\begin{document}
\checkexpandability{\expandable{test}}{test} % Should be OK
\checkexpandability{\notexpandable{test}}{test} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}}{true} % Should CRASH
\end{document}

Комментарий по расширяемости

Поскольку определение полностью расширяемого не так ясно, как можно было бы подумать (см. комментарий ниже), контекст этого вопроса заключается в том, что я просто пытаюсь создать что-то, что поможет мне отлаживать некоторый код. Я согласен ограничить вопрос этим конкретным поведением: будет ли макрос работать в макросах контекста, таких как команда \color:

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\color{\expandable{blue}} % OK
\color{\notexpandable{red}} % CRASHES
X
\end{document}

По сути, \colorкоманда выполняет ту работу, которую я ищу, просто мне хотелось бы назвать ее \checkexpandabilityболее универсально и вывести понятное сообщение об ошибке.

решение1

Я думаю, что основное недопонимание заключается в том,

По сути, \colorкоманда выполняет ту работу, которую я ищу,

Команда \colorне проверяет запрошенный тип, она просто ожидает, что после расширения аргумент будет определенным именем цвета. Если расширение не удается, вы получаете ошибку низкого уровня или если оно расширяется до неопределенного цвета, вы получаете конкретное сообщение об ошибке, но никакая часть обработки не является общей и не применяется к команде, отличной от команд, ожидающих цвета.

Единственная версия, которая может быть реализована, это версия с ожидаемым расширением, поскольку она просто спрашивает, равны ли два аргумента после расширения. Уровень программирования L3 имеет несколько вариантов этого, или вы можете использовать пакет ifthenи

\ifthenelse{\equal{\expandable{test}}{test}}{yes}{no}

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

решение2

Для отладки вашего кода я бы просто использовал \typeout.

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\typeout{\expandable{blue}} % OK, print "blue"
\typeout{\notexpandable{red}} % CRASHES
X
\end{document}

Суть в том, что это \typeoutполностью развернет его аргумент, а затем выведет на терминал полностью развернутый результат --- так что вы можете просто взглянуть на терминал.

В первом случае печатает blue, значит все в порядке. Во втором случае вылетает.


Конечно, у описанного выше подхода есть две проблемы.

  • Даже если\expandable{blue} являетсяполностью расширяемый (что бы это ни значило),это может быть не тот случай, который \colorгарантированно полностью развернет его аргумент перед интерпретацией результата как цвета. (Я предполагаю, что поЗакон Хайрама(Однако на практике это было бы сделано для того, чтобы избежать поломки «существующих пакетов».)

    Поэтому, если вы хотите быть более уверены, лучше расширить его заранее, используя, например,\ExpandArgs.

  • Информация о коде категории, а также любые специальные символы, скрывающиеся в коде (например, пробел или табуляция), теряются.

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

    Если это так, попробуйтемой пакет. (сейчас код в беспорядке, но он работает, и существуют пакеты с худшим исходным кодом)

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