Por que o código a seguir não funciona?
\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
\NewEnviron{\csname #1\endcsname}[1]{%
##1 : \BODY
}
}
Já vi exemplos do uso de \csname SOMENAME\endcsname
macro for sem argumentos mas não sei como fazer com a \NewEnviron
ou \newcommand
com múltiplos argumentos. Eu sou avisado com o erro ! Missing \endcsname inserted
.
Responder1
Você não quer um nome de comando para o nome de um ambiente. Apenas o nome está bom.
Então, você pode fazer isso:
\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}
Observe que este código não requeramsthm, você pode usar apenas \newcommand\newtheorem...
a menos que precise do pacote por outros motivos.
Além disso, você nunca faz nada com o segundo argumento, mesmo que crie o comando para que seja necessário. No exemplo acima, nada é feito com oaks
.
Não estou convencido de que isso seja realmente o que você deseja fazer. A saída do código acima é:
ComoChristian Hupfer destaca, isso irá, é claro, quebrar qualquer coisa que seja usada \newtheorem
no sentido padrão. Comoegreg diz, não é de todo óbvio a que propósito \newtheorem
serve uma redefinição como esta. Parece quase garantido que haverá problemas mais cedo ou mais tarde... provavelmente mais cedo.
Responder2
Por que o código a seguir não funciona?
Vamos dar uma olhada mais de perto no que \NewEnviron
faz:
Após uma curta cadeia de macros para analisar corretamente a entrada do usuário, \NewEnviron
usa-se \env@newenvironment
o que era \let
no \newenvironment
início.
Agora, \newenvironment
internamente faz entre outras coisas (um pouco simplificado) algo como
\expandafter\def\csname <env-name>\endcsname{<begin-code>}
(Basicamente você fez a coisa certa sem saber que os internos já estão cuidando disso.)
Se você definir " <env-name>=\csname SOMENAME\endcsname
" - isso resultaria do uso de sua macro personalizada como \newtheorem{SOMENAME}{}
- você acabaria com um \csname...\endcsname
par supérfluo:
\expandafter\def\csname\csname SOMENAME\endcsname\endcsname...
\expandafter
(como você provavelmente sabe), neste caso, pega \def
e armazena-o para antecipar o próximo token e expande-o primeiro. Aqui, ele descobre \csname
quem procura o próximo \endcsname
e expande tudo o que está no meio e forma uma sequência de controle a partir disso. Este seria outro \csname
que seria novamente encerrado corretamente pelo \endcsname
. Então, você realmente aplica o \csname
mecanismo duas vezes a 'SOMENAME' e isso significa que você não termina com \def\SOMENAME{<begin-code>}
(como planejou), mas com
\def\<expansion of \SOMENAME>{<begin-code>}
Se \SOMENAME
foi definido não tivemos problema:
\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}
Mas voce devianãoDefina isso; esta interface de usuário seria de alguma forma enganosa. Basta usar \NewEnviron
exatamente como \newenvironment
na entrada do nome do ambiente:
\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}
Observação
Alterei o nome da sua macro de exemplo para evitar conflitos com o amsthm
pacote. Acho que é melhor manter essas coisas como estão, em geral. Certamente há exceções, mas perder completamente sua funcionalidade pode não ser a melhor opção se você puder evitá-lo simplesmente escolhendo outro nome para seu comando.