Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to declare functions in tikz for multiple uses of the same function within the code.

Sadly, it seems that the tikz "declare function" is not compatible with the french option in babel. Indeed, the following code (that I simplifed on purpose) runs fine :

\documentclass[english]{article}
\usepackage{babel}                      
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
    \tikzset{declare function={Carre(\t)=\t*\t;}}
    \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}
\end{document}

But when I replace

\documentclass[english]{article}

with

\documentclass[english,french]{article}

compilation generates an error. This is what the log file says :

Missing character: There is no = in font nullfont! Missing character: There is no @ in font nullfont! Missing character: There is no @ in font nullfont!

Runaway argument? -1:1] (\x ,{Carre(\x )}); \end {tikzpicture} \end {document} ! Paragraph ended before \pgfmath@local@@functions was complete. \par l.18

I suspect you've forgotten a `}', causing me to apply this control sequence to too much text. How can we recover? My plan is to forget the whole thing and hope for the best.

Before posting this, I updated all packages without success.

Any help welcome!

share|improve this question
1  

4 Answers 4

The semicolon is made active by the french babel option, which throws the TikZ parser off. You can say \shorthandoff{;} in your tizpicture to fix this.

You can do this either by manually putting \shorthandoff{;} at the start of each tikzpicture, or you can use a TikZ style for inserting the code automatically into each tikzpicture by setting

\tikzset{
    every picture/.prefix style={
        execute at begin picture=\shorthandoff{;}
    }
}

or, as Tobi points out in a comment, you can load the etoolbox package and use

\AtBeginEnvironment{tikzpicture}{\shorthandoff{;}}

to patch the tikzpicture environment.

share|improve this answer
4  
It seems to work too with \AtBeginEnvironment{tikzpicture}{\shorthandoff{;}} (command form etoolbox package) So one can hack the environment globally and not every single environment. –  Tobi Dec 7 '12 at 22:53
    
@Tobi: Good point! I've edited my answer accordingly. –  Jake Dec 7 '12 at 23:07
1  
I think /.prefix style is a tiny bit safer. –  percusse Dec 8 '12 at 23:52
1  
@Tobi What's the difference between 'globally' and 'every single environment'? –  marczellm Jan 20 '13 at 22:23
2  
Note that this won't work in beamer unless the fragile option is given to the frame since in beamer the frames are read in before processing and catcodes are frozen at that time. –  Loop Space Apr 22 '13 at 14:28

As with the question that Claudio links to, the problem is in some extra code that TikZ loads which doesn't have the same amount of checking for active characters as the main TikZ parser does. As Babel doesn't change the catcode of ; until the start of the document all of the semicolons involved in the declare function routine are inactive and thus don't match the active semicolon in the declaration of the function. Also as in that question, one solution is as Jake says: to switch off the activeness of ; in a tikzpicture. Another is to hack the code to make it robust with respect to the catcode of the semicolon:

\documentclass[french]{article}
%\url{http://tex.stackexchange.com/q/86023/86}
\usepackage{babel}                      
\usepackage{tikz}

\makeatletter
\pgfkeys{%
        /pgf/declare function/.code={%
          \ifnum\the\catcode`\;=\active\relax%
          \let\pgfmath@local@function@body=\pgfmath@local@function@body@active
          \let\pgfmath@local@@functions=\pgfmath@local@@functions@active
          \pgfmath@local@functions@active{#1}%
          \else
          \pgfmath@local@functions@notactive{#1}%
          \fi
        }
}

\def\pgfmath@local@functions@notactive#1{%
  \pgfmath@local@functions#1@=@;%
}

\begingroup
\catcode`\;=\active\relax
\gdef\pgfmath@local@functions@active#1{%
  \pgfmath@local@functions#1@=@;%
}

\gdef\pgfmath@local@@functions@active#1=#2;{%
        \def\pgfmath@local@temp{#1}%
        \ifx\pgfmath@local@temp\pgfmath@local@at%
                \let\pgfmath@local@next=\relax%
        \else%
                \pgfmath@local@function#1=#2;%
                \let\pgfmath@local@next=\pgfmath@local@functions%
        \fi%
        \pgfmath@local@next%
}
\gdef\pgfmath@local@function@body@active#1;{%
        \def\pgfmath@local@body{#1}%
        \begingroup%
                \c@pgf@counta=0\relax%
                \ifx\pgfmath@local@args\pgfmath@empty%
                        \expandafter\pgfmath@toks\expandafter=\expandafter{\pgfmath@local@body}%
                \else%
                        \pgfmath@toks={}%
                        \expandafter\pgfmath@local@function@@body\pgfmath@local@args,,%
                \fi%
                \xdef\pgfmath@local@temp{%
                        \noexpand\pgfmathdeclarefunction{\pgfmath@local@name}{\the\c@pgf@counta}%
                                {\noexpand\pgfmathparse{\the\pgfmath@toks}}%
                }%
        \endgroup%
        \pgfmath@local@temp%
}

\endgroup


\makeatother

\begin{document}
\begin{tikzpicture}
    \tikzset{declare function={Carre(\t)=\t*\t;}}
    \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}

\shorthandoff{;}

\begin{tikzpicture}
    \tikzset{declare function={Carre(\t)=\t*\t;}}
    \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}
\end{document}

As with the other question, the result here is that it compiles. To prove that, here's the result (sort of, standalone puts the pictures side by side):

declare function with active and inactive semicolon

share|improve this answer

TikZ 3.0 introduced a new babel tikzlibrary to solve these kind of problems.

A tiny library that make the interaction with the babel package easier. Despite the name, it may also be useful in other contexts, namely whenever the catcodes of important symbols are changed globally. Normally, using this library is always a good idea; it is not always loaded by default since in some rare cases it may break old code.

\documentclass[english]{article}
\usepackage[english,french]{babel}                      
\usepackage{tikz}
\usetikzlibrary{babel}

\begin{document}
\begin{tikzpicture}
    \tikzset{declare function={Carre(\t)=\t*\t;}}
    \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer

I use this:

\usepackage[babel=true, kerning=true]{microtype}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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