1

I'm making a special tick command. Without *, the tick shows on the left side. With *, it should appear on the right side. The * (or lack of) should set a few macros to change the behaviour of the tick. What is happening though, is that all ticks are appearing on the right side. (If the most recent ytick call does not have a *, they will appear on the left. I know this problem has to do with expansion. I think what I need to do is completely expand each ytick call.

\documentclass{article}

\RequirePackage{tikz} \usetikzlibrary{calc} \RequirePackage{pgfplots} \RequirePackage{pgffor} \pgfplotsset{compat=newest}

\newcommand{\ticksign}{-} \newcommand{\tickside}{0} \newcommand{\tickanchor}{east} \newcommand{\ticklength}{2pt}

\NewDocumentCommand{\ytick}{ s m O{#2} }{% \IfBooleanTF{#1}{ \gdef\ticksign{} \gdef\tickside{1} \gdef\tickanchor{west} }{ \gdef\ticksign{-} \gdef\tickside{0} \gdef\tickanchor{east} } \coordinate (tick) at ({rel axis cs: \tickside , 0} |- {axis cs: 0, #2}) ; \draw[gray] (tick) -- + (\ticksign \ticklength , 0pt); \node[anchor=\tickanchor ] at ($ (tick) + (\ticksign \ticklength , 0pt) $) {#3} ; }

\begin{document}

\begin{tikzpicture} \begin{axis}[hide axis,clip=false] \addplot table[header=false,x expr=\coordindex, y index=0] { 1 2 3 2 1 }; \ytick{1}[one] % should be on left side \ytick{3}[three] % should be on left side \ytick*{2}[two] \end{axis} \end{tikzpicture} \end{document}

enter image description here

2 Answers2

2

I'd suggest to use an auxiliary macro instead which gets the parameters forwarded instead of storing them in a macro:

\documentclass{article}

\RequirePackage{tikz} \usetikzlibrary{calc} \RequirePackage{pgfplots} \RequirePackage{pgffor} \pgfplotsset{compat=newest}

\newcommand{\ticklength}{2pt}

\makeatletter \newcommand\ytick@[5] {% \coordinate (tick) at ({rel axis cs: #2 , 0} |- {axis cs: 0 , #4}); \draw[gray] (tick) -- +(#1\ticklength , 0pt); \node[anchor=#3] at ($ (tick) + (#1\ticklength , 0pt) $) {#5}; } \NewDocumentCommand{\ytick}{ s m O{#2} } {% \IfBooleanTF{#1} {\ytick@{}{1}{west}} {\ytick@{-}{0}{east}} {#2}{#3}% } \makeatother

\begin{document}

\begin{tikzpicture} \begin{axis}[hide axis,clip=false] \addplot table[header=false,x expr=\coordindex, y index=0] { 1 2 3 2 1 }; \ytick{1}[one] % should be on left side \ytick{3}[three] % should be on left side \ytick*{2}[two] \end{axis} \end{tikzpicture} \end{document}

enter image description here

Skillmon
  • 60,462
2

Imho Skillmon's answer provides the best and most efficient solution to the problem. My answer is intended to be just an addendum to Skillmon's answer for illustrating tricks with macro expansion although these tricks are not really needed here(, which is proven by Skillmon's answer).

For the sake of having fun learning about expansion you can nest things like \expandafter\Exchange\expandafter{...}{...}:

\documentclass{article}

\RequirePackage{tikz} \usetikzlibrary{calc} \RequirePackage{pgfplots} \RequirePackage{pgffor} \pgfplotsset{compat=newest}

\newcommand\Exchange[2]{#2#1} \newcommand\PassFirstToSecond[2]{#2{#1}}

\newcommand{\ticksign}{-} \newcommand{\tickside}{0} \newcommand{\tickanchor}{east} \newcommand{\ticklength}{2pt}

\NewDocumentCommand{\ytick}{ s m O{#2} }{% \IfBooleanTF{#1}{ \gdef\ticksign{} \gdef\tickside{1} \gdef\tickanchor{west} }{ \gdef\ticksign{-} \gdef\tickside{0} \gdef\tickanchor{east} } \expandafter\expandafter\expandafter\PassFirstToSecond \expandafter\expandafter\expandafter{% \expandafter\Exchange\expandafter{% \tickside}{rel axis cs: } , 0}{\coordinate (tick) at (} |- {axis cs: 0, #2}) ; \expandafter\Exchange\expandafter{\ticklength}% {\expandafter\Exchange\expandafter{\ticksign}{\draw[gray] (tick) -- + (}} , 0pt); \expandafter\Exchange\expandafter{\ticklength}% {\expandafter\Exchange\expandafter{\ticksign}% {\expandafter\Exchange\expandafter{\tickanchor}{\node[anchor=} ] at ($ (tick) + (} } , 0pt) $) {#3} ; }

\begin{document}

\begin{tikzpicture} \begin{axis}[hide axis,clip=false] \addplot table[header=false,x expr=\coordindex, y index=0] { 1 2 3 2 1 }; \ytick{1}[one] % should be on left side \ytick{3}[three] % should be on left side \ytick*{2}[two] \end{axis} \end{tikzpicture} \end{document}

enter image description here

In case of using a TeX-engine where \expanded is available you can combine \expanded with \noexpand:

\documentclass{article}

\RequirePackage{tikz} \usetikzlibrary{calc} \RequirePackage{pgfplots} \RequirePackage{pgffor} \pgfplotsset{compat=newest}

\newcommand{\ticksign}{-} \newcommand{\tickside}{0} \newcommand{\tickanchor}{east} \newcommand{\ticklength}{2pt}

\NewDocumentCommand{\ytick}{ s m O{#2} }{% \IfBooleanTF{#1}{ \gdef\ticksign{} \gdef\tickside{1} \gdef\tickanchor{west} }{ \gdef\ticksign{-} \gdef\tickside{0} \gdef\tickanchor{east} } \expanded{% \noexpand\coordinate (tick) at ({rel axis cs: \tickside , 0} |- {axis cs: 0, #2}) ; \noexpand\draw[gray] (tick) -- + (\ticksign \ticklength , 0pt); \noexpand\node[anchor=\tickanchor ] at ($ (tick) + (\ticksign \ticklength , 0pt) $) {#3} ; }% }

\begin{document}

\begin{tikzpicture} \begin{axis}[hide axis,clip=false] \addplot table[header=false,x expr=\coordindex, y index=0] { 1 2 3 2 1 }; \ytick{1}[one] % should be on left side \ytick{3}[three] % should be on left side \ytick*{2}[two] \end{axis} \end{tikzpicture} \end{document}

enter image description here

Ulrich Diez
  • 28,770