# Tikz shortandoff-on newcommand problem

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}

-
You can make \shorthandoff{:!} only inside tikzpicture. You don't like that idea is it? – Harish Kumar Mar 6 '14 at 6:00
Inside or around the command is better, isn't it ? as it's done once. – Tarass Mar 6 '14 at 8:42

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:

-

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.

-
I think TikZ v3.00 fixed this once and forall. – percusse Mar 6 '14 at 8:47
@percusse: Apparently not, I use TikZ v3.00 and I had not problem since this command ... – Tarass Mar 6 '14 at 9:08
@Andrew-Gandalf: one-scheme-to-rule-them-all is good for me. – Tarass Mar 6 '14 at 9: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. – Loop Space Mar 6 '14 at 9:10
Actually, I suppose one should load the babel` library to let TikZ 3.0.0 solving all the problems. – Claudio Fiandrino Mar 6 '14 at 10:10