7

Usually I have no problem with babel and !:, and I don't use shortandoff-on switch. But since I made a command using !#1 parameter, the problem comes up again.

The same synthax used outside the command work fine, but in the command I get the error message :

! Package tikz Error: + or - expected.

How to solve the problem without using the shortandoff-on switch ?

\documentclass[french,a4paper]{article}
\RequirePackage{etex}
\RequirePackage[utf8]{inputenc}
\RequirePackage[T1]{fontenc}
\RequirePackage{fourier}

\RequirePackage{tikz}
\usetikzlibrary{calc,intersections}

%%%%%%%%%%%%%%%%%%%%%%
%%%% Francisation %%%%
%%%%%%%%%%%%%%%%%%%%%%

\RequirePackage{babel}

%%%%%%%%%%%%%%%%%%% ----------------------------------------
%%%% Géométrie %%%%
%%%%%%%%%%%%%%%%%%%-----------------------------------------

    % #1 option du path
    % #2 premier point
    % #3 second point
    % #4 longueur dans un sens
    % #5 longueur dans l'autre
    % défini Mil#1#2
\newcommand{\Med}[5][]{%
    \path[#1,name path=Med#2#3] ($(#2)!.5!(#3)$) node (Mil#2#3) {} 
    ($(Mil#2#3)!#4!90:(#3)$) -- ($(Mil#2#3)!#5!270:(#3)$) ; }

\tikzset{small dot/.style={fill=black,circle,scale=0.3}}

\begin{document}

%\shorthandoff{:!}
\begin{tikzpicture}

\coordinate[label=below left:$A$] (A) at (0,0) ;
\coordinate[label=below right:$B$] (B) at (4,0) ;

\draw (A)--(B) ;

%\Med[draw]{A}{B}{1}{1} ;

\draw($(A)!.5!(B)$) node (MilAB) {} 
    ($(MilAB)!1!90:(B)$) -- ($(MilAB)!1!270:(B)$) ; 

\end{tikzpicture}
%\shorthandon{:!}

\end{document}
Tarass
  • 16,912

2 Answers2

10

TikZ v3.0.0 is introducing a library babel for the purpose. It is documented on page 526 of the pgfmanual (42 Babel Library).

With its help

\Med[draw]{A}{B}{1}{1} ;

can now work:

\documentclass[french,a4paper]{article}
\RequirePackage{etex}
\RequirePackage[utf8]{inputenc}
\RequirePackage[T1]{fontenc}
\RequirePackage{fourier}

\RequirePackage{tikz}
\usetikzlibrary{calc,intersections}
\usetikzlibrary{babel} % <= the new library

%%%%%%%%%%%%%%%%%%%%%%
%%%% Francisation %%%%
%%%%%%%%%%%%%%%%%%%%%%

\RequirePackage{babel}

%%%%%%%%%%%%%%%%%%% ----------------------------------------
%%%% Géométrie %%%%
%%%%%%%%%%%%%%%%%%%-----------------------------------------

    % #1 option du path
    % #2 premier point
    % #3 second point
    % #4 longueur dans un sens
    % #5 longueur dans l'autre
    % défini Mil#1#2
\newcommand{\Med}[5][]{%
    \path[#1,name path=Med#2#3] ($(#2)!.5!(#3)$) node (Mil#2#3) {} 
    ($(Mil#2#3)!#4!90:(#3)$) -- ($(Mil#2#3)!#5!270:(#3)$) ; }

\tikzset{small dot/.style={fill=black,circle,scale=0.3}}

\begin{document}

\begin{tikzpicture}

\coordinate[label=below left:$A$] (A) at (0,0) ;
\coordinate[label=below right:$B$] (B) at (4,0) ;

\draw (A)--(B) ;

\Med[draw]{A}{B}{1}{1} ;

\draw($(A)!.5!(B)$) node (MilAB) {} 
    ($(MilAB)!1!90:(B)$) -- ($(MilAB)!1!270:(B)$) ; 

\end{tikzpicture}

\end{document}

The result:

enter image description here

8

TikZ tries to play nice with packages such as babel which change catcodes of certain characters. The problem is that TikZ needs to parse various expressions such as ($(a)!.5!(b)$) which contain special characters like ! and $. To our human eye, these look fairly easy to spot. But TikZ has to work in TeX's world and so has to take account of catcodes as well. So it has to look for $-as-math-shift or $-as-active or $-as-something-else. The way that TikZ works out which one to look for is to examine the current catcode of the special character and look for that. So it says "What is the current catcode of $? Okay, look for $ with that catcode." (Well, it's a bit more complicated than that ... but that'll do for this explanation.)

The problem comes when a command is used that was defined under a different catcode scheme. If you define a command where, say, ! is "other" but use it when ! is, say, "active" then you confuse the parser. It's expecting ! to be active (because it is at use time) but doesn't find it (because the embedded ! is frozen as "other").

The simplest solution is to ensure that you define your commands under the same catcode scheme as they will be used under. Unfortunately, babel doesn't put its catcode scheme into place until \begin{document} so either define these commands after \begin{document} (which is fine, but bad style) or switch the catcodes while defining them. This latter is easy enough using the \shorthandon/\shorthandoff switches.

If you're going to use the commands under different catcode regimes then life is a big more complicated. In effect you have to emulate TikZ's switching method and define different versions of your commands, one in each scheme, and switch between them according to the current catcode scheme. That's a more complicated answer, though, so if you want then then ask a fresh question.

For the one-scheme-to-rule-them-all solution, here's a possible version:

\documentclass[french,a4paper]{article}
%\url{http://tex.stackexchange.com/q/163929/86}
\RequirePackage{etex}
\RequirePackage[utf8]{inputenc}
\RequirePackage[T1]{fontenc}
\RequirePackage{fourier}

\RequirePackage{tikz}
\usetikzlibrary{calc,intersections}

%%%%%%%%%%%%%%%%%%%%%%
%%%% Francisation %%%%
%%%%%%%%%%%%%%%%%%%%%%

\RequirePackage{babel}

%%%%%%%%%%%%%%%%%%% ----------------------------------------
%%%% Géométrie %%%%
%%%%%%%%%%%%%%%%%%%-----------------------------------------

    % #1 option du path
    % #2 premier point
    % #3 second point
    % #4 longueur dans un sens
    % #5 longueur dans l'autre
    % défini Mil#1#2
\showthe\catcode`! % 12, other
\shorthandon{:!}
\showthe\catcode`! % 13, active
\newcommand{\Med}[5][]{%
    \path[#1,name path=Med#2#3] ($(#2)!.5!(#3)$) node (Mil#2#3) {} 
    ($(Mil#2#3)!#4!90:(#3)$) -- ($(Mil#2#3)!#5!270:(#3)$) ; }
\shorthandoff{:!}
\showthe\catcode`! % 12,other

\tikzset{small dot/.style={fill=black,circle,scale=0.3}}

\begin{document}

\showthe\catcode`! % 13, active
\begin{tikzpicture}
\showthe\catcode`! % 13, active

\coordinate[label=below left:$A$] (A) at (0,0) ;
\coordinate[label=below right:$B$] (B) at (4,0) ;

\draw (A)--(B) ;

\Med[draw]{A}{B}{1}{1}

\end{tikzpicture}

\end{document}

All the \showthe\catcode stuff is to print the catcode of ! at the appropriate junctures to show how the switching is working. They can safely be removed.

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • I think TikZ v3.00 fixed this once and forall. – percusse Mar 06 '14 at 08:47
  • @percusse: Apparently not, I use TikZ v3.00 and I had not problem since this command ... – Tarass Mar 06 '14 at 09:08
  • @Andrew-Gandalf: one-scheme-to-rule-them-all is good for me. – Tarass Mar 06 '14 at 09:09
  • @percusse \show\pgfversion reports 3.0.0 on my system and I saw the problem with the original code. So whilst TikZ v3.00 probably is better than previous versions, it doesn't appear to have a complete solution. Not that I think it should: a complete solution would be to test for every catcode variant of the given character each time which would be far too expensive. – Andrew Stacey Mar 06 '14 at 09:10
  • 2
    Actually, I suppose one should load the babel library to let TikZ 3.0.0 solving all the problems. – Claudio Fiandrino Mar 06 '14 at 10:10
  • @ClaudioFiandrino Not sure I get what you're suggesting there. The problem isn't (I think) with the order of loading. babel doesn't do its catcode changes until the \begin{document} is issued, so any commands defined beforehand are in the old catcode regime not the new one. – Andrew Stacey Mar 06 '14 at 10:28
  • @AndrewStacey: the suggestion is to \usetikzlibrary{babel}; I loaded it right after the TikZ call and decommented \Med[draw]{A}{B}{1}{1} ;: the compilation was fine. Without that call, I'm getting errors. – Claudio Fiandrino Mar 06 '14 at 10:35
  • @ClaudioFiandrino I was completely unaware of the existence of this library! (And it doesn't appear in the documentation as far as I can tell.) What it appears to do is to effectively issue \shorthandoff at the start of the tikzpicture and \shorthandon at the end, plus some extra for handling nodes. That's neat. I recommend you post that as a solution. – Andrew Stacey Mar 06 '14 at 10:44
  • @AndrewStacey: sure; I will detail also where it is documented. – Claudio Fiandrino Mar 06 '14 at 10:47
  • Oops sorry for missing out the babel library detail. – percusse Mar 06 '14 at 10:58
  • @Tarass I recommend that you accept Claudio's answer. It's the better solution. – Andrew Stacey Mar 06 '14 at 11:00
  • Ok I did't see Claudio's answer, only the comment above. Then he gets the bonus ;-) – Tarass Mar 06 '14 at 11:38