我正在尝试编写一个宏\mappingto
,基本上,在绘制箭头后调用,应该在下面添加另一个宏,阐明映射到哪些元素。
例如,在简单的情况下,我想
\xymatrix{%
A \ar[rr]^{f}
\mappingto{x}{f(x)}
&& B}
扩大到
\xymatrix{%
A \ar[rr]^{f}
\ar@{|->}[]!/:a(-90) 3ex/*{x};[rr]!/:a(-90) 3ex/*{f(x)}
&& B}
我的主要问题是如何获取前一个箭头的源和目标?我天真地认为
\newcommand{\mappingto}[2]{%
\POS c="target"
\POS p="source"
\ar@{|->}"source"!/:a(-90) 3ex/*{#1};"target"!/:a(-90) 3ex/*{#2}
}
可以解决问题,但显然不行:两个项目都排版在同一个位置,即 A 下面。我尝试了c
和的所有切换p
,包括c=..., c=...
和p=..., p=...,
以防<coord>=<"Id">
更新c
和p
,但都没有改变任何东西。
我现在非常确信,即使我在参考手册中找不到确认,箭头和路径会xy
在绘制之前保存状态,然后恢复它。
所以我的问题是:有没有办法恢复最后绘制的箭头的目标?(因为 c 始终是源,所以恢复源不是问题)
我也考虑过以下解决方案:
- 再次将方向作为参数传递:它可以工作,但我不太喜欢它,在逻辑编码的想法中
- 将方向作为参数传递并使
\mappingto
宏绘制两个宏:我希望能够将\mappingto
具有任何特定形状、标签、位置的宏用于“常规”箭头,因此它需要更多参数 - 将前一个箭头的代码作为参数传递:仅仅调用它并在之前或之后保存 c 和 p 是行不通的,因为我已经可以做到这一点。我实际上可以用宏的代码做一些事情:提取方向:从
"\ar[rr]^{f}"
,获取"rr"
。我几乎可以使用来做到这一点xstring
,但似乎xy-pic
无法在里面扩展宏[ ]
,所以我回到第一步。
你们有找到解决办法吗?(最好是以一种逻辑编程的方式,也就是说,如果我能有一种方法不强迫我将方向或前一个箭头传递给宏,那就更好了^^)
对于那些想要进行实验的人来说,最简单的例子是:
\documentclass{article}
\usepackage[all]{xy}
\usepackage{xstring}
% Clean code version
\newcommand{\mappingtoI}[2]{%
\POS c="target"
\POS p="source"
\ar@{|->}"source"!/:a(-90) 3ex/*{#1};"target"!/:a(-90) 3ex/*{#2}
}
% Dirty version
\newcommand{\mappingtoII}[3]{% % First argument is now the first arrow
\StrBetween{#1}{[}{]}[\direction]
% Now \direction expands to the direction of the arrow
#1% % We draw the first arrow...
\ar@{|->}[]!/:a(-90) 3ex/*{#2};[\direction]!/:a(-90) 3ex/*{#3}
% ... and then we try to draw the second one.
}
\begin{document}
% % Uncomment this part to see the expected output.
% Expected output :
% \xymatrix{%
% A \ar[rr]^{f}
% \ar@{|->}[]!/:a(-90) 3ex/*{x};[rr]!/:a(-90) 3ex/*{f(x)}
% && B
% }
What the basic macro gives :
\xymatrix{%
A \ar[rr]^{f}
\mappingtoI{x}{f(x)}
&& B
}
What the "string processing" macro gives :
% Won't compile, comment this matrix out if you are trying to get an output!
\xymatrix{%
A \mappingtoII{\ar[rr]^{f}}
{x}{f(x)}
&& B
}
\end{document}
编辑 :
看来我说 xy-pic 无法扩展方向定义内的宏是错误的。现在我认为 xy-pic 会尝试评估\ar
宏参数内部的值。:/
实际上,以下宏
\newcommand{\mappingtoTest}[3]{%
\StrBetween[1]{#1}{[}{]}[\direction]
\direction
}
它应该只打印输入的宏的方向,返回错误消息
!Argument of \next has an extra }.
有趣的是,以下宏不会返回错误:
\newcommand{\mappingtoTest}[3]{}
\protect
之前添加\ar
并没有帮助,我尝试使用xstring
选项,最后得到这个宏,这是目前最有可能的工作,但仍然没有:
\newcommand{\mappingtoTest}[3]{% % First argument is now the first arrow
\noexpandarg
\StrBetween{#1}{[}{]}[\direction]
% Now \direction expands to the direction of the arrow
\fullexpandarg
#1% % We draw the first arrow...
\ar@{|->}[]!/:a(-90) 3ex/*{#2};[\direction]!/:a(-90) 3ex/*{#3}
% ... and then we try to draw the second one.
}
然而,这noexpandarg
有所不同,因为
\newcommand{\mappingtoTest}[3]{% % First argument is now the first arrow
\noexpandarg
\StrBetween{#1}{[}{]}[\direction]}
确实可以编译,而没有的相同方法则noexpandarg
不能。\direction
但是,如果我尝试打印,我会再次收到一个模糊的 xy 错误。:/
答案1
看起来像是一个扩展问题。
\documentclass{article}
\usepackage[all]{xy}
\usepackage{xstring}
% Clean code version
\newcommand{\mappingtoI}[2]{%
\POS c="target"
\POS p="source"
\ar@{|->}"source"!/:a(-90) 3ex/*{#1};"target"!/:a(-90) 3ex/*{#2}
}
% Dirty version
\newcommand{\mappingtoII}[3]{% % First argument is now the first arrow
{\noexpandarg\StrBetween{#1}{[}{]}[\direction]
% Now \direction expands to the direction of the arrow
#1% We draw the first arrow...
\edef\temp{\noexpand\ar@{|->}[]!/:a(-90) 3ex/*{#2};[\direction]!/:a(-90) 3ex/*{#3}}\temp
% ... and then we try to draw the second one.
}
}
\begin{document}
% Expected output :
\xymatrix{%
A \ar[rr]^{f}
\ar@{|->}[]!/:a(-90) 3ex/*{x};[rr]!/:a(-90) 3ex/*{f(x)}
&& B
}
What the basic macro gives :
\xymatrix{%
A \ar[rr]^{f}
\mappingtoI{x}{f(x)}
&& B
}
What the "string processing" macro gives :
\xymatrix{%
A \mappingtoII{\ar[rr]^{f}}{x}{f(x)}
&& B
}
\end{document}