Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to write a macro \mappingto which, basically, called after an arrow has been drawn, should add another one below clarifying what elements are mapped to.

e.g. in an easy situation, I'd like

\xymatrix{%
    A \ar[rr]^{f}
      \mappingto{x}{f(x)}
    && B}

to expand to

\xymatrix{%
    A \ar[rr]^{f}
      \ar@{|->}[]!/:a(-90) 3ex/*{x};[rr]!/:a(-90) 3ex/*{f(x)}
    && B}

The main problem I have is how to get the source and target of the previous arrow? I naively thought that

\newcommand{\mappingto}[2]{%
    \POS c="target"
    \POS p="source"
    \ar@{|->}"source"!/:a(-90) 3ex/*{#1};"target"!/:a(-90) 3ex/*{#2}
}

would do the trick, but it obviously doesn't : both items get typeset at the same place, namely below A. I tried all switching of c and p, including c=..., c=... and p=..., p=..., in case the <coord>=<"Id"> does update c and p, but none did change anything.

I'm pretty convinced now, even though I couldn't find confirmation in the reference manual, that arrows and paths save the xy state before being drawn, and restore it afterwards.

So here is my question : is there any way to recover the target of the last drawn arrow? (Since c is always the source, recovering the source isn't a problem)

I also have considered the following solutions :

  • pass the direction again as a parameter : it would work, but I don't really like it, in the idea of logical coding
  • pass the direction as a parameter and make the \mappingto macro draw both macros : I'd like to be able to use the \mappingto macro with any specific shape, label, position for the "regular" arrow, so it would need a lot of more parameters
  • pass the code of the previous arrow as a parameter : Just calling it and saving c and p before or after wouldn't do the trick, because I can already do that. I could actually do something with the code of the macro : extract the direction : from "\ar[rr]^{f}", get "rr". I can almost do it using xstring, but it seems xy-pic can't expand macros inside [ ], so I'm back to step one.

Do you guys see any solution? (preferably in a logical programming mood, aka if I could have a way not forcing me to pass direction or previous arrow to the macro, it would be even nicer ^^)

Minimal example for those who want to experiment:

\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}

Edit :

It seems I was wrong stating that xy-pic couldn't expand the macros inside direction definition. Now I think xy-pic tries to evaluate \ar inside macros arguments. :/

Actually, the following macro

\newcommand{\mappingtoTest}[3]{%
    \StrBetween[1]{#1}{[}{]}[\direction]
    \direction
}

which should just print the direction of the entered macro, returns an error message

!Argument of \next has an extra }.

Funny enough, the following macro doesn't return an error :

\newcommand{\mappingtoTest}[3]{}

Adding \protect before \ar doesn't help, and I tried to play with xstring options, finally getting to this macro, which is the most likely to work at the moment, but still doesn't :

\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.
}

The noexpandarg makes a difference though, because

\newcommand{\mappingtoTest}[3]{% % First argument is now the first arrow
    \noexpandarg
     \StrBetween{#1}{[}{]}[\direction]}

does compile, while the same without noexpandarg didn't. If I try to print \direction, I get an obscure xy error again, though. :/

share|improve this question
    
Welcome to TeX.SE. While code snippets are useful for explaining things, it is always best to compose a MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it. –  Peter Grill Nov 22 '11 at 23:25
    
@PeterGrill : Done, and I also added the code of the "dirty" macro. –  T. Verron Nov 22 '11 at 23:59
2  
Please make sure that your minimal example compiles, otherwise it will be difficult for anybody to find solutions. This is very important - see How to make a “minimum example”. For example, as-is, LaTeX does not "enjoy" your macros \mappingto1 and \mappingto2 since they contain numerals. Moreover, use (say) the article document class rather than minimal, since the latter declares very little in terms of usage for a document to play with. –  Werner Nov 23 '11 at 3:40
    
@Werner : Done, I just realized you don't necessarily recieve a notification when the main post is edited. –  T. Verron Nov 25 '11 at 7:53
1  
@Werner it should be \ar[r]and not \ar[rr] –  Matsaya Nov 25 '11 at 13:55
show 2 more comments

1 Answer 1

up vote 3 down vote accepted

Looks like an expansion problem.

\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}

enter image description here

share|improve this answer
    
Thanks, it indeeds does the trick! I'll mark this as accepted, even though I still hope someone someday will come with a macro satisfying the first, more natural syntax. Thanks again! –  T. Verron Sep 28 '12 at 8:02
    
@T.Verron My pleasure. –  percusse Sep 28 '12 at 8:03
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.