为什么这个宏不能与 babel 的法语选项很好地兼容?

为什么这个宏不能与 babel 的法语选项很好地兼容?

以下代码受到以下启发这个答案,当选择 babel 选项时,会产生不良结果french。但是,使用 选项时,它可以正常工作english

有人能向我解释这一点,并找到一种方法使它能与该french选项很好地配合吗?

\documentclass[12pt]{article}
\usepackage[french]{babel}
%\usepackage[english]{babel}
\usepackage{amsmath}

\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\matr#1{\def\matrL{}\matrA#1\end}
\def\matrA#1{\ifx\end#1\begin{pmatrix}\matrL\end{pmatrix}\else 
   \ifx,#1\addto\matrL{&}\else
   \ifx;#1\addto\matrL{\cr}\else
   \addto\matrL{#1}\fi\fi
   \expandafter\matrA\fi
}

\begin{document}
$\matr{ a, b    ;   c, d    }$
\end{document}

使用法语选项,我得到了以下信息:法语,而这应该给我这个:英语,就像英语选项一样。

答案1

为了确保法语印刷惯例,一些字符(包括分号);被制作成积极的当 在 选择语言时\begin{document}

当您在序言中键入定义时,冒号仍然有\catcode12(其他),因此的定义\matrA#1根据类别代码为 12 的冒号进行检查。但是,当\begin{document}冒号变为活动状态(类别代码 13)时,测试将始终失败。

除了babel在数学模式下停用速记功能外,我找到了两种快速解决方法:要么使用活动冒号定义宏(这样可以仅有的当您使用时french,否则会失败),或者您\ifx用 替换测试\if,它只测试字符代码而不测试类别代码。

\documentclass[12pt]{article}
\usepackage[french]{babel}
\usepackage{amsmath}

% Avoid redefining babel's own \addto
% (thanks to egreg for bringing this to my attention)
\newcommand*{\myaddto}[2]{\expandafter\def\expandafter#1\expandafter{#1#2}}

% Works only when french is loaded
% \begingroup
% \catcode`\;=\active
% \gdef\matr#1{\def\matrL{}\matrA#1\end}
% \gdef\matrA#1{\ifx\end#1\begin{pmatrix}\matrL\end{pmatrix}\else 
%    \ifx,#1\myaddto\matrL{&}\else
%    \ifx;#1\myaddto\matrL{\\}\else
%    \myaddto\matrL{#1}\fi\fi
%    \expandafter\matrA\fi
% }
% \endgroup

\newcommand*{\matr}[1]{\def\matrL{}\matrA#1\end}
\newcommand*{\matrA}[1]{%
   \ifx\end#1\begin{pmatrix}\matrL\end{pmatrix}\else 
   \ifx,#1\myaddto\matrL{&}\else
   \if;#1\myaddto\matrL{\\}\else
   \myaddto\matrL{#1}\fi\fi
   \expandafter\matrA\fi
}

\begin{document}

$\matr{ a , b ; c , d }$

\end{document}

得到期望的输出在此处输入图片描述

答案2

问题是分号在 中处于活动状态babel-french

这里有一个解决方案,将任意类别代码的分号替换为类别代码 12 的分号,因此可以使用“通常”的拆分成行然后处理每一行。

如果在分号未激活时使用该代码,则不会出现问题,因为不会进行替换。

\documentclass[12pt]{article}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{amsmath}

\ExplSyntaxOn
\NewDocumentCommand{\matr}{O{p}m}
 {
  \watson_matrix:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \watson_matrix:nn
 {
  \tl_set:Nn \l_tmpa_tl { #2 }
  \regex_replace_all:nnN { ; } { \cO; } \l_tmpa_tl
  \seq_set_split:NnV \l_tmpa_seq { ; } \l_tmpa_tl
  \begin{#1matrix}
  \seq_map_function:NN \l_tmpa_seq \__watson_matrix_row:n
  \end{#1matrix}
 }
\cs_new_protected:Nn \__watson_matrix_row:n
 {
  \seq_set_split:Nnn \l_tmpb_seq { , } { #1 }
  \seq_use:Nn \l_tmpb_seq { & }
  \\
 }

\ExplSyntaxOff

\begin{document}

\[
\matr{ a, b    ;   c, d    }\qquad
\matr[b]{1,2,3;4,5,6}
\]

\end{document}

为了方便起见,我添加了对不同栅栏的支持。这样\matr[]{1,2;3,4}你就得不到任何栅栏了。

在此处输入图片描述

对您的代码的一些评论。

  1. \addto已经以babel不同的方式由 定义,但它完成相同的工作。覆盖此定义可能会导致错误。您可以直接使用\addto提供的babel,但我不推荐这样做,因为它执行全球的定义。您可以通过加载etoolbox并使用其\appto命令来避免此问题。

  2. \crmatrix不应在定义的任何环境中使用。行应以amsmath结尾\\很多多于\cr

  3. 不要使用\defLaTeX,除非你确切地知道你在做什么,特别是知道你要定义的控制序列尚未定义,或者你知道为什么您想重新定义它。对于您来说,\def\matrL这很好,因为它是一个临时宏,将被重新定义多次。但这\def\addto...根本不好。

答案3

为了使宏更能抵抗 catcode 更改,您可以将\ifxprimitive 更改为\ifprimitive 并添加\string

\def\matrA#1{\ifx\end#1\begin{pmatrix}\matrL\end{pmatrix}\else 
   \if,\string#1\addto\matrL{&}\else
   \if;\string#1\addto\matrL{\cr}\else
   \addto\matrL{#1}\fi\fi
   \expandafter\matrA\fi
}

答案4

\pmatr这是一个 LuaLaTeX 解决方案。它由 2 个 LaTeX 实用宏和\bmatr以及三个 Lua 函数组成,它们几乎可以完成所有工作。

以下屏幕截图中的黄色条显示;(和!)继续具有其特殊含义(与前面的材料由空格分隔)。

还要注意的是,无论是否;是“主动”角色,这种方法都有效。

在此处输入图片描述

\documentclass[12pt]{article}
\usepackage[french]{babel}
\usepackage{amsmath} % for 'pmatrix' and 'bmatrix' environments

\usepackage{luacode} % for 'luacode' env. and '\luastring' macro
\begin{luacode}
function change_chars ( s ) -- replace ';" and "," characters
   s = s:gsub ( ";" , "\\\\" )
   s = s:gsub ( "," , "&" )
   return  s
end
function pmatr ( s ) 
   tex.sprint ( "\\begin{pmatrix}" .. change_chars(s) .. "\\end{pmatrix}" )
end
function bmatr ( s ) 
   tex.sprint ( "\\begin{bmatrix}" .. change_chars(s) .. "\\end{bmatrix}" )
end
\end{luacode}

% Define a couple of utility or "front end" LaTeX macros
\newcommand\pmatr[1]{\directlua{pmatr("#1")}}
\newcommand\bmatr[1]{\directlua{bmatr("#1")}}

\begin{document}
$\pmatr{ a, b ; c, d  } \quad \bmatr{ a, b ; c, d ; e , f} $\quad bonjour; bonsoir!
\end{document}

相关内容