我正在尝试创建一个命令来表示存储在序列中的代码而不执行它(类似于\meaning
)。当使用时\cs_log:N \l_scontents_macro_tmp_tl
,我获得了在传递给之前.log
在环境中记录的内容。scontents
seq
我可以创建一个类似的命令并\typestored[number]{seqname}
在文档中给出相同的结果吗?
运行时\typestored[1]{contents}
获取内容存储在序列中并在文件中显示:
Using \verb+scontents+ env no \verb+[key=val]+, save in \verb+contents+
with index $1$\footnote{AND footnotes !!}.%
Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+
\begin{Verbatim}
(A) verbatim environment %
many space here and percent at end of line %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
我曾尝试使用:
% Fake \meaning
\tl_const:Nn \c_catcode_specials_tl { \ \\ \{ \} \$ \& \# \^ \_ \% \~ }
\cs_new_protected:Npn \_catcode_dospecials:
{
\tl_map_inline:Nn \c_catcode_specials_tl
{
\char_set_catcode_other:N ##1
}
}
\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\tl_put_right:Nx \l_tmpb_tl
{
\_catcode_dospecials:
\_scontents_getfrom_seq:nn { #1 }{ #2 }
}
\tl_show:N \l_tmpb_tl
}
但它不起作用,我只想要保存在verbatim
风格,\l_tmpb_tl
不包含序列中存储的内容。这是我的平均能量损失。
\documentclass{article}
\usepackage{filecontentsdef}[2019/04/20]
\usepackage{xparse}
\usepackage{fvextra}
\setlength{\parindent}{0pt} % just for the example
\ExplSyntaxOn
\tl_new:c { l_scontents_macro_tmp_tl }
\keys_define:nn { scontents }
{
save-env .tl_set:N = \l_scontents_name_seq_tl,
save-env .initial:n = contents,
show-env .bool_set:N = \l_scontents_show_env_bool,
show-env .initial:n = false
}
% Adapted from https://tex.stackexchange.com/a/215571/7832
\cs_new_protected:Npn \_scontents_append_contents:nn #1 #2
{
\seq_if_exist:cF { g_scontents_seq_name_#1_seq }
{
\seq_new:c { g_scontents_seq_name_#1_seq }
}
\seq_gput_right:cn { g_scontents_seq_name_#1_seq } { #2 }
}
\cs_new_protected:Npn \_scontents_getfrom_seq:nn #1 #2
{
\seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
}
\ProvideExpandableDocumentCommand{\getstored}{ O{1} m }
{
\_scontents_getfrom_seq:nn { #1 } { #2 }
}
% Define scontents (wrap \filecontentsdefmacro) whit [key=val] Delaying
% Adapted from https://tex.stackexchange.com/a/487746/7832
\ProvideDocumentEnvironment{ scontents }{}
{
\char_set_catcode_active:N \^^M
\scontents_start_environment:w
}
{
\scontents_stop_environment:
\scontents_atend_environment:
}
\cs_new_protected:Npn \scontents_environment_keys:w [#1]
{
\keys_set:nn { scontents } { #1 }
}
% Star environment
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \scontents_start_environment:w #1 ^^M
{
\tl_if_blank:nF { #1 } { \scontents_environment_keys:w #1 }
\group_begin: % open group for env
\use:c { filecontentsdefmacro } { \l_scontents_macro_tmp_tl } ^^M
}
\group_end:
% Stop environment
\cs_new_protected:Nn \scontents_stop_environment:
{
\endfilecontentsdefmacro
\group_end: % close group for env
}
% A variant to replace \^^M for \^^J (need by Verb{..} from fvextra)
% https://tex.stackexchange.com/a/8971/7832
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nxx }
% Expand \l_tmpa_tl and pass to seq
\cs_gset_protected:Nn \_scontents_macro_to_seq:
{
\regex_replace_all:nnN { \^^M } { \^^J } \l_scontents_macro_tmp_tl
\cs_log:N \l_scontents_macro_tmp_tl
\exp_args:NNx \_scontents_append_contents:nn \l_scontents_name_seq_tl
{
\exp_not:N \scantokens \exp_after:wN { \tl_use:c { l_scontents_macro_tmp_tl} } %
}
}
% Code after scontent environment \seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
\cs_new_protected:Nn \scontents_atend_environment:
{
\_scontents_macro_to_seq:
\bool_if:NT \l_scontents_show_env_bool
{
\_scontents_getfrom_seq:nn { -1 }{ \l_scontents_name_seq_tl }
}
\cs_undefine:N \l_scontents_macro_tmp_tl
}
% Fake \meaning
\tl_const:Nn \c_catcode_specials_tl { \ \\ \{ \} \$ \& \# \^ \_ \% \~ }
\cs_new_protected:Npn \_catcode_dospecials:
{
\tl_map_inline:Nn \c_catcode_specials_tl
{
\char_set_catcode_other:N ##1
}
}
\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\tl_put_right:Nx \l_tmpb_tl
{
\_catcode_dospecials:
\_scontents_getfrom_seq:nn { #1 }{ #2 }
}
%\tl_show:N \l_tmpb_tl
}
\ExplSyntaxOff
\begin{document}
\section*{Test environment}
Test \verb+\begin{scontents}+ no \verb+[key=val]+\par
\begin{scontents}
Using \verb+scontents+ env no \verb+[key=val]+, save in \verb+contents+
with index $1$\footnote{AND footnotes !!}.%
Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+
\begin{Verbatim}
(A) verbatim environment %
many space here and percent at end of line %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
\end{scontents}
\section*{Show stored contents}
XX\getstored[1]{contents}NO space here :)\par
\section*{typestored}
%\typestored[1]{contents} % not work
\end{document}
如果我删除评论\tl_show:l \l_tmpb_tl
并\typestored[1]{contents}
进入log
文件:
\l_tmpb_tl=\_catcode_dospecials: \_scontents_getfrom_seq:nn {1}{contents}
正如@David Carlisle在他的评论中所说,这不是我想要的。我希望它包含:
\l_tmpb_tl=Using \verb+scontents+ env no \verb+[key=val]+, save in
\verb+contents+
with index $1$\footnote{AND footnotes !!}.%
Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+
\begin{Verbatim}
(A) verbatim environment %
many space here and percent at end of line %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
该包的作者提供了宏\filecontentsprint
,我尝试使用存储在序列中的内容来模仿它。它应该看起来像这样(或类似):
编辑1
第一次尝试,通过定义'\typestored'如下:
\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\tl_put_right:Nx \l_tmpb_tl
{
\seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
}
\regex_replace_once:nnN { ^ \c{scantokens} } { \c{#2[#1]} } \l_tmpb_tl
\tl_show:N \l_tmpb_tl
\small\texttt{\meaning\l_tmpb_tl}
}
我得到:
这几乎就是我想要的,当然,这打破了问题的标题(我不需要修改 catcode),我需要用a 替换和Ω
(我不知道怎么做)。我希望这能更好地说明我想要什么(我的英语不是最好的,西班牙语是我的语言)。ΩΩ
regex
编辑2
\filecontentsprint
第二次尝试,我从样式文件中复制了定义并添加了newvbtm
包以避免与经典verbatim
环境发生冲突。它一点也不优雅,也没有遵循我想要的路线,代码对我来说有点“模糊”,但它有效。
% Fake \meaning, copy direct from filecontensdef package
% Add \usepackage{newvbtm} to solve conflict whit verbatim nested
\newverbatim{typescverb}{}{}{}{}
\makeatletter
\gdef\filecontentsprint{\filecontentsdef@get\filecontents@print}%
\catcode`\^^M\active%
\gdef\filecontents@print #1{\let\filecontents@print@EOL^^M\let^^M\relax%
\begingroup\toks@\expandafter{#1}\edef\x{\endgroup%
\noexpand\begin{typescverb}^^M%
\the\toks@\@backslashchar end\string{typescverb\string}}\x^^M%
\filecontents@print@resetEOL}%
\gdef\filecontents@print@resetEOL{\let^^M\filecontents@print@EOL}%
\makeatother
\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\group_begin:
\tl_put_right:Nx \l_tmpb_tl
{
\seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
}
\filecontentsprint\l_tmpb_tl
\group_end:
}
我所寻找的,当然,这样做你会失去用心做事 expl3
通过混合LaTeX2e
代码。
问候。
答案1
由于您似乎热衷于遵循expl3
指南,我建议您查看“expl3
软件包和 LaTeX3 编程”(texdoc expl3
) 和“LaTeX3 内核:代码作者的风格指南”(texdoc l3styleguide
)。这是两篇简短的文档,介绍了的基本概念expl3
和优选的编码风格。
也就是说,我将您问题中的代码翻译成了expl3
语法,并稍微改变了您的代码以纳入上述准则。
首先,代码的翻译。
这个答案比代码更概念化,所以我保留了它,\newverbatim
因为它已经在工作了。正如我在评论中所说:您正在将 LaTeX2ε 与 LaTeX3 连接起来,因此您最终必须将一些 2ε 放进去,主要是如果该代码来自包的话。既然您已经在使用了\filecontentsdefmacro
,那么我想\newverbatim
没问题。
我放弃了\makeatletter
(那是在喊“我是 LaTeX2ε c@de!”:-)。我复制了一份以便在代码filecontentsdef@get
中使用,这样你就不需要:expl3
\cs_new_eq:Nc
\makeatletter
\cs_new_eq:Nc \__scontents_fcdef_get:NN { filecontentsdef@get }
接下来,我们使^^M
(组内) 活跃起来:
\group_begin:
\char_set_catcode_active:N \^^M
现在来看看主要的宏。首先,理清一下代码:
\gdef\filecontents@print#1{%
\let\filecontents@print@EOL^^M%
\let^^M\relax%
\begingroup%
\toks@\expandafter{#1}%
\edef\x{%
\endgroup%
\noexpand\begin{typescverb}^^M%
\the\toks@%
\@backslashchar end\string{typescverb\string}%
}\x^^M%
\filecontents@print@resetEOL%
}
首先,代码保存了 的定义^^M
,并使其成为无操作的\let^^M\relax
。我们做同样的事情:
\cs_new_protected:Npn \__scontents_fcdef_print:N #1
{
\cs_set_eq:NN \__scontents_fcdef_saved_EOL: ^^M
\cs_set_eq:NN ^^M \scan_stop:
请注意,的范围\cs_new_protected:
是全局的,因此\gdef
已经涵盖。此外,函数包含赋值,因此它无法在仅扩展的上下文中扩展,因此您需要protected
。
现在代码将宏的扩展保存到 中,然后在中\toks@
使用。之所以使用这种方法是因为只扩展一次,即使在 内部也是如此,因此它允许在 TeX 中使用类似 ε-TeX 的东西(实际上恰恰相反:在 内部或多或少地执行操作以防止 进一步扩展)。可以使用 (在 中)完成相同的操作,而无需。由于(以及 LaTeX2ε,就此而言)无论如何都需要 ε-TeX,所以这样做没有坏处。更多\edef
\the\toks@
\the\toks@
\edef
\unexpanded
\unexpanded{<stuff>}
\toks@{<stuff>}\the\toks@
<stuff>
\edef
\unexpanded\expandafter{#1}
\toks@
expl3
expl3
是版本是\exp_not:V #1
,它检索的内容#1
并防止进一步扩展。
这段代码也使用了\begingroup\edef\x{\endgroup<stuff to be expanded>}\x
。这正是x
中的扩展所做的事情expl3
,只不过由于使用了私有临时宏,因此不使用分组。因此,我们可以用 替换所有这些\use:x
。
最后,\@backslashchar end\string{typescverb\string}
用等效字符串替换expl3
。将所有这些放在一起:
\use:x
{
\exp_not:N \begin{typescverb} ^^M
\exp_not:V #1
\c_backslash_str end \c_left_brace_str typescverb \c_right_brace_str
}
^^M
最后我们重置^^M
并结束我们从那里开始的组:
\cs_set_eq:NN ^^M \__scontents_fcdef_saved_EOL:
}
\group_end:
现在,对代码进行一些总体说明。
其中,expl3
内部、代码级和用户级函数和变量有明显区别。用户级是用 等定义的代码xparse
,\NewDocumentCommand
最终用户将在文档中使用它。
代码级函数和变量将用于用户级代码的实现以及跨不同模块。这些应该记录下来,并以\<module>_function_name:<args>
函数和\(l|g|c)_variable_name_<type>
变量命名。这些示例分别是\seq_item:Nn
和\l_tmpa_tl
。
最后,内部代码用于前一级别的实现和细节。这些函数永远不应在定义它们的模块之外使用。它们被命名为\__<module>_macro_name:<args>
和\(l|g|c)__variable_name_<type>
。请注意这两种情况下的双下划线。这些示例是\__seq_item:wNn
和\l__char_tmp_tl
。
在您的代码中,您使用了许多\_scontents...
,它介于代码级和内部级之间。您应该决定:如果您希望其他程序员使用它,那么\scontents...
,否则它是内部代码,应该是\__scontents...
。变量也是如此。
您还应该记住使用正确的\cs_new...
函数。如果定义是可扩展的,并且您需要它可扩展,那么您需要\cs_new:Npn
(或类似函数)。在其他所有情况下,函数都应使用\cs_new_protected:Npn
(或类似函数) 进行定义。\__scontents_getfrom_seq:nn
使用\seq_item:Nn
(可扩展) 从seq
变量中获取内容。如果您希望此函数在 -type 扩展中扩展,则x
不能使用 来定义它\cs_new_protected:Npn
,否则它不会扩展。仅\cs_new:Npn
在此处使用。
还要记住根据传递给函数的参数类型使用适当的变体。假设你定义一个函数,比如,\cs_new:Npn \my_use:n #1 { \use:c { my_#1_command_name: } }
使用 as\my_use:n { funny }
和 get \my_funny_command_name:
(抱歉举了个愚蠢的例子),TeX 允许你这样做\tl_set:Nn \l_my_tl { funny }
,然后\my_use:n { \l_my_tl }
因为\use:c
( \csname
) 会随着操作而扩展\l_my_tl
。但你真的应该不是那就这么做吧!在这种特殊情况下,不会出现任何问题。但是,假设现在您想禁止 的参数为空\my_use:n
,则可以使用以下命令定义它:
\cs_new:Npn \my_use:n #1
{
\tl_if_empty:nTF {#1}
{ \msg_error:nn { mymodule } { empty-arg } }
{ \use:c { my_#1_command_name: } }
}
如果您使用,\my_use:n { }
则会发出错误消息,但如果您这样做\tl_clear:n \l_my_tl
,则\my_use:n { \l_my_tl }
错误不会显示!这里使用\my_use:n
with 的正确方法\l_my_tl
是\exp_args:NV \my_use:n \l_my_tl
或简单地\my_use:V \l_my_tl
使用正确的变体定义。
某个地方你有\cs_undefine:N \l__scontents_macro_tmp_tl
。那是非常错误!\cs_undefine:N
应该用来使c
控制s
序列未定义,但却\l__scontents_macro_tmp_tl
是t
oken l
ist。是的,它确实有效,是的,令牌列表本质上是控制序列,但从概念上讲这是错误的。变量一旦分配,\<type>_new:N
就应该“永远”存在并被重复使用。您在这里想要的可能是\tl_clear:N
清除该令牌列表的内容。
函数\_catcode_dospecials:
和变量\c_catcode_specials_tl
应该命名为\__scontents_catcode_dospecials:
,\c_scontents_catcode_specials_tl
因为你正在创建的模块是scontents
,而不是catcode
。还要注意expl3
定义了一个包含你需要的特殊字符的seq
变量,所以你\l_char_special_seq
不需要自己定义序列,并可以简化定义\__scontents_catcode_dospecials:
:
\cs_new_protected:Npn \__scontents_catcode_dospecials:
{ \seq_map_function:NN \l_char_special_seq \char_set_catcode_ignore:N }
但是您没有在代码中使用它,所以我将其删除了。
只有在有充分理由的情况下才应使用\ProvideDocumentCommand
and 。在所有其他情况下,您都应坚持使用(或如果重新定义)以避免意外。通常,“命令已定义”错误很有帮助。\DeclareDocumentCommand
\NewDocumentCommand
\RenewDocumentCommand
您还应避免使用\l_tmpa_tl
LaTeX3 内核定义的其他临时变量。当然可以使用它们,但只能在临时代码中使用(例如,如果您正在测试某些内容)。如果代码超出了临时范围,则应声明一个变量并使用该变量。这将避免使用相同临时变量的包之间发生不必要的交互。
我还将 的定义改为 ,\typestored
因为\tl_put_right:Nx
您\tl_set:Nx
实际上并不想添加到标记列表的现有内容中。如果您忘记清除标记列表,这将导致较长的代码出现问题(例如,如果其他一些包代码使用\l_tmpb_tl
并忘记清除它,它们的内容就会潜入您的代码中)。
为了允许使用fancyvrb
而不是 ,newvbtm
我不得不稍微改变 的时间\scantokens
。显然,逐字环境是这样的:
\begin{typescverb}
\scantokens{<stuff>}
\end{typescverb}
(代码就是这么做的),用 定义的环境newvbtm
会扩展(以某种方式),事情会按计划进行。然而,用 定义的相同环境不会,它会认为整个东西只是一行代码,并按此方式排版。要让它工作,您需要更改为:\scantokens
fancyvrb
fancyvrb
\scantokens{
\begin{typescverb}
<stuff>
\end{typescverb}
}
但是,要做到这一点,您需要\scantokens
从 周围删除<stuff>
,因此我将标记列表变量传递给一个\__scontents_strip_scantokens:N
宏,该宏扩展标记列表,检查第一个标记是否为\tex_scantokens:D
。 如果是(即标记列表是\scantokens{<stuff>}
),则它扩展为\unexpanded{<stuff>}
。 否则它返回未更改的标记列表。
说了这么多,下面是修改后的代码:
\documentclass{article}
\usepackage{filecontentsdef}[2019/04/20]
\usepackage{xparse}
\usepackage{fvextra}
\setlength{\parindent}{0pt} % just for the example
\ExplSyntaxOn
\tl_new:N \l__scontents_macro_tmp_tl
\tl_new:N \l__scontents_tmpa_tl
\keys_define:nn { scontents }
{
save-env .tl_set:N = \l__scontents_name_seq_tl,
save-env .initial:n = contents,
show-env .bool_set:N = \l__scontents_show_env_bool,
show-env .initial:n = false
}
% Adapted from https://tex.stackexchange.com/a/215571/7832
\cs_new_protected:Npn \__scontents_append_contents:nn #1#2
{
\seq_if_exist:cF { g__scontents_seq_name_#1_seq }
{ \seq_new:c { g__scontents_seq_name_#1_seq } }
\seq_gput_right:cn { g__scontents_seq_name_#1_seq } {#2}
}
\cs_new:Npn \__scontents_getfrom_seq:nn #1#2
{ \seq_item:cn { g__scontents_seq_name_#2_seq } {#1} }
\NewExpandableDocumentCommand { \getstored } { O{1} m }
{ \__scontents_getfrom_seq:nn {#1} {#2} }
% Define scontents (wrap \filecontentsdefmacro) whit [key=val] Delaying
% Adapted from https://tex.stackexchange.com/a/487746/7832
\NewDocumentEnvironment { scontents } { }
{
\char_set_catcode_active:N \^^M
\scontents_start_environment:w
}
{
\scontents_stop_environment:
\scontents_atend_environment:
}
\cs_new_protected:Npn \scontents_environment_keys:w [ #1 ]
{ \keys_set:nn { scontents } {#1} }
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \scontents_start_environment:w #1 ^^M
{
\tl_if_blank:nF {#1} { \scontents_environment_keys:w #1 }
\group_begin: % open group for env
\filecontentsdefmacro { \l__scontents_macro_tmp_tl } ^^M
}
\cs_new_protected:Nn \scontents_stop_environment:
{
\endfilecontentsdefmacro
\group_end: % close group for env
}
\group_end:
\exp_args_generate:n { Vx }
\cs_gset_protected:Nn \__scontents_macro_to_seq:
{
\regex_replace_all:nnN { \^^M } { \^^J } \l__scontents_macro_tmp_tl
\cs_log:N \l__scontents_macro_tmp_tl
\exp_args:NVx \__scontents_append_contents:nn \l__scontents_name_seq_tl
{ \exp_not:N \tex_scantokens:D { \tl_use:N \l__scontents_macro_tmp_tl } }
}
% Code after scontent environment \seq_item:cn { g__scontents_seq_name_#2_seq } { #1 }
\cs_new_protected:Nn \scontents_atend_environment:
{
\__scontents_macro_to_seq:
\bool_if:NT \l__scontents_show_env_bool
{ \exp_args:NnV \__scontents_getfrom_seq:nn { -1 } { \l__scontents_name_seq_tl } }
\tl_clear:N \l__scontents_macro_tmp_tl
}
\DefineVerbatimEnvironment{typescverb}{Verbatim}{}
\cs_new_eq:Nc \__scontents_fcdef_get:NN { filecontentsdef@get }
\quark_new:N \q__scontents_strip_quark
\cs_new:Npn \__scontents_strip_scantokens:N #1
{ \exp_args:NV \__scontents_strip_scantokens:n #1 }
\cs_new:Npn \__scontents_strip_scantokens:n #1
{
\tl_if_head_is_N_type:nTF {#1}
{
\__scontents_if_scantokens:NwTF #1 \q__scontents_strip_quark
{ \exp_not:o { \use_ii:nn #1 } }
{ \exp_not:n {#1} }
}
{ \exp_not:n {#1} }
}
\prg_new_conditional:Npnn \__scontents_if_scantokens:Nw
#1 #2 \q__scontents_strip_quark { TF }
{
\token_if_eq_meaning:NNTF \tex_scantokens:D #1
{ \prg_return_true: }
{ \prg_return_false: }
}
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \__scontents_fcdef_print:N #1
{
\cs_set_eq:NN \__scontents_fcdef_saved_EOL: ^^M
\cs_set_eq:NN ^^M \scan_stop:
\use:x
{
\exp_not:N \tex_scantokens:D
{
\exp_not:N \begin{typescverb} ^^M
\__scontents_strip_scantokens:N #1
\c_backslash_str end \c_left_brace_str typescverb \c_right_brace_str ^^M
}
}
\cs_set_eq:NN ^^M \__scontents_fcdef_saved_EOL:
}
\group_end:
\NewDocumentCommand { \typestored } { O{1} m }
{
\group_begin:
\tl_set:Nx \l__scontents_tmpa_tl
{ \seq_item:cn { g__scontents_seq_name_#2_seq } {#1} }
\__scontents_fcdef_get:NN \__scontents_fcdef_print:N \l__scontents_tmpa_tl
\group_end:
}
\ExplSyntaxOff
\begin{document}
\section*{Test environment}
Test \verb+\begin{scontents}+ no \verb+[key=val]+\par
\begin{scontents}
Using \verb+scontents+ env no \verb+[key=val]+, save in \verb+contents+
with index $1$\footnote{AND footnotes !!}.%
Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+
\begin{Verbatim}
(A) verbatim environment %
many space here and percent at end of line %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
\end{scontents}
\section*{Show stored contents}
XX\getstored[1]{contents}NO space here :)\par
\section*{typestored}
\typestored[1]{contents} % not work
\end{document}