列表和新命令冲突

列表和新命令冲突

我想制作一个显示数字和相应代码的文档,并希望减少重复。下面的 MWE。我认为在新命令中列出列表有些奇怪。

\documentclass{article}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{mwe}


\newcommand{\figMe}[3]{
\begin{figure}
#3
\caption{#2. See Listing~\ref{lst#1} for code.}
\label{fig#1}
\end{figure}
\begin{lstlisting}[caption={#2. See Figure~\ref{fig#1}.},label={lst#1}]
#3
\end{lstlisting}
}

\begin{document}


\figMe{ex1}{Example drawing}{
\includegraphics{example-image-a}
}

\end{document}

谢谢您的回答。这就是我最终所做的,使用外部文件...

\newcommand{\figMeToo}[3]{
\begin{figure}
\input{#3}
\caption{#2 See Listing~\ref{lst#1} for code.}
\label{fig#1}
\end{figure}%\FloatBarrier
\lstinputlisting[frame=tb,caption={#2 See Figure~\ref{fig#1}.},label={lst#1},captionpos=b,language={[latex]TeX}]{#3}%\FloatBarrier
}

答案1

我以前为自己写过一些代码(我的一份文档),这些代码允许我根据需要将输入和输出分离。本答案中的代码重用了大部分代码,但这些定义中可能有一些死键对你不起作用,因为我是为自己的输出创建的。

我删除了一些键,但我可能忽略了其中一个。 、gappendno-appendafter都是有用的,但您必须用它们自己构建一些东西(我创建它们是gappend为了能够存储一些代码,稍后将其添加到另一个环境的输出中,但由于您的代码只有 1:1 的对应关系,我想这对您来说没什么用)。

此实现enverb将忽略第一个n其主体每行的字符,其中n是匹配前的空格数\end(所以这里是\end{figMe})加上为键指定的数字more-ignore(本例中为 2 - 这是我在文档中个人使用的缩进量)。我自己的文档不使用空格,<Tab>只使用空格,我不知道制表符与此配合得如何(假设它应该可以工作,但尚未经过广泛测试)。

这些是许多行实现(好吧,这是一个包草稿,所以就假装\makeatletter和之间的所有内容\makeatother都隐藏在后面\usepackage{enverb}),我用于输出的代码实际上只有 26 行代码:

\NewDocumentEnvironment{figMe}{mm}
  {\enverb} % enverb will collet an additional o-arg for its own options
  {%
    \enverbUnexpandedOutput
      {\begin{figure}}% pre-contents
      {% post-contents
        \caption
          {%
            #2. See Listing~\ref{lst#1} for code.%
            \label{fig#1}%
          }%
        \end{figure}%
      }%
    \enverbExpandedOutput
      {% pre-contents
        % we don't want to expand the begin part
        \unexpanded
          {%
            \begin{lstlisting}
              [caption={#2. See Figure~\ref{fig#1}.},label={lst#1}]%
          }%
      }
      % verbatim output in lstlistings needs to see the \end as a string without
      % a trailing space
      {\string\end{lstlisting}}% post-contents
  }

整个文档及enverb代码:

\documentclass{article}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{mwe}

\usepackage{expkv-def}

\makeatletter
\ExplSyntaxOn
\cs_new_eq:NN \enverb@count \tl_count:n
\cs_set:Npx \enverb@othercr { \char_generate:nn {13} {12} }
\ExplSyntaxOff
%% key setup
\ekvdefinekeys{enverb}
  {
     boolTF  auto-ignore   = \enverb@ifautoignore
    ,initial auto-ignore
    ,protected code ignore = \let\enverb@ifautoignore\@secondoftwo
    ,also eint      ignore = \enverb@ignore
    ,eint    more-ignore   = \enverb@moreignore
    ,initial more-ignore   = 2
    ,long store bol = \enverb@bol@content
    ,long store eol = \enverb@eol@content
    ,einitial   eol = \enverb@othercr
    ,data gappend   = \enverb@append
    ,code no-append = \let\enverb@append\@secondoftwo
    ,store after    = \enverb@after
  }
\protected\long\ekvsetdef\enverbsetup{enverb}

%% auxiliary error function
\newcommand\enverb@error[1]
  {%
    \GenericError
      {(enverb)\@spaces\@spaces\@spaces\@spaces\@spaces}%
      {Environment enverb error: #1}%
      {Just use it correctly!}%
      {Read the sources.}%
  }

%% setup for weird category code regime
\begingroup
\lccode`\~=`\^^M
\catcode`\:=13
\lccode`\:=`\ % <- space
\catcode`\;=13
\lccode`\;=`\^^I % <- tab
\lowercase{\endgroup
%% code for spaces and CR
\def\enverb@body@space{}%
\def\enverb@body@tab{}%
\def\enverb@body@newline#1~%
  {\enverb@ifnotend{#1}{\enverb@bol\unexpanded{#1}\enverb@eol~}}%
%% activate the category code regime of the body
\protected\def\enverb@body@setup
  {%
    \let\enverb@collected@body\@empty
    \let\do\@makeother\dospecials
    \catcode`\^^M=13 \let~\enverb@body@newline
    \catcode`\   =13 \let:\enverb@body@space
    \catcode`\^^I=13 \let;\enverb@body@tab
    \let\enverb@bol\relax
    \let\enverb@eol\relax
  }
%% check for optional argument
\newcommand\enverb@search@oarg@a
  {%
    \ifx:\next
      \ifenverb@firsteol
      \else
        \enverb@body@add{:}%
      \fi
      \let\next\enverb@search@oarg@b
    \else
      \ifx~\next
        \ifenverb@firsteol
          \enverb@firsteolfalse
        \else
          \enverb@body@add{~}%
        \fi
        \let\next\enverb@search@oarg@b
      \else
        \ifx[\next\@gobble]%
          \let\next\enverb@oarg
        \else
          \ifenverb@firsteol
            \let\next\enverb@body@after@begin
          \else
            \let\next\enverb@body
          \fi
        \fi
      \fi
    \fi
    \next
  }
%% start body collection
\newcommand\enverb@body
  {\edef\enverb@collected@body{\iffalse}\fi\expandafter~\enverb@collected@body}
%% check the line after an oarg
\def\enverb@body@after@oarg#1~%
  {\enverb@ensure@blank{#1}{closing bracket}\enverb@body}
%% check the line after the \begin statement
\def\enverb@body@after@begin#1~%
  {\enverb@ensure@blank{#1}{\string\begin}\enverb@body}
}
%% quick check for empty line
\newcommand\enverb@ensure@blank[2]
  {%
    \expandafter\enverb@ifempty\expanded{{#1}}{}%
      {%
        \expanded{%
        \noexpand\enverb@error
          {%
            Line after #2 not empty.\noexpand\MessageBreak
            Contains: \detokenize\expandafter{\romannumeral`\^^@#1}%
          }%
        }%
      }%
  }
%% quick check for empty argument
\newcommand\enverb@ifempty[1]
  {%
    \enverb@ifempty@\enverb@ifempty@A#1\enverb@ifempty@B.\enverb@ifempty@true
      \enverb@ifempty@A\enverb@ifempty@B
  }
\def\enverb@ifempty@#1\enverb@ifempty@A\enverb@ifempty@B#2#3{#3}
\def\enverb@ifempty@true\enverb@ifempty@A\enverb@ifempty@B#1#2{#1}
\newcommand\enverb@gadd[2]{\xdef#1{\unexpanded\expandafter{#1#2}}}
\newcommand\enverb@body@add[1]
  {%
    \edef\enverb@collected@body
      {\unexpanded\expandafter{\enverb@collected@body#1}}%
  }
% start of environment `enverb'
\newcommand\enverb
  {%
    \begingroup
      \def\tmp{enverb}%
      \expandafter
    \endgroup
    \expandafter\enverb@ifnotend@setup@perhaps\expanded
      {{\string{\@currenvir\string}}}%
    \begingroup
    \enverb@body@setup
    \enverb@firsteoltrue
    \let\enverb@collected@oarg\@empty
    \enverb@search@oarg
  }
\newif\ifenverb@firsteol
\newcommand\enverb@search@oarg{\futurelet\next\enverb@search@oarg@a}
\newcommand\enverb@search@oarg@b{\expandafter\enverb@search@oarg\@gobble}
\newcommand\enverb@oarg{\endgroup\enverb@oarg@}
\NewDocumentCommand\enverb@oarg@{O{}}
  {%
    \edef\enverb@collected@oarg{\unexpanded{#1}}%
    \begingroup
    \enverb@body@setup
    \enverb@body@after@oarg
  }
\def\enverb@ifnotend#1%
  {%
    \def\enverb@ifnotend##1%
      {%
        \enverb@ifnotend@
          ##1\enverb@mark\enverb@ifnotend@maybe
          #1\enverb@mark\@thirdofthree
          \enverb@stop
      }%
    \def\enverb@ifnotend@##1#1##2\enverb@mark##3##4\enverb@stop{##3{##1}{##2}}%
  }
\expandafter\enverb@ifnotend\expanded{{\expandafter\@gobble\string\\end}}
\newcommand\enverb@ifnotend@maybe[2]
  {\expandafter\enverb@ifnotend@perhaps\expandafter{\romannumeral`\^^@#2}{#1}}
\newcommand\enverb@ifnotend@setup@perhaps[1]
  {%
    \def\enverb@ifnotend@perhaps##1%
      {%
        \enverb@ifnotend@perhaps@\enverb@mark##1\enverb@mark\enverb@ifnotend@end
          \enverb@mark#1\enverb@mark\@thirdofthree
          \enverb@stop
      }%
    \def\enverb@ifnotend@perhaps@
        ##1\enverb@mark#1##2\enverb@mark##3##4\enverb@stop
      {##3{##2}}%
  }
\providecommand\@thirdofthree[3]{#3}
\newcommand\enverb@ifnotend@end[3]
  {%
    \iffalse{\fi}%
    \enverb@ensure@blank{#1}{\string\end}%
    \expanded
      {%
        \endgroup
        \enverbsetup
          {\unexpanded\expandafter{\enverb@collected@oarg}}%
        \noexpand\enverb@final
          {\unexpanded\expandafter{\enverb@collected@body}}%
      }%
      {#2}%
    \expandafter\end\expandafter{\@currenvir}%
  }
\long\def\enverb@final#1#2%
  {%
    \enverb@ifautoignore
      {\enverb@setup@ignore{\enverb@count{#2}+\enverb@moreignore}}%
      {\enverb@setup@ignore\enverb@ignore}%
    \edef\enverb@line##1\enverb@eol
      {%
        \noexpand\detokenize{##1}%
        \noexpand\unexpanded{\unexpanded\expandafter{\enverb@eol@content}}%
      }%
    \edef\enverb@collected@body{#1}%
    \expanded
      {\unexpanded{\enverb@append\enverb@gadd\@gobble}\expandafter}%
      \expandafter{\enverb@collected@body}%
  }
\providecommand\@firstofnine[9]{#1}
\newcommand\enverb@setup@ignore[1]
  {\expandafter\enverb@setup@ignore@\the\numexpr#1\relax;\enverb@line}
\def\enverb@setup@ignore@#1;#2%
  {%
    \ifnum#1>9
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
    {\expandafter\enverb@setup@ignore@\the\numexpr#1-8;{\@firstofnine{#2}}}%
    {%
      \let\enverb@bol@gobble\@empty % just so that renewcommand doesn't go nuts
      \expanded
        {%
          \unexpanded{\renewcommand\enverb@bol@gobble}\ifnum#1>\z@[#1]\fi
            {\unexpanded{#2}}%
          \unexpanded{\def\enverb@bol##1\enverb@eol}%
            {%
              \noexpand\unexpanded
                {\unexpanded\expandafter{\enverb@bol@content}}%
              \unexpanded{\expandafter\enverb@ifempty\expanded}{{##1}}%
                {\noexpand\enverb@line}%
                {\noexpand\enverb@bol@gobble}%
              ##1\unexpanded{\enverb@eol}%
            }%
        }%
    }%
  }
% the output routine if you'd use only an `enverb` environment, empty for you
\let\endenverb\@empty
\NewDocumentCommand\enverbExpandedOutput{O{} +m +m}
  {%
    \begingroup
      \everyeof{\noexpand}%
      #1\relax
      \expandafter
    \endgroup
    \scantokens\expanded
      {{%
        #2\enverb@othercr
        \enverb@collected@body
        #3\enverb@othercr
      }}%
  }
\NewDocumentCommand\enverbUnexpandedOutput{O{} +m +m}
  {%
    \begingroup
      \everyeof{\noexpand}%
      \newlinechar=\endlinechar
      #1\relax
      \expandafter
    \endgroup
    \scantokens\expanded
      {{%
        \unexpanded{#2}%
        \enverb@collected@body
        \unexpanded{#3}%
      }}%
  }
\makeatother


\NewDocumentEnvironment{figMe}{mm}
  {\enverb} % enverb will collet an additional o-arg for its own options
  {%
    \enverbUnexpandedOutput
      {\begin{figure}}
      {%
        \caption
          {%
            #2. See Listing~\ref{lst#1} for code.%
            \label{fig#1}%
          }%
        \end{figure}%
      }%
    \enverbExpandedOutput
      {%
        % we don't want to expand the begin part
        \unexpanded
          {%
            \begin{lstlisting}%
              [caption={#2. See Figure~\ref{fig#1}.},label={lst#1}]%
          }%
      }
      % verbatim output in lstlistings needs to see the \end as a string without
      % a trailing space
      {\string\end{lstlisting}}%
  }

\begin{document}
  \begin{figMe}{ex1}{Example drawing}
    \includegraphics{example-image-a}
  \end{figMe}
\end{document}

输出:

在此处输入图片描述

答案2

您还可以使用 Ulrich Diez 的DefineVerbatimToScantokens宏(可以在一些答案中找到,例如https://tex.stackexchange.com/a/626166/250119) 如下:

\documentclass{article}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{mwe}



%=== Code of \DefineVerbatimToScantokens ========================
% With older LaTeX-releases uncomment the following line:
%\usepackage{xparse}   
\NewDocumentCommand\DefineVerbatimToScantokens{mm}{%
  \begingroup
  \catcode`\^^I=12\relax
  \InnerDefineVerbatimToScantokens{#1}{#2}%
}%
\begingroup
\makeatletter
\def\InnerDefineVerbatimToScantokens#1#2{%
  \endgroup
  \NewDocumentCommand\InnerDefineVerbatimToScantokens{mm+v}{%
    \endgroup\ReplaceHashloop{##3}{##1}{##2}%
  }%
  \newcommand\ReplaceHashloop[3]{%
    \ifcat$\detokenize\expandafter{\Hashcheck##1#1}$%
    \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {%
      \NewDocumentCommand{##2}{##3}{%
         \begingroup\newlinechar=\endlinechar
         \scantokens{\endgroup##1#2}%
      }%
    }{%
      \expandafter\ReplaceHashloop\expandafter{\Hashreplace##1}{##2}{##3}%
    }%
  }%
  \@ifdefinable\Hashcheck{\long\def\Hashcheck##1#1{}}%
  \@ifdefinable\Hashreplace{\long\def\Hashreplace##1#1{##1####}}%
}%
\catcode`\%=12\relax
\catcode`\#=12\relax
\InnerDefineVerbatimToScantokens{#}{%}%
%=== End of code of \DefineVerbatimToScantokens =================




\DefineVerbatimToScantokens{\figMe}{m m +v}{
\begin{figure}
#3
\caption{#2. See Listing~\ref{lst#1} for code.}
\label{fig#1}
\end{figure}
\begin{lstlisting}[caption={#2. See Figure~\ref{fig#1}.},label={lst#1}]
#3
\end{lstlisting}
}

\begin{document}


\figMe{ex1}{Example drawing}{\includegraphics{example-image-a}}

\end{document}

尽管使用{...}它来界定逐字环境有点脆弱,但我认为注释必须是{}-brace-balanced。

相关内容