pgfplots 和扩展-立即扩展宏吗?

pgfplots 和扩展-立即扩展宏吗?

我正在制作一个特殊的 tick 命令。如果没有*,则 tick 显示在左侧。有了*,它应该出现在右侧。*应该设置一些宏来更改 tick 的行为。但是,发生的事情是,所有 tick 都出现在右侧。(如果最近的ytick调用没有*,它们将出现在左侧。我知道这个问题与扩展有关。我想我需要做的是完全扩展每个 ytick 调用。

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

在此处输入图片描述

答案1

我建议使用辅助宏来获取转发的参数而不是将它们存储在宏中:

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

在此处输入图片描述

答案2

恕我直言Skillmon 的回答为该问题提供了最佳、最有效的解决方案。我的回答只是对 Skillmon 的回答的一个补充,用于说明宏扩展的技巧,尽管这些技巧在这里并不是真正需要的(Skillmon 的回答已证明这一点)。

为了在学习扩展时获得乐趣,你可以嵌套如下内容\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}

在此处输入图片描述

如果使用 TeX 引擎,\expanded您可以结合\expanded使用\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}

在此处输入图片描述

相关内容