解析 \foreach 的逗号分隔列表

解析 \foreach 的逗号分隔列表

\foreach我在逗号分隔的列表中使用 PGF,其中的项目可能包含空格;{...}如果每个项目包含空格,则可以将其括起来,这样就可以了。现在,当列表中只有一个项目时会发生什么?奇怪的是,空格在这里有(对我来说意想不到的)影响。

如果能给出解释,或者更好的是,提供一种避免这种输入脆弱性的方法,我将不胜感激。

这是正确解析的:

\fooList{items={{foo, foo}
    }
}

但不是这个:

\fooList{items={{foo, foo}
}}

或者这个:

\fooList{items={{foo, foo}}}
\documentclass{article}
\usepackage{pgffor}
\pgfkeys{
    /foo/.is family,
    /foo,
    items/.store in=\fooItems,
    items/.initial=\undefined
}
\newcommand{\fooList}[1]{
    \pgfkeys{/foo/.cd,#1}
    \begin{enumerate}
        \foreach [var=\content] in \fooItems{\item\content}
    \end{enumerate}
}
\parindent=0pt
\begin{document}
    Comma-separated list works fine for two items:
    \fooList{
        items={
            {foo, foo},
            {bar, bar}
        }
    }
    Single item is understood when written with trailing newlines
    \fooList{items={{foo, foo}
        }
    }
    It gets incorrectly split when written like this:
    \fooList{items={{foo, foo}
    }}
    And also when fully compacted:
    \fooList{items={{foo, foo}}}
\end{document}

PDF

答案1

恐怕你对这些错误无能为力...如果你想坚持下去,pgfkeys两种可能性没有可行的解决方案:

  • 总是在开括号前或闭括号后留一个空格(\fooItems{items={{one,two}} }\fooItems{items= {{one,two}}}-- 或两者皆有)
  • 在值周围添加一个额外的括号 ( \fooItems{items={{{one,two}}}})

编辑:不幸的是,这仍然不正确,因为pgfkeys,如果值周围没有空格,它会过多地删除一组括号(这可以通过两个建议来解决)然后它可能会删除一秒将值转发给.store in处理程序定义的底层命令时使用大括号(哎哟!)


但请注意,有几个可用的 key=value 解析器没有那个括号错误(并且也可能提供 csv 循环宏):

  • expkv
  • kvsetkeys
  • l3keys(该语言中的 LaTeX 内核的一部分expl3
  • \DeclareKeys/ \SetKeys(LaTeX 内核的一部分)

下面使用expkv(免责声明:我是包作者)和l3keys(语言expl3)演示了您的代码:

\documentclass{article}

\usepackage{expkv-def}
\ekvdefinekeys{foo}
  {
     store items = \fooItems
    ,initial items = \undefined
  }
\newcommand\fooList[1]
  {%
    \ekvset{foo}{#1}%
    \begin{enumerate}
      % no automatic detection of a variable storing the list, so we need to
      % manually expand it.
      \expandafter\ekvcsvloop\expandafter\item\expandafter{\fooItems}%
    \end{enumerate}
  }

\ExplSyntaxOn
\keys_define:nn { eudoxos / foo }
  {
     items .clist_set:N = \l__eudoxos_items_clist
    ,items .initial:n = \undefined
  }
\NewDocumentCommand \FooList { m }
  {
    \keys_set:nn { eudoxos / foo } {#1}
    \begin{enumerate}
      \clist_map_function:NN \l__eudoxos_items_clist \item
    \end{enumerate}
  }
\ExplSyntaxOff

\parindent=0pt
\begin{document}
\section{Using \texttt{expkv}}
    Comma-separated list works fine for two items:
    \fooList{
        items={
            {foo, foo},
            {bar, bar}
        }
    }
    Single item is understood when written with trailing newlines
    \fooList{items={{foo, foo}
        }
    }
    It gets incorrectly split when written like this:
    \fooList{items={{foo, foo}
    }}
    And also when fully compacted:
    \fooList{items={{foo, foo}}}
    \clearpage

\section{Using \texttt{l3keys}}
    Comma-separated list works fine for two items:
    \FooList{
        items={
            {foo, foo},
            {bar, bar}
        }
    }
    Single item is understood when written with trailing newlines
    \FooList{items={{foo, foo}
        }
    }
    It gets incorrectly split when written like this:
    \FooList{items={{foo, foo}
    }}
    And also when fully compacted:
    \FooList{items={{foo, foo}}}
\end{document}

相关内容