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  
add comment

3 Answers

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
1  
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. –  Andrew Stacey Apr 22 '13 at 14:28
show 12 more comments

I use this:

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

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
add comment

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.