9

I am currently working on an update of tkz-euclide and new documentation but I just met the following problem. If I compile this code with pdflatex or lualatex and pgf 2.1 (The library babel does not exist with pgf 2.1) then the code compiles fine but with 3.0 pgf I must comment on the call \usetikzlibrary{babel} (pgf doc gives so I recommend to always load this library by saying \usetikzlibrary{babel}). I'd like to know where the error occurred. Especially I would like to work around this problem.

With \usetikzlibrary{babel} I get the error Latex Error: ./untitled 2.tex:46 Undefined control sequence. l.1 \tkz@line@start

Bug in babel, bug in tikzlibrary{babel} bug in my code. I would like to keep \usetikzlibrary{babel} but to avoid the error.

%!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}
6

The babel TikZ library invokes two keys handle active characters in code and handle active characters in nodes. The latter controls how node contents are parsed. The crucial code is:

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

Did you spot it? It's that \scantokens in the inner \else branch. This means that the contents of the node will be rescanned and so the \makeatletter no longer applies. Thus when \tkz@line@start is invoked, the tokens are rescanned meaning that it is \tkz @ l i n e @ s t a r t (using spaces to separate tokens).

Exactly how to surmount this depends on how deep this gets in your code. If this is a typical example, you could just use \csname tkz@line@start\endcsname. Another solution, which is a bit more elegant in my mind, is to use the node contents key. This doesn't seem to get hit by the \scantokens (I guess because the node contents are more likely to be used in styles than in bare text). (Slightly oddly, I seem to still need the empty braces after the second node when I do that.)

%!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

  • Thanks for your fine explanation! I had not seen or noticed this scantokens – Alain Matthes Mar 9 '16 at 22:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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