列表中的行首字符

列表中的行首字符

在 中lstlisting我可以使用\^^M来表示行的结束morecomment。是否有类似的字符来查找行的开头?

答案1

下面定义了一个宏\collectverbenv,您可以在环境定义的开始部分使用它。此宏将开始逐字抓取内容,直到\end达到(具有相同的环境名称)。该宏支持单个可选参数(必须紧跟在后面,\begin{<env>}没有空格!

该宏支持指定应在每行开头和结尾添加的内容。对于结尾,以下示例使用\char_generate:nn \endlinechar { 12 }(这是正确重建带有换行符的列表所必需的),对于开头,它使用AA。您可以指定任何需要的内容来获取行首。

这在自定义环境中使用mylstlisting。为此,可选参数将存储在标记列表中,然后作为可选参数转发到嵌套lstlisting环境。然后使用一点 TeX magic ( \scantokens) 来lstlisting收集主体本身及其自己的 catcode 和内容。瞧,您可以检测到一行的开头(因为您可以在那里注入任意标记)。

看这个例子(正如已经说过的,只AA在每行的开头注入):

\documentclass[]{article}

\usepackage{listings}

\ExplSyntaxOn
\cs_new_eq:NN \__collectverbenv_processor:n \q_nil
\keys_define:nn { collectverbenv }
  {
     process    .code:n     = \cs_set:Npn \__collectverbenv_processor:n ##1 {#1}
    ,bol        .tl_set:N   = \l__collectverbenv_bol_tl
    ,eol        .tl_set:N   = \l__collectverbenv_eol_tl
    ,optional   .tl_set:N   = \l__collectverbenv_opt_arg_tl
    ,ignore     .int_set:N  = \l__collectverbenv_ignore_int
    ,no-process .code:n     = \cs_set_eq:NN \__collectverbenv_processor:n \q_nil
    ,no-process .value_forbidden:n = true
  }
\NewDocumentCommand \collectverbenvstore { +m }
  {
    \tl_put_right:Nx \l__collectverbenv_body_tl
      {
        \exp_not:o \l__collectverbenv_bol_tl
        \exp_not:n {#1}
        \exp_not:o \l__collectverbenv_eol_tl
      }
  }
\NewDocumentCommand \collectverbenvretrieve { m }
  {
    \cs_set_eq:NN #1 \l__collectverbenv_body_tl
  }
\NewDocumentCommand \collectverbenv { +m }
  {
    \keys_set:nn { collectverbenv } {#1}
    \tl_clear:N \l__collectverbenv_body_tl
    \group_begin:
    \__collectverbenv_set_catcodes:
    \tl_if_empty:NTF \l__collectverbenv_opt_arg_tl
      \__collectverbenv_collect:w
      \__collectverbenv_opt_arg:w
  }
\cs_new_protected:Npn \__collectverbenv_set_catcodes:
  {
    \cs_set_eq:NN \do \char_set_catcode_other:N
    \dospecials
    \char_set_catcode_active:N \^^M
  }
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \__collectverbenv_collect:w #1 ^^M
  {
    \__collectverbenv_collect_check_end:n {#1}
    \int_compare:nNnTF \l__collectverbenv_ignore_int > \c_zero_int
      {
        \int_decr:N \l__collectverbenv_ignore_int
      }
      {
        \cs_if_eq:NNTF \__collectverbenv_processor:n \q_nil
          {
            \tl_put_right:Nx \l__collectverbenv_body_tl
              {
                \exp_not:o \l__collectverbenv_bol_tl
                #1
                \exp_not:o \l__collectverbenv_eol_tl
              }
          }
          { \__collectverbenv_processor:n {#1} }
      }
    \__collectverbenv_collect:w
  }
\group_end:
\exp_args:NNo
\cs_new_protected:Npn \__collectverbenv_opt_arg:w
  {
    \use_i_ii:nnn \peek_charcode:NTF []
      \__collectverbenv_opt_arg_auxi:w
      {
        \group_end:
        \exp_after:wN \cs_set:Npn \l__collectverbenv_opt_arg_tl {}
        \group_begin:
        \__collectverbenv_set_catcodes:
        \__collectverbenv_collect:w
      }
  }
\cs_new_protected:Npn \__collectverbenv_opt_arg_auxi:w
  {
    \group_end:
    \__collectverbenv_opt_arg_auxii:w
  }
\NewDocumentCommand \__collectverbenv_opt_arg_auxii:w { O{} }
  {
    \exp_after:wN \tl_set:Nn \l__collectverbenv_opt_arg_tl {#1}
    \group_begin:
    \__collectverbenv_set_catcodes:
    \__collectverbenv_collect:w
  }
\cs_new_protected:Npn \__collectverbenv_collect_check_end:n #1
  {
    \str_set:Nn \l_tmpa_str {#1}
    \str_remove_all:Nn \l_tmpa_str { ~ }
    \str_if_eq:eeT
      \l_tmpa_str
      { \token_to_str:N \end { \use:c { @currenvir } } }
      \__collectverbenv_collect_end:w
  }
\cs_new:Npn \__collectverbenv_collect_end:w #1 \__collectverbenv_collect:w
  {
    \exp_args:NNNo
    \group_end:
    \tl_set:Nn \l__collectverbenv_body_tl \l__collectverbenv_body_tl
    \exp_args:Ne \end { \use:c { @currenvir } }
  }
\tl_new:N \l__collectverbenv_body_tl


\tl_new:N \l_mylstlisting_opt_tl
\NewDocumentEnvironment { mylstlisting } { }
  {
    \collectverbenv
      {
         bol = AA % <- use whatever you need as a marker for a start of the line
        ,eol = \char_generate:nn \endlinechar { 12 } % <- needed to rebuild the list
        ,ignore = 1 % <- first line (the one containing \begin) is ignored
        ,optional = \l_mylstlisting_opt_tl % <- collect an optional argument
      }
  }
  {
    \group_begin:
    \collectverbenvretrieve \l_tmpa_tl
    \everyeof={\noexpand}
    \exp_args:Nx \scantokens
      {
        \token_to_str:N \begin{lstlisting}
          [{ \exp_not:o \l_mylstlisting_opt_tl }]
        \char_generate:nn { \endlinechar } { 12 }
        \l_tmpa_tl
        \char_generate:nn { \endlinechar } { 12 }
        \token_to_str:N \end{lstlisting}
      }
    \group_end:
  }
\ExplSyntaxOff


\begin{document}
\begin{mylstlisting}
  \foo
  \bar
\end{mylstlisting}
\end{document}

在此处输入图片描述

相关内容