计算命令在枚举环境中出现的次数

计算命令在枚举环境中出现的次数

我正在尝试创建一种机制来了解环境中重复命令的次数是否enumerate存在。

举例来说,使用以下\dummy命令,这将是一个有效的条目:

\begin{enumerate}
  \item Level 1 \dummy{1} OK
  \item Level 1 \dummy{2} OK
\end{enumerate}

无效条目为:

\begin{enumerate}
  \item Level 1 \dummy{1} OK
  \item Level 1 NO dummy here.
\end{enumerate}

由于环境可以嵌套,有效条目可以采用以下形式:

\begin{enumerate}
  \item Level 1 \dummy{1} OK
  \item Level 1 NO dummy here, dummy in next level
    \begin{enumerate}
      % Start level 2
      \item Level 2 \dummy{2} OK
      \item Level 2 NO dummy here, dummy in next level
        \begin{enumerate}
          % Start level 3
          \item Level 3 \dummy{3} OK
          \item Level 3 NO dummy here, dummy in next level
            \begin{enumerate}
              % Start level 4
              \item Level 4 \dummy{4} OK
              \item Level 4 \dummy{5} OK
            \end{enumerate}
          \item Level 3 \dummy{6} OK
        \end{enumerate}
      \item Level 2 \dummy{7} OK
    \end{enumerate}
  \item Level 1 \dummy{8} OK
\end{enumerate}

对于下一个 MWE,我预计最终输出将是{ TRUE }

\documentclass{article}
\ExplSyntaxOn
% Copy macros
\cs_new_eq:NN \_enumerate_start: \enumerate
\cs_new_eq:NN \_enumerate_stop: \endenumerate
\NewCommandCopy{ \_item_std }{ \item }

% Vars
\int_new:N \g_enumerate_level_int
\int_new:N \g_enumerate_item_int

% Redefine enumerate
\RenewDocumentEnvironment{enumerate}{ }
  {
    \int_gincr:N \g_enumerate_level_int
    \_redefine_item:
    \_enumerate_start:
  }
  {
    \_enumerate_stop:
    \int_compare:nTF { \g_enumerate_level_int = \g_enumerate_item_int }
      { TRUE }{ FALSE }
  }

% Redefine \item
\cs_new_protected:Npn \_redefine_item:
  {
    \RenewDocumentCommand\item{ o }
      {
        \int_gincr:N \g_enumerate_item_int
        %\int_compare:nT { \g_enumerate_level_int > 1 }
          %{
            %\int_gsub:Nn \g_enumerate_item_int { 1 }
          %}
        \tl_if_novalue:nTF {##1}
          {
            \_item_std%[Item ~ \int_use:N \g_enumerate_item_int]
          }
          { \_item_std[##1] }
      }
  }

\NewDocumentCommand\dummy{ m }
  {
    \int_gincr:N \g_tmpb_int
    \texttt{dummy~#1~=~\int_use:N \g_tmpb_int}
  }
\ExplSyntaxOff
\begin{document}
\begin{enumerate}
  \item Level 1 \dummy{1} OK % \g_enumerate_item_int = 1
  \item Level 1 NO dummy here, dummy in next level
    \begin{enumerate}
      % Start level 2
      \item Level 2 \dummy{2} OK % \g_enumerate_item_int = 2
      \item Level 2 NO dummy here, dummy in next level
        \begin{enumerate}
          % Start level 3
          \item Level 3 \dummy{3} OK % \g_enumerate_item_int = 3
          \item Level 3 NO dummy here, dummy in next level
            \begin{enumerate}
              % Start level 4
              \item Level 4 \dummy{4} OK % \g_enumerate_item_int = 4
              \item Level 4 \dummy{5} OK % \g_enumerate_item_int = 5
            \end{enumerate}
          \item Level 3 \dummy{6} OK % \g_enumerate_item_int = 6
        \end{enumerate}
      \item Level 2 \dummy{7} OK % \g_enumerate_item_int = 7
    \end{enumerate}
  \item Level 1 \dummy{8} OK % \g_enumerate_item_int = 8
\end{enumerate}
\end{document}

我怎样才能实现这个目标?

真实情况是问题/答案列表,目的是检查每个问题是否都有答案。

如果该行以 开头\item并且没有打开嵌套环境,则它必须有一个\dummy,如果该行以 开头\item并且打开嵌套环境,则\item嵌套环境中的每个都必须有一个 \dummy

答案1

这里有一种tokcycle方法,你可以将外部环境包装在 中\needdummytrue\tokencyclexpress...\endtokencyclexpress。它...在执行之前会预先分析 ,如果应该出现在 上但没有出现,或者出现在非预期的地方,则将 插入(MISSING)到环境中。\dummy\item(XTRA)\dummy

通过删除包装器,测试消失并且环境正常执行。

虽然这个 MWE 不会分析 OP 提供的“有效形式”,但这种方法是使用该输入运行的,并且没有检测到任何错误,正如预期的那样。

\documentclass{article}
\usepackage{tokcycle}
\def\dummy{DD}
\newif\ifneeddummy
\Macrodirective{%
  \ifx\item#1\ifneeddummy\addcytoks{(MISSING)}\else\needdummytrue\fi\fi
  \ifx\end#1\ifneeddummy\addcytoks{(MISSING)}\fi\fi
  \ifx\dummy#1\ifneeddummy\needdummyfalse\else\addcytoks{(XTRA)}\fi\fi
  \ifx\begin#1\ifneeddummy\needdummyfalse\else\addcytoks{(XTRA)}\fi\fi
  \addcytoks{#1}%
}
\begin{document}
\needdummytrue\tokencyclexpress
\begin{itemize}
\item \dummy
\item no dummy
  \begin{enumerate}
  \item \dummy
  \item no dummy
  \item \dummy
  \end{enumerate}
\item \dummy \dummy
\item \dummy
  \begin{enumerate}
  \item \dummy
  \end{enumerate}
\end{itemize}
\endtokencyclexpress
\end{document}

在此处输入图片描述

如果我注释掉包装行,我会得到相同的输出,但诊断消息被删除了。当然,如果没有注意到运行诊断的警告,输出可能会包含错误。

在此处输入图片描述

答案2

可能的解决方案(经过我的测试)并且符合我的需要:)

\documentclass{article}
\ExplSyntaxOn
% Copy macros
\cs_new_eq:NN \_enumerate_start: \enumerate
\cs_new_eq:NN \_enumerate_stop: \endenumerate
\NewCommandCopy{ \_item_std }{ \item }

% Vars
\int_new:N \g_enumerate_tempa_int
\int_new:N \g_enumerate_tempb_int
\int_new:N \g_enumerate_tempc_int
\int_new:N \l_enumerate_level_int
\int_new:N \g_enumerate_count_item_all_int

% Redefine enumerate
\RenewDocumentEnvironment{enumerate}{ }
  {
    \int_incr:N \l_enumerate_level_int
    \_enumerate_start:
    \_redefine_item:
    \int_case:nn{ \l_enumerate_level_int }
      {
        { 2 }{ \int_gincr:N \g_enumerate_tempa_int }
        { 3 }{ \int_gincr:N \g_enumerate_tempb_int }
        { 4 }{ \int_gincr:N \g_enumerate_tempc_int }
      }
  }
  { \_enumerate_stop: }

% Redefine \item
\cs_new_protected:Npn \_redefine_item:
  {
    \RenewDocumentCommand\item{ o }
      {
        \int_gincr:N \g_enumerate_count_item_all_int
        \tl_if_novalue:nTF {##1} { \_item_std } { \_item_std[##1] }
      }
  }

\NewDocumentCommand\dummy{ m }
  {
    \int_gincr:N \g_tmpb_int
    \texttt{dummy~#1~=~\int_use:N \g_tmpb_int}
  }
\NewDocumentCommand\test{ }
  {
   \int_gset:Nn \g_tmpa_int
     {
        \g_enumerate_count_item_all_int - \g_enumerate_tempa_int
      - \g_enumerate_tempb_int - \g_enumerate_tempc_int
     }
   % \int_show:N \g_tmpa_int
    \int_compare:nTF { \g_tmpa_int = \g_tmpb_int }
      { \typeout{TRUE}  }{ \typeout{FALSE} }
  }
\ExplSyntaxOff
\begin{document}

\begin{enumerate}
  \item Level 1 \dummy{1}
  \item Level 1 NO dummy
    \begin{enumerate}
      \item Level 2 \dummy{2}
      \item Level 2 NO dummy
        \begin{enumerate}
          \item Level 3 \dummy{3}
          \item Level 3 NO dummy
            \begin{enumerate}
              \item Level 4 \dummy{4}
              \item Level 4 \dummy{5}
            \end{enumerate}
          \item Level 3 \dummy{6}
        \end{enumerate}
      \item Level 2 NO dummy
        \begin{enumerate}
          \item Level 3 \dummy{7}
          \item Level 3 NO dummy
            \begin{enumerate}
              \item Level 4 \dummy{8}
              \item Level 4 \dummy{9}
            \end{enumerate}
          \item Level 3 \dummy{10}
        \end{enumerate}
      \item Level 2 \dummy{11}
    \end{enumerate}
  \item Level 1 \dummy{12}
  \item Level 1 \dummy{13}
  \item Level 1 NO dummy
    \begin{enumerate}
      \item Level 2 \dummy{14}
      \item Level 2 NO dummy
         \begin{enumerate}
           \item Level 3 \dummy{15}
          \end{enumerate}
       \item Level 2 \dummy{16}
     \end{enumerate}
\end{enumerate}

% TRUE
\test

\end{document}

相关内容