个人命令与 tikz calc 库不兼容

个人命令与 tikz calc 库不兼容

我编写了一个名为的个人命令\compo,它允许您在文本旁边放置一个图形:\compo[.4]{ text }{ figure };

使用 tikz calc 库创建图形时出现以下错误:

! Package tikz Error: + or - expected.

我安装了tikz babel library和,也使用了\shorthandoff\shortandon命令,但这并没有改变任何东西。我猜问题出在我的宏上。他的代码如下:

%----------------------------------------
% new command \compo to place a figure next to a text
%----------------------------------------
\newlength{\colG}\newlength{\colD}
\newcommand{\compo}[3][0.5]{
\setlength{\colG}{#1\linewidth}
\setlength{\colD}{\linewidth}%
\addtolength{\colD}{-\colG}
\addtolength{\colG}{-10pt}
\addtolength{\colD}{-10pt}%
\par \noindent%
\begin{minipage}[t]{\colG}\vspace{0cm}#2\end{minipage}\hfill\vrule\hfill%
\begin{minipage}[t]{\colD}\vspace{0cm}#3\end{minipage}\par}

以下是一个 MCE:

\documentclass[a4paper, 11pt]{article} 
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{tikz}               
\usetikzlibrary{calc}        
\usetikzlibrary{babel}     

%----------------------------------------
% new command \compo to place a figure next to a text
%----------------------------------------
\newlength{\colG}\newlength{\colD}
\newcommand{\compo}[3][0.5]{
\setlength{\colG}{#1\linewidth}
\setlength{\colD}{\linewidth}%
\addtolength{\colD}{-\colG}
\addtolength{\colG}{-10pt}
\addtolength{\colD}{-10pt}%
\par \noindent%
\begin{minipage}[t]{\colG}\vspace{0cm}#2\end{minipage}\hfill\vrule\hfill%
\begin{minipage}[t]{\colD}\vspace{0cm}#3\end{minipage}\par}

\begin{document}

\compo[.5]{
  Un triangle 

}{
\shorthandoff{!:}
\begin{tikzpicture}[handle active characters in code]

\draw(-1,-1) rectangle (4,4);
\coordinate (B) at (0,0);
\coordinate  (C) at (3,0);
\coordinate(D) at (2,0);
\draw(B)--(C)--(D)--cycle;
\coordinate (Ap) at ($(C)!.35!-90:(B)$);
\draw (Ap)--(B)--(C)--cycle;
\end{tikzpicture}
\shorthandon{!:}
}

\end{document}

此宏的代码中有什么错误\compo?我该如何纠正此错误?

答案1

该问题是一个 catcode 问题。下面是一个更简单的演示:

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

\newcommand\compo[1]{#1} % compo does nothing but return it's argument
\begin{document}
%%% Works:
\shorthandoff{!}
\compo{
    \begin{tikzpicture}[]
    \coordinate (Ap) at ($(0,0)!0!(3,0)$);
    \end{tikzpicture}
}
\shorthandon{!}

%%% Breaks:
\compo{
    \shorthandoff{!}    % \shorthandoff doesn't do anything because characters in 
    \begin{tikzpicture} % argument have already had their catcodes assigned
    \coordinate (Ap) at ($(0,0)!0!(3,0)$); % so the active ! causes an error here
    \end{tikzpicture}
    \shorthandon{!}
}
\end{document} 

请注意,我已将您的命令替换为一个只返回其参数而不执行任何操作的命令,但仍然会导致问题。为什么会导致问题?因为字符的 catcode 是在第一次解析时分配的。通常,在命令从 catcode active 更改为 catcode other!之后,会解析 tikzpicture 主体中的。但是,当在命令的参数中出现 时,会在评估任何主体之前解析整个命令主体。因此,已经处于活动状态,并且命令导致的 catcode 更改不执行任何操作。最好的解决方法是在命令内部执行 catcode 更改并调用 helpre 命令来获取参数:\shorthandoff{!}!!!\shorthandoff{!}\compo

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

% The wrapper command doesn't take any arguments, it just makes the catcode change and 
% calls the helper.
\newcommand\compo{\shorthandoff{!}\compohelper}
% The helper does all the work.
\newcommand\compohelper[1]{#1\shorthandon{!}}
\begin{document}
\compo{
    \begin{tikzpicture}
    \coordinate (Ap) at ($(0,0)!0!(3,0)$);
    \end{tikzpicture}
}
\end{document} 

现在您可以使用原始定义\compohelper并且它可以按预期工作:

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

\newlength{\colG}\newlength{\colD}
% Wrapper command just changes catcodes and calls helper
\newcommand\compo{%
    \shorthandoff{!:}% Change the catcodes
    \compohelper % call helper to grab arguments
}
\newcommand{\compohelper}[3][0.5]{% do actual work
    \setlength{\colG}{#1\linewidth}%
    \setlength{\colD}{\linewidth}%
    \addtolength{\colD}{-\colG}%
    \addtolength{\colG}{-10pt}%
    \addtolength{\colD}{-10pt}%
    \par \noindent%
    \begin{minipage}[t]{\colG}#2\end{minipage}\hfill\vrule\hfill%    
    \begin{minipage}[t]{\colD}#3\end{minipage}%
    \par
    \shorthandon{!:}% restore catcodes
}

\begin{document}
\compo[.5]{
  Un triangle

}{
    \begin{tikzpicture}
        \draw(-1,-1) rectangle (4,4);
        \coordinate (B) at (0,0);
        \coordinate  (C) at (3,0);
        \coordinate(D) at (2,0);
        \draw(B)--(C)--(D)--cycle;
        \coordinate (Ap) at ($(C)!.35!-90:(B)$);
        \draw (Ap)--(B)--(C)--cycle;
    \end{tikzpicture}
}
\end{document} 

相关内容