
Ao usar xparse
para definir um novo ambiente com um argumento opcional O{}
, o primeiro caractere de fim de linha é engolido, como pode ser visto no documento de exemplo a seguir:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Npn \__my_end_of_line: { X }
\NewDocumentEnvironment{mycode}{ !O{} }{
\char_set_catcode_active:N \^^M
\char_set_active_eq:nN {`\^^M} \__my_end_of_line:
}{}
\ExplSyntaxOff
\begin{document}
\begin{mycode}
abc
\end{mycode}
\end{document}
quais saídas
abcX
onde eu esperaria
XabcX
Já existeessa questãoque é semelhante, mas não faz uso de caracteres ativos. Além disso, os comentários nessa pergunta não ajudam aqui. Nem prefixar o especificador de argumento está !
funcionando nem está funcionando em uma xparse
versão mais recente (minha versão é xparse 2019-05-28
).
Existe uma maneira de contornar esse problema?
EDITAR:Meu caso de uso é ter um ambiente literal especial com alguma configuração opcional no início. O problema é que preciso ler adiante até encontrar o final da primeira linha/a primeira ^^M
para descartar qualquer coisa que esteja nessa linha (geralmente está vazia). Isso funciona bem se um argumento opcional estiver presente, mas sem um argumento opcional, a primeira linha real do código é considerada a linha a ser descartada, o que é indesejado.
Responder1
Conforme solicitado, meu rápido modelo como resposta. Você desejará primeiro alterar os códigos de categoria antes de verificar a presença do argumento opcional e, em seguida, alterná-lo novamente para a captura do argumento e redefinir os códigos de gato para o ambiente real.
O exemplo a seguir faz uma captura bastante simples do argumento opcional, como é feito no LaTeX2e, mas isso é inferior a um O{}
argumento from xparse
, pois não haverá balanceamento de colchetes. Você pode contornar isso fazendo um \NewDocumentCommand \__mycode_parse_arg:w { !O{} } { ... }
, mas \NewDocumentCommand
não deve ser usado para macros em nível de código (daí o nome).
Eu configurei o argumento opcional de forma que ele altere a definição de \__mycode_end_of_line:
, apenas para mostrar que está funcionando.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Npn \__mycode_end_of_line: { X }
\cs_new_protected:Npn \__mycode_real_begin:
{
\__mycode_catcode_setup:
\char_set_active_eq:nN { `\^^M } \__mycode_end_of_line:
}
\cs_new_protected:Npn \__mycode_parse_arg:w [ #1 ]
{
% do whatever with the optional argument
\cs_set_protected:Npn \__mycode_end_of_line: { #1 }
\__mycode_real_begin:
}
\cs_new_protected:Npn \__mycode_catcode_setup:
{
\char_set_catcode_active:N \^^M
}
\NewDocumentEnvironment { mycode } {}
{
\group_begin:
\__mycode_catcode_setup:
\peek_meaning:NTF [
{
\group_end:
\__mycode_parse_arg:w
}
{
\group_end:
\__mycode_real_begin:
}
}
{}
\ExplSyntaxOff
\begin{document}
\begin{mycode}
abc
\end{mycode}
\begin{mycode}[Y]
abc
\end{mycode}
\end{document}