如何解决 \usetikzlibrary{babel} 的问题?

如何解决 \usetikzlibrary{babel} 的问题?

我目前正在更新 tkz-euclide 和新文档,但我刚刚遇到了以下问题。如果我使用 pdflatex 或 lualatex 和 pgf 2.1(pgf 2.1 中不存在 babel 库)编译此代码,则代码可以正常编译,但使用 3.0 pgf 时,我必须对调用进行注释\usetikzlibrary{babel}(pgf 文档给出所以我建议总是通过 \usetikzlibrary{babel} 来加载这个库)。我想知道错误发生在哪里。特别是我想解决这个问题。

\usetikzlibrary{babel}收到错误 Latex 错误:./untitled 2.tex:46 未定义的控制序列。l.1 \tkz@line@start

babel 中的 Bug,tikzlibrary{babel}我的代码中的 Bug。我想保留它 \usetikzlibrary{babel},但要避免错误。

%!TEX TS-program = pdflatex
\documentclass[a4paper]{article}
\usepackage[french]{babel}
\usepackage{tikz} 
\usetikzlibrary{calc}
%\usetikzlibrary{babel}

\makeatletter
\pgfkeys{%
    tkzdrawline/.cd,
    start/.code         =  {\gdef\tkz@line@start{#1}},%
    end/.code           =  {\gdef\tkz@line@end{#1}},%
    start style/.code   =  {\tikzset{tkzstartstyle/.style={#1}}},%
    end style/.code     =  {\tikzset{tkzendstyle/.style={#1}}},%
   /tkzdrawline/.unknown/.code ={\let\searchname=\pgfkeyscurrentname\pgfkeysalso{%
                         \searchname/.try=#1,/tikz/\searchname/.retry=#1}}} 
%<--------------------------------------------------------------–>
%                              Draw line
%<--------------------------------------------------------------–>
\pgfkeys{tkzdrawline/.cd,
start/.code       =  {\def\tkz@line@start{#1}},%
end/.code         =  {\def\tkz@line@end{#1}},
start style/.code =  {\tikzset{tkzstartstyle/.style={#1}}},
end style/.code   =  {\tikzset{tkzendstyle/.style={#1}}},  
/tkzdrawline/.unknown/.code   = {\let\searchname=\pgfkeyscurrentname
                                 \pgfkeysalso{\searchname/.try=#1,
                                /tikz/\searchname/.retry=#1}}}%       
 %<--------------------------------------------------------------–>
 \def\tkzDrawLine{\pgfutil@ifnextchar[{\tkz@DrawLine}{%
                                  \tkz@DrawLine[]}}% 
 \def\tkz@DrawLine[#1](#2,#3){%
 \begingroup
  \pgfkeys{tkzdrawline/.cd,start = {}, end = {}, start style={}, end style={},}
  \pgfqkeys{/tkzdrawline}{#1}
  \draw[ /tkzdrawline/.cd,#1] (#2) to%
    node [at start,left,/tkzdrawline/.cd,tkzstartstyle] {\tkz@line@start}%
    node [at end,right,/tkzdrawline/.cd,tkzendstyle] {\tkz@line@end} (#3);
 \endgroup
 }% 
 \makeatother

 \begin{document}
   \begin{tikzpicture}
     \node (A) at (0,1) {}; 
     \node (B) at (5,2) {}; 
     \tkzDrawLine[end = {$\alpha$}](A,B)    
  \end{tikzpicture}

\end{document}

答案1

TikZbabel库调用两个键handle active characters in codehandle active characters in nodes。后者控制如何解析节点内容。关键代码是:

\def\tikz@collect@arg#1{%
  \iftikz@handle@active@nodes%
    \iftikz@collect@pic%
      \expandafter\def\expandafter\tikz@collected@onpath\expandafter{\tikz@collected@onpath{#1}}%
    \else%
      \expandafter\def\expandafter\tikz@collected@onpath\expandafter{\tikz@collected@onpath{\scantokens{#1}}}%
    \fi%
  \else%
    \expandafter\def\expandafter\tikz@collected@onpath\expandafter{\tikz@collected@onpath{#1}}%
  \fi%
  \tikz@collect@cont%
}

你发现了吗?它位于\scantokens内部\else分支中。这意味着节点的内容将被重新扫描,因此\makeatletter不再适用。因此,当\tkz@line@start调用时,将重新扫描标记,这意味着它是\tkz @ l i n e @ s t a r t(使用空格分隔标记)。

如何克服这个问题取决于代码中这个问题的严重程度。如果这是一个典型的例子,你可以使用\csname tkz@line@start\endcsname。另一个解决方案,在我看来更优雅一点,是使用 key node contents。这没有似乎受到了影响\scantokens(我猜是因为node contents在样式中比在纯文本中更可能使用)。(有点奇怪的是,node当我这样做时,我似乎仍然需要在第二个括号后使用空括号。)

%!TEX TS-program = pdflatex
\documentclass[a4paper]{article}
%\url{http://tex.stackexchange.com/q/298177/86}
\usepackage[french]{babel}
\usepackage{tikz} 
\usetikzlibrary{calc}
\usetikzlibrary{babel}

\makeatletter
\pgfkeys{%
    tkzdrawline/.cd,
    start/.code         =  {\gdef\tkz@line@start{#1}},%
    end/.code           =  {\gdef\tkz@line@end{#1}},%
    start style/.code   =  {\tikzset{tkzstartstyle/.style={#1}}},%
    end style/.code     =  {\tikzset{tkzendstyle/.style={#1}}},%
   /tkzdrawline/.unknown/.code ={\let\searchname=\pgfkeyscurrentname\pgfkeysalso{%
                         \searchname/.try=#1,/tikz/\searchname/.retry=#1}}} 
%<--------------------------------------------------------------–>
%                              Draw line
%<--------------------------------------------------------------–>
\pgfkeys{tkzdrawline/.cd,
start/.code       =  {\def\tkz@line@start{#1}},%
end/.code         =  {\def\tkz@line@end{#1}},
start style/.code =  {\tikzset{tkzstartstyle/.style={#1}}},
end style/.code   =  {\tikzset{tkzendstyle/.style={#1}}},  
/tkzdrawline/.unknown/.code   = {\let\searchname=\pgfkeyscurrentname
                                 \pgfkeysalso{\searchname/.try=#1,
                                /tikz/\searchname/.retry=#1}}}%       
 %<--------------------------------------------------------------–>
 \def\tkzDrawLine{\pgfutil@ifnextchar[{\tkz@DrawLine}{%
                                  \tkz@DrawLine[]}}% 
  \def\tkz@DrawLine[#1](#2,#3){%
 \begingroup
  \pgfkeys{tkzdrawline/.cd,start = {}, end = {}, start style={}, end style={},}
  \pgfqkeys{/tkzdrawline}{#1}
  \draw[ /tkzdrawline/.cd,#1] (#2) to%
    node [at start,left,/tkzdrawline/.cd,tkzstartstyle,node contents={\tkz@line@start}]%
    node [at end,right,/tkzdrawline/.cd,tkzendstyle,node contents={\tkz@line@end}] {} (#3);
 \endgroup
 }% 
 \makeatother

 \begin{document}
   \begin{tikzpicture}
     \node (A) at (0,1) {}; 
     \node (B) at (5,2) {}; 
     \tkzDrawLine[end = {$\alpha$}, start={$\beta$}](A,B)    
  \end{tikzpicture}

\end{document}

TkZ Euclide with line

相关内容