
SE, в последнее время я немного поигрался с expl3
и xparse
столкнулся со следующей проблемой: я хочу создать команду, которая создает новую команду — похожую наэта почта. Это не так сложно, если только вторая команда не имеет аргументов; попытка создать команду, которая принимает аргументы, немного сложнее.
Что я получил на данный момент:
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\test{ m}
{
\NewDocumentCommand#1 {m}
{My name is \string#1, king of kings}
}
\begin{document}
\test{\ozymandias}
\ozymandias{\manthano}
\end{document}
Это выводит My name is ozymandias, king of kings
, что дает правильный сонет, но не то, что я хотел. Я знаю, в чем проблема, я просто не знаю, как ее исправить :)
решение1
Мне интересно, что там \string#1
внутри.
Новая команда внутри может быть создана с помощью
\expandafter\NewDocumentCommand\csname #1\endcsname{...}{....}
т.е. имя новой последовательности должно быть построено первым с \expandafter
(сначала дается имя, затем \NewDocumentCommand
вступает в действие). Тот же подход должен быть принят для традиционного \newcommand
или \renewcommand
и т.д.
Однако \test
команду необходимо использовать как \test{ozymandias}
, без \
!
##1
Обратите внимание, что для доступа к первому аргументу внутреннего макроса необходимо использовать (если это вообще необходимо), последующие аргументы нумеруются и ##2
т. д.
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\manthano}{}{Manthano}
\NewDocumentCommand\test{ m}
{%
\expandafter\NewDocumentCommand\csname #1\endcsname{m}{%
My name is ##1, king of kings%
}
}
\begin{document}
\test{ozymandias}
\ozymandias{\manthano}
\end{document}
РЕДАКТИРОВАТЬ:Для использования \test
с \
, вам необходимо адаптировать команду к
\makeatletter
\NewDocumentCommand\test{ m}
{%
\expandafter\NewDocumentCommand\csname\expandafter\@gobble\string #1\endcsname{m}{%
My name is ##1, king of kings%
}
}
\makeatother