使用 etoolbox 自动生成 \xymatrix 的输入

使用 etoolbox 自动生成 \xymatrix 的输入

我想发出一个命令\exactseq,例如,

\exactseq{A,f,B,g,C}

对应于

\xymatrix{A \ar[r]^{f} & B \ar[r]^{g} & C}

并且这适用于任意长度的输入,而不仅仅是某些固定长度。准确地说,我想输入一个列表,当 n 为奇数时,将列表的第 n 个元素作为 xymatrix 中的条目,当 n 为偶数时,将其作为箭头。

编辑:正如 Werner 在下面询问的那样,我通常会有长度超过一个字符的条目和箭头,并且可能不是纯文本,例如\Omega,或f_{i},或\mathbb{Z}。上面给出的简单示例仅用于说明目的。

我一直试图使用etoolbox包的列表命令来实现这一点;作为初次尝试(甚至没有定义\exactseq),我尝试

\documentclass[11pt]{article}
\usepackage{amsmath,amssymb,amsthm,amsfonts}
\usepackage{etoolbox}
\usepackage[all]{xy}
\begin{document}

\newcounter{obfun}
\setcounter{obfun}{0}
\renewcommand*{\do}[1]{\ifnumodd{\value{obfun}}{\ar[r]^{#1} &}{#1}\stepcounter{obfun}}

\[\xymatrix{\docsvlist{A,f,B,g,C}}\]

\end{document}

但这会产生大量错误,主要与缺失或放错有关\cr(恐怕我不明白这是什么意思)。我尝试\expandafter在 之前放置\xymatrix,但这没有帮助。

我如何创建命令来进行书写正合序列更加自动化?当然,它不必使用etoolbox,或者xy就此而言。


编辑:egreg 的答案确实有效,但我对引入的所有这些新命令并不熟悉,expl3所以我真的不明白它是如何工作的,而且如果以后我想修改它,我也不知道该如何着手。因此,我想请求一个“低技术”解决方案(也许使用更常见或某种意义上“基本”的软件包),或者只是其他解决方案(如果您看到的话)。如果似乎没有其他解决方案,我会接受 egreg 的答案。

也许有办法使用这个TikZ代码这也适用于更一般的对象和箭头数组吗?

答案1

以下是一个使用的方法expl3

\documentclass{article}
\usepackage[all,cmtip]{xy}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\exactseq}{ O{+0pt} m }
 {
  \exactseq_main:nn { #1 } { #2 }
 }

\int_new:N \l__exactseq_place_int
\tl_new:N \l__exactseq_seq_tl
\cs_new_protected:Npn \exactseq_main:nn #1 #2
 {
  \tl_clear:N \l__exactseq_seq_tl
  \int_zero:N \l__exactseq_place_int
  \clist_map_inline:nn { #2 } { \__exactseq_process:n { ##1 } }
  \xymatrix@C#1 { \l__exactseq_seq_tl }
 }

\cs_new_protected:Npn \__exactseq_process:n #1
 {
  \int_if_even:nTF { \l__exactseq_place_int }
   { 
    \int_compare:nT { \l__exactseq_place_int > 0 }
     { \tl_put_right:Nn \l__exactseq_seq_tl { & } }
    \tl_put_right:Nn \l__exactseq_seq_tl { #1 }
   }
   {
    \tl_put_right:Nn \l__exactseq_seq_tl { \ar[r]^{#1} }
   }
  \int_incr:N \l__exactseq_place_int
 }
\ExplSyntaxOff

\begin{document}
$\exactseq{A,f,B,g,C}$

$\exactseq[+1em]{A,f,B,g,C,h,D}$
\end{document}

该命令\exactseq有一个可选参数,用于改变列间距(\xymatrix@C+1em{...}在示例中)。

我们处理列表,使用一个整数变量跟踪我们所处的位置,从 0 开始。我们将第一个对象添加到标记列表变量中,然后在偶数正位置(对应于除最左边的对象以外的对象)添加&该对象。在奇数位置我们添加\ar[r]^{f}(这里f表示箭头标签)。

最后,我们发布\xymatrix@C<optional argument>{<contents of the token list>}

在此处输入图片描述


版本带有etoolbox,详细说明您的示例。

\documentclass[11pt]{article}
\usepackage{amsmath,amssymb,amsthm,amsfonts}
\usepackage{etoolbox}
\usepackage[all]{xy}

\newcounter{obfun}
\newcommand{\exactseq}[2][+0pt]{%
  \setcounter{obfun}{0}%
  \def\storedsofar{}%
  \forcsvlist{\appendtoseq}{#2}%
  \xymatrix@C#1{\storedsofar}
}
\newcommand{\appendtoseq}[1]{%
  \ifnumodd{\value{obfun}}
    {\appto\storedsofar{\ar[r]^{#1} &}}
    {\appto\storedsofar{#1}}
  \stepcounter{obfun}%
}

\begin{document}

\[\exactseq{A,f,B,g,C}\]

\[\exactseq[+1em]{A,f,B,g,C}\]

\end{document}

此方法与使用 的方法非常相似expl3\storedsofar代替\l__exactseq_seq_tl,我们将项目一个接一个地添加。 该\forcsvlist命令是 的模拟\clist_map_inline:nn,因为它对参数进行循环,并使用 处理它们\appendtoseq。 在expl3上述版本中,列表中的每个项目都由执行 操作的辅助函数处理\appendtoseq

在 中执行所有操作的问题在于,\xymatrix这会在内部使用\halign(就像 一样tabular),因此使用是危险的(也是导致大量错误的原因)。因此,最好的策略是将所有材料收集到辅助存储位置(或)&中,然后将这个材料提供给。\l__exactseq_seq_tl\storedsofar\xymatrix

相关内容