如何在每次出现某个命令时自动将出现次数放置在 xparse 环境内?

如何在每次出现某个命令时自动将出现次数放置在 xparse 环境内?

有一个 (xparse) 环境\myEnv,并且\myCo该环境中用户提供了未指定数量的命令。我需要为该环境编写一个代码,该代码将计算出现的次数并在每次出现\myCo时显示该数字。\myCo

\documentclass[varwidth]{standalone}

\usepackage{expl3}
\usepackage{xparse}

\def\myCo{}

\begin{document}
  \ExplSyntaxOn
    \NewDocumentEnvironment{myEnv}{+b}
      { #1 % before displaying the contents,
           %  I need to count how many \myCo
           %   occurrences there are and display this number
           %    at each occurrence of \myCo
      } {}
  \ExplSyntaxOff
  \begin{myEnv}
    \myCo This is sentence 1. This is sentence 2.\myCo This is sentence 3.\myCo This is sentence 4. This is sentence 5. This is sentence 6.\myCo
  \end{myEnv}
\end{document}

我希望输出看起来像这样:(4)这是句子 1。这是句子 2。(4)这是句子 3。(4)这是句子 4。这是句子 5。这是句子 6。(4)

其中(4)是命令的数量\myCo

答案1

对于这两件事,你可以使用LaTeX3正则表达式。要计算出现的次数,\myCo您可以使用\regex_count:nnN,然后可以使用\regex_replace_all:nnN在命令的每个实例后插入计数。控制序列的正则表达式匹配\myCo是,\c{myCo}因此要查找出现的次数,您可以使用类似以下内容:

\regex_count:nnN {\c{myCo}} {#1} \l_tmpa_int

并且\regex_replace_all:nnN命令类似。有了这个,您的 MWE 产生的输出是预期的:

在此处输入图片描述

以下是完整的代码。

\documentclass[varwidth, border=10mm]{standalone}

\usepackage{expl3}
\usepackage{xparse}

\def\myCo{}

\begin{document}
  \ExplSyntaxOn
    \int_new:N \l_myCo_int
    \tl_new:N \l_myenv_tl
    \NewDocumentEnvironment{myEnv}{+b}
      {
      \regex_count:nnN {\c{myCo}} {#1} \l_myCo_int
      \tl_set:Nn \l_myenv_tl {#1}
      \regex_replace_all:nnN {\c{myCo}} 
         {\c{myCo}~(\c{int_use:N} \c{l_myCo_int})} \l_myenv_tl
      \tl_use:N \l_myenv_tl
      } {}
  \ExplSyntaxOff
  \begin{myEnv}
    \myCo This is sentence 1. This is sentence 2.\myCo 
    This is sentence 3.\myCo This is sentence 4. 
    This is sentence 5. This is sentence 6.\myCo
  \end{myEnv}
\end{document}

答案2

\myCo如果您的环境的内容不包含反向前进命令,您可以简单地在丢弃的框中排版内容,从而改变框内部的含义。

\documentclass{article}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\myCo}{}
 {
  \__bp_myco:
 }
\NewDocumentEnvironment{myEnv}{+b}
  {
   \int_zero:N \g__bp_myco_int
   \vbox_set:Nn \l_tmpa_box
    {
     \cs_set:Nn \__bp_myco: { \int_gincr:N \g__bp_myco_int }
     #1
    }
   #1
  }{}

\int_new:N \g__bp_myco_int
\cs_new:Nn \__bp_myco:
 {
  (\int_to_arabic:n { \g__bp_myco_int })
 }
\ExplSyntaxOff

\begin{document}

\begin{myEnv}
\myCo\ This is sentence 1. 
This is sentence 2. \myCo\ This is sentence 3. \myCo\ This is sentence 4. 
This is sentence 5. This is sentence 6.\myCo
\end{myEnv}

\end{document}

在此处输入图片描述

答案3

如果您需要\myCo对环境的每个实例和每个嵌套级别分别计算单个实例数myEnv,则可以通过定义来实现myEnv\myCo其中 LaTeX 同时计算myEnv-environment 的实例数和 -macro 的实例数\myCo,并且在环境结束时发出\label用于检索最后一个值的命令。\myComyEnv

如果您有 LaTeX\myCo按照 来计算 s \refstepcounter,您可以\label在它们后面放置命令以供引用。

我以一种你可以用或不用的方式实现了一些东西超链接包裹。

加载时超链接,无需创建超链接即可通过 进行引用\ref*
但是,在没有创建超链接的情况下,无法使用“加星号”引用命令超链接。因此我使用了引用计数无需创建超链接
即可实现引用命令的包。无论超链接已加载 或者 未加载。

正如内部使用的\label..\ref那样\getrefbykeydefault,您需要至少编译示例两次/直到警告
LaTeX Warning: There were undefined references.不再
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right
出现在控制台/日志文件中。

\documentclass{article}

%\usepackage{hyperref}
\usepackage{refcount}
\usepackage{xspace}

\makeatletter
\newcommand\nolinkref[1]{%
  \IfRefUndefinedBabel{#1}{%
    \refused{#1}%
    \nfss@text {\reset@font \bfseries ??}%
  }{%
    \getrefbykeydefault{#1}{}{0}%
  }%
}%

\newcounter{myEnvCtr}
\newcounter{myCoCtr}[myEnvCtr]
\def\theHmyEnvCtr{\arabic{myEnvCtr}}
\def\theHmyCoCtr{myEnvInstance\myEnv@THISmyEnvCtr.\arabic{myCoCtr}}
\def\themyCoCtr{\arabic{myCoCtr}}

\newcommand\myEnv@SAVEDcurrentlabel{}
\newcommand\myEnv@SAVEDcurrentHref{}
\newcommand\myEnv@SAVEDcurrentlabelname{}
\newcommand\myEnv@SAVEDmyCoCtr{}
\newcommand\myEnv@THISmyEnvCtr{0}

\newcommand\myCo{%
  \refstepcounter{myCoCtr}%
  % Save the referencing-data from the last \myCo:
  \let\myEnv@SAVEDcurrentlabel=\@currentlabel
  \let\myEnv@SAVEDcurrentHref=\@currentHref
  \let\myEnv@SAVEDcurrentlabelname=\@currentlabelname
  % In case of using zref-package or the like you may need
  % to add the saving of the values of some more
  % referencing-properties here.
  (\nolinkref{myEnvInstance.\[email protected]})\xspace%
}%
\newenvironment{myEnv}{%
  \edef\myEnv@SAVEDmyCoCtr{\number\value{myCoCtr}}%
  \stepcounter{myEnvCtr}%
  \edef\myEnv@THISmyEnvCtr{\number\value{myEnvCtr}}%
}{%
  \ifnum\number\value{myCoCtr}>0 %
    \begingroup
      % Restore the referencing-data from the last \myCo:
      \let\@currentlabel=\myEnv@SAVEDcurrentlabel
      \let\@currentHref=\myEnv@SAVEDcurrentHref
      \let\@currentlabelname=\myEnv@SAVEDcurrentlabelname
      % In case of using zref-package or the like you may need
      % to add the restoring of the values of some more 
      % referencing-properties here.
      \label{myEnvInstance.\[email protected]}%
    \endgroup
  \fi
  \setcounter{myCoCtr}{\myEnv@SAVEDmyCoCtr}%
}%

\makeatother

\begin{document}

\footnotesize

\begin{myEnv}
  \myCo This is sentence 1. This is sentence 2.\myCo This is sentence 3.\myCo This is sentence 4. This is sentence 5. This is sentence 6.\myCo
\end{myEnv}

\bigskip

\bigskip

\noindent Now with nesting:

\bigskip

\begin{myEnv}
\noindent \verb|myEnv| -- nesting-level 0 -- nesting level 0 has \nolinkref{myEnv0last} \verb|\myCo|:\\
\myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 0's 1\textsuperscript{st} \verb|\myCo|.\\
\myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 0's 2\textsuperscript{nd} \verb|\myCo|.\\

  \begin{myEnv}
  \noindent \verb|myEnv| -- nesting-level 1 -- nesting level 1 has \nolinkref{myEnv1last} \verb|\myCo|:\\
  \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 1's 1\textsuperscript{st} \verb|\myCo|.\\
  \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 1's 2\textsuperscript{nd} \verb|\myCo|.\\

    \begin{myEnv}
    \noindent \verb|myEnv| -- nesting-level 2a -- nesting level 2a has \nolinkref{myEnv2alast} \verb|\myCo|:\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 1\textsuperscript{st} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 2\textsuperscript{nd} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 3\textsuperscript{rd} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 4\textsuperscript{th} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 5\textsuperscript{th} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 6\textsuperscript{th} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 7\textsuperscript{th} \verb|\myCo|.\\
    \myCo {}\label{myEnv2alast}%
          $\leftarrow$This number in parentheses comes from myEnv's nesting level 2a's 8\textsuperscript{th} \verb|\myCo|.\\
    \end{myEnv}

  \noindent Back to \verb|myEnv| -- nesting-level 1 which has \nolinkref{myEnv1last} \verb|\myCo|:\\
  \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 1's 3\textsuperscript{rd} \verb|\myCo|.\\
  \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 1's 4\textsuperscript{th} \verb|\myCo|.\\

    \begin{myEnv}
    \noindent \verb|myEnv| -- nesting-level 2b -- nesting level 2b has \nolinkref{myEnv2blast} \verb|\myCo|:\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2b's 1\textsuperscript{st} \verb|\myCo|.\\
    \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 2b's 2\textsuperscript{nd} \verb|\myCo|.\\
    \myCo {}\label{myEnv2blast}%
          $\leftarrow$This number in parentheses comes from myEnv's nesting level 2b's 3\textsuperscript{rd} \verb|\myCo|.\\
    \end{myEnv}

  \noindent Back to \verb|myEnv| -- nesting-level 1 which has \nolinkref{myEnv1last} \verb|\myCo|:\\
  \myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 1's 5\textsuperscript{th} \verb|\myCo|.\\
  \myCo {}\label{myEnv1last}%
        $\leftarrow$This number in parentheses comes from myEnv's nesting level 1's 6\textsuperscript{th} \verb|\myCo|.\\
  \end{myEnv}

\noindent Back to \verb|myEnv| -- nesting-level 0 which has \nolinkref{myEnv0last} \verb|\myCo|:\\
\myCo {}$\leftarrow$This number in parentheses comes from myEnv's nesting level 0's 3\textsuperscript{rd} \verb|\myCo|.\\
\myCo {}\label{myEnv0last}%
      $\leftarrow$This number in parentheses comes from myEnv's nesting level 0's 4\textsuperscript{th} \verb|\myCo|.\\
\end{myEnv}

\end{document}

在此处输入图片描述

相关内容