Почему следующий код не работает?
\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
\NewEnviron{\csname #1\endcsname}[1]{%
##1 : \BODY
}
}
Я видел примеры использования \csname SOMENAME\endcsname
макроса for без аргументов, но не знаю, как это сделать с \NewEnviron
или \newcommand
с несколькими аргументами. Мне выдается сообщение об ошибке ! Missing \endcsname inserted
.
решение1
Вам не нужно имя команды для имени среды. Достаточно просто имени.
Итак, вы можете сделать это:
\documentclass{article}
\usepackage{amsthm,environ}
\renewcommand\newtheorem[2]{%
\NewEnviron{#1}[1]{%
##1 : \BODY
}%
}
\begin{document}
\newtheorem{acorns}{oaks}
\begin{acorns}{trees}
leaves and things
\end{acorns}
\end{document}
Обратите внимание, что этот код не требуетамстм, вы можете просто использовать его, \newcommand\newtheorem...
если только пакет вам не нужен по другим причинам.
Кроме того, вы никогда ничего не делаете со вторым аргументом, даже если вы создаете команду так, что она обязательна. В приведенном выше примере ничего никогда не делается с oaks
.
Я не уверен, что это действительно то, что вы хотите сделать. Вывод из кода выше:
КакКристиан Хапфер отмечает, это, конечно, сломает все, что использует \newtheorem
в стандартном смысле. Какэгрег говорит, совсем не очевидно, какой цели \newtheorem
служит такое переопределение. Кажется, это почти гарантированно приведет к проблемам рано или поздно... скорее всего рано.
решение2
Почему следующий код не работает?
Давайте подробнее рассмотрим, что \NewEnviron
делает:
После короткой цепочки макросов для правильного анализа пользовательского ввода \NewEnviron
используется \env@newenvironment
то, что было \let
в \newenvironment
начале.
Теперь, \newenvironment
внутренне делает среди прочего (немного упрощенно) что-то вроде
\expandafter\def\csname <env-name>\endcsname{<begin-code>}
(По сути, вы поступили правильно, не зная, что внутренние механизмы уже об этом позаботились.)
Если вы установите " <env-name>=\csname SOMENAME\endcsname
" (что может произойти в результате использования вашего пользовательского макроса \newtheorem{SOMENAME}{}
), то в результате вы получите лишнюю \csname...\endcsname
пару:
\expandafter\def\csname\csname SOMENAME\endcsname\endcsname...
\expandafter
(как вы, вероятно, знаете) в этом случае захватывает \def
и сохраняет его, чтобы смотреть вперед на следующий токен и расширяет его первым. Здесь он находит, \csname
который ищет следующий \endcsname
и расширяет все, что между ними, и формирует из этого управляющую последовательность. Это будет еще один \csname
, который снова правильно завершается завершающим \endcsname
. Таким образом, вы действительно применяете механизм \csname
дважды к 'SOMENAME', и это означает, что вы не получаете \def\SOMENAME{<begin-code>}
(как вы планировали), а получаете
\def\<expansion of \SOMENAME>{<begin-code>}
Если \SOMENAME
было определено, у нас не было проблем:
\documentclass{article}
\usepackage{environ}
\def\SOMENAME{somename}
\NewEnviron{\csname SOMENAME\endcsname}{somename-content: \BODY}
\begin{document}
\begin{somename}
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer feugiat tempus urna, cursus placerat sapien mollis ac.
Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}
Но вам следуетнетопределить его; этот пользовательский интерфейс будет каким-то образом вводить в заблуждение. Просто используйте \NewEnviron
точно так же, как \newenvironment
в отношении ввода имени окружения:
\documentclass{article}
\usepackage{environ}
\newcommand{\FlorianEnvdefWrapper}[1]{%
\NewEnviron{#1}[1]{##1: \BODY}
}
\FlorianEnvdefWrapper{somename}
\begin{document}
\begin{somename}{foo-bar}
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer feugiat tempus urna, cursus placerat sapien mollis ac.
Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}
Замечание
Я изменил имя вашего примера макроса, чтобы избежать конфликтов с пакетом amsthm
. Я думаю, что лучше оставить эти вещи такими, какие они есть, в общем. Конечно, есть исключения, но полная потеря его функциональности может быть не лучшим вариантом, если вы можете этого избежать, просто выбрав другое имя для своей команды.