
Cuando se utiliza xparse
para definir un nuevo entorno con un argumento opcional O{}
, el primer carácter de final de línea se devora, como se puede ver en el siguiente documento de ejemplo:
\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}
que salidas
abcX
donde esperaría
XabcX
ya hayesta preguntaque es similar, pero no utiliza personajes activos. Además, los comentarios en esa pregunta no ayudan aquí. Ni anteponer el especificador de argumento !
funciona ni funciona en una xparse
versión más nueva (mi versión es xparse 2019-05-28
).
¿Hay alguna manera de solucionar este problema?
EDITAR:Mi caso de uso es tener un entorno especial similar al literal con alguna configuración opcional al principio. El problema es que necesito seguir leyendo hasta encontrar el final de la primera línea/la primera ^^M
para descartar todo lo que esté en esa línea (normalmente está vacía). Esto funciona bien si hay un argumento opcional presente, pero sin un argumento opcional, la primera línea de código real se considera la línea que se descarta, lo cual no es deseado.
Respuesta1
Según lo solicitado, mi maqueta rápida como respuesta. Primero querrá cambiar los códigos de categoría antes de verificar si hay argumentos opcionales presentes, luego volver a cambiarlos para capturar el argumento y restablecer los códigos cat para el entorno real.
El siguiente ejemplo captura de forma bastante sencilla el argumento opcional, como se hace en LaTeX2e, pero es inferior a un O{}
argumento de xparse
ya que no habrá equilibrio entre corchetes. Puedes evitarlo haciendo un \NewDocumentCommand \__mycode_parse_arg:w { !O{} } { ... }
, pero \NewDocumentCommand
no deberías usarlo para macros a nivel de código (de ahí el nombre).
Configuré el argumento opcional de manera que cambie la definición de \__mycode_end_of_line:
, solo 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}