% Copyright 2011 by Florêncio Neves
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
\ProvidesPackage{tikz-cd}[2011/09/12 v0.1 Macros for creation of commutative diagrams with tikz.]
\RequirePackage{tikz}

\usepgfmodule{parser}
\usetikzlibrary{matrix}
\usepgflibrary{arrows}

\pgfkeys{%
  /commutative diagrams/picture style/.style={
    baseline=(current bounding box.base)},
  /commutative diagrams/matrix style/.style={
    matrix of math nodes,
    row sep=6ex,
    column sep=6ex,
    text height=1.5ex,
    text depth=0.25ex},
  /commutative diagrams/path style/.style={
    font=\scriptsize,
    auto,
    description/.style={
      anchor=center,fill=\tikzcd@bgcolor,inner sep=2pt}},
  /commutative diagrams/current arrows/.style={
    rightarrow/.style={cm cap-cm to},
    leftarrow/.style={cm to-cm cap},
    mapsto/.style={cm |-cm to},
    hookrightarrow/.style={cm right hook-cm to},
    hookleftarrow/.style={cm to-cm left hook},
    rightharpoonup/.style={cm cap-cm left to},
    rightharpoondown/.style={cm cap-cm right to},
    leftharpoonup/.style={cm right to-cm cap},
    leftharpoondown/.style={cm left to-cm cap},
    line width=0.09285ex,
    rightarrow}}

\def\tikzcd@bgcolor{white}

\makeatletter

\newcount\tikzcd@currcol
\newcount\tikzcd@currrow
\newcount\tikzcd@destrow
\newcount\tikzcd@destcol

%The arrow commands and its parser
\def\tikzcd@arrow{%
  \let\tikzcd@ar@edgeopt\empty%
  \let\tikzcd@ar@node\empty%
  \let\tikzcd@ar@nodeopt\empty%
  \tikzcd@destcol\tikzcd@currcol%
  \tikzcd@destrow\tikzcd@currrow%
  \global\edef\tikzcd@patharg{\tikzcd@patharg %
  (m-\the\tikzcd@currrow-\the\tikzcd@currcol) }%
  \futurelet\next\tikzcd@arrowb}
\def\tikzcd@arrowb{%
  \ifx[\next\expandafter\tikzcd@arrowi\else%
  \expandafter\tikzcd@arrowii\fi}
\def\tikzcd@arrowi[#1]{%
  \def\tikzcd@ar@edgeopt{[#1]}%
  \tikzcd@arrowii}
\def\tikzcd@arrowii#1{%
  \pgfparserparse{tikzmd@parser}#1*%
  \futurelet\next\tikzcd@arrowiii}
\def\tikzcd@arrowiii{%
  \ifx[\next\expandafter\tikzcd@arrowiv%
  \else\expandafter\tikzcd@arrowv\fi}
\def\tikzcd@arrowiv[#1]{%
  \def\tikzcd@ar@nodeopt{[#1]}%
  \futurelet\next\tikzcd@arrowv}
\def\tikzcd@arrowv{%
  \ifx\next\bgroup\expandafter\tikzcd@arrowvi%
  \else\tikzcd@arrowvii\fi}
\def\tikzcd@arrowvi#1{%
  \def\tikzcd@ar@node{ node\tikzcd@ar@nodeopt{$#1$}}%
  \tikzcd@arrowvii}
\def\tikzcd@arrowvii{
  \global\edef\tikzcd@patharg{\tikzcd@patharg %
  edge\tikzcd@ar@edgeopt \tikzcd@ar@node %
  (m-\the\tikzcd@destrow-\the\tikzcd@destcol)}%
}

\def\tikzcd@lar{%
  \tikzcd@destcol\tikzcd@currcol%
  \tikzcd@destrow\tikzcd@currrow%
  \advance\tikzcd@destcol by1\relax%
  \futurelet\next\tikzcd@xar}
\def\tikzcd@rar{%
  \tikzcd@destcol\tikzcd@currcol%
  \tikzcd@destrow\tikzcd@currrow%
  \advance\tikzcd@destcol by-1\relax%
  \futurelet\next\tikzcd@xar}
\def\tikzcd@dar{%
  \tikzcd@destcol\tikzcd@currcol%
  \tikzcd@destrow\tikzcd@currrow%
  \advance\tikzcd@destrow by1\relax%
  \futurelet\next\tikzcd@xar}
\def\tikzcd@uar{%
  \tikzcd@destcol\tikzcd@currcol%
  \tikzcd@destrow\tikzcd@currrow%
  \advance\tikzcd@destrow by-1\relax%
  \futurelet\next\tikzcd@xar}
\def\tikzcd@xar{%
  \let\tikzcd@ar@edgeopt\empty%
  \let\tikzcd@ar@node\empty%
  \let\tikzcd@ar@nodeopt\empty%
  \global\edef\tikzcd@patharg{\tikzcd@patharg %
  (m-\the\tikzcd@currrow-\the\tikzcd@currcol) }%
  \ifx[\next\expandafter\tikzcd@xari%
  \else\expandafter\tikzcd@xarii\fi}
\def\tikzcd@xari[#1]{%
  \def\tikzcd@ar@edgeopt{[#1]}%
  \futurelet\next\tikzcd@xarii}
\def\tikzcd@xarii{%
  \ifx\next\bgroup\expandafter\tikzcd@arrowvi%
  \else\expandafter\tikzcd@xariii\fi}
\def\tikzcd@xariii{%
  \ifx[\next\expandafter\tikzcd@arrowiv%
  \else\tikzcd@arrowvii\fi}

\pgfparserdef{tikzmd@parser}{initial}{the letter l}
{\advance\tikzcd@destcol by1\relax}
\pgfparserdef{tikzmd@parser}{initial}{the letter r}
{\advance\tikzcd@destcol by-1\relax}
\pgfparserdef{tikzmd@parser}{initial}{the letter d}
{\advance\tikzcd@destrow by1\relax}
\pgfparserdef{tikzmd@parser}{initial}{the letter u}
{\advance\tikzcd@destrow by-1\relax}
\pgfparserdef{tikzmd@parser}{initial}{the character *}
{\pgfparserswitch{final}}

%Diagram environment
\def\tikzcd{%
  \tikzpicture[/commutative diagrams/picture style]%
  \let\tikzcd@patharg\empty%
  \let\arrow\tikzcd@arrow%
  \let\ar\tikzcd@arrow%
  \let\lar\tikzcd@lar%
  \let\rar\tikzcd@rar%
  \let\dar\tikzcd@dar%
  \let\uar\tikzcd@uar%
  \matrix (m) [/commutative diagrams/matrix style,%
    execute at begin cell=%
    \tikzcd@currcol\pgfmatrixcurrentcolumn%
    \tikzcd@currrow\pgfmatrixcurrentrow]\bgroup%
}

\def\endtikzcd{%
  \\\egroup;%
  \path[/commutative diagrams/path style,%
    /commutative diagrams/current arrows]%
  \tikzcd@patharg ;%
  %\typeout{\tikzcd@patharg}
  \endtikzpicture%
}

%Computer modern arrow tips
\pgfarrowsdeclare{cm to}{cm to}
{
  \pgfarrowsleftextend{-5.833\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-5.333\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-4.2\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{-2.133\pgfutil@tempdima}{0.6\pgfutil@tempdima}}
  {\pgfpointorigin}
  \pgfpathcurveto
  {\pgfqpoint{-2.133\pgfutil@tempdima}{-0.6\pgfutil@tempdima}}
  {\pgfqpoint{-4.2\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-5.333\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm bold to}{cm bold to}
{
  \pgfarrowsleftextend{-4.055\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=0.667\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-5.333\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-4.2\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{-2.133\pgfutil@tempdima}{0.6\pgfutil@tempdima}}
  {\pgfpointorigin}
  \pgfpathcurveto
  {\pgfqpoint{-2.133\pgfutil@tempdima}{-0.6\pgfutil@tempdima}}
  {\pgfqpoint{-4.2\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-5.333\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm left to}{cm left to}
{
  \pgfarrowsleftextend{-5.833\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-5.333\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-4.2\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{-2.133\pgfutil@tempdima}{0.6\pgfutil@tempdima}}
  {\pgfpointorigin}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm right to}{cm right to}
{
  \pgfarrowsleftextend{-5.833\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfpointorigin}
  \pgfpathcurveto
  {\pgfqpoint{-2.133\pgfutil@tempdima}{-0.6\pgfutil@tempdima}}
  {\pgfqpoint{-4.2\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-5.333\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm |}{cm |}
{
  \pgfarrowsleftextend{-0.5\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{-4\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{0pt}{4\pgflinewidth}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm left hook}{cm left hook}
{
  \pgfarrowsleftextend{-0.5\pgflinewidth}
  \pgfarrowsrightextend{3.5\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{4.667\pgflinewidth}}
  \pgfpathcurveto
    {\pgfqpoint{4\pgflinewidth}{4.667\pgflinewidth}}
    {\pgfqpoint{4\pgflinewidth}{0pt}}
    {\pgfpointorigin}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm right hook}{cm right hook}
{
  \pgfarrowsleftextend{-0.5\pgflinewidth}
  \pgfarrowsrightextend{3.5\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{-4.667\pgflinewidth}}
  \pgfpathcurveto
    {\pgfqpoint{4\pgflinewidth}{-4.667\pgflinewidth}}
    {\pgfqpoint{4\pgflinewidth}{0pt}}
    {\pgfpointorigin}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm o}{cm o}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}
  \pgfarrowsrightextend{7.167\pgflinewidth}
}
{
  \pgfpathcircle{\pgfqpoint{3.333\pgflinewidth}{0pt}}{3.333\pgflinewidth}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm *}{cm *}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}
  \pgfarrowsrightextend{7.167\pgflinewidth}
}
{
  \pgfpathcircle{\pgfqpoint{3.333\pgflinewidth}{0pt}}{3.333\pgflinewidth}
  \pgfusepathqfillstroke
}

\pgfarrowsdeclare{cm cap}{cm cap}
{
  \pgfarrowsleftextend{+0pt}
  \pgfarrowsrightextend{+\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfpointorigin}
  \pgfpathlineto{\pgfqpoint{0.5\pgflinewidth}{0pt}}
  \pgfusepathqstroke
}

\pgfarrowsdeclarereversed{cm to reversed}{cm to reversed}{cm to}{cm to}
\pgfarrowsdeclarereversed{cm left to reversed}{cm left to reversed}{cm left to}{cm left to}
\pgfarrowsdeclarereversed{cm right to reversed}{cm right to reversed}{cm right to}{cm right to}

\pgfarrowsdeclaredouble{cm double to}{cm double to}{cm to}{cm to}
\pgfarrowsdeclaredouble{cm double to reversed}{cm double to reversed}{cm to reversed}{cm to reversed}

\makeatother
\endinput