以下代码受到以下启发这个答案,当选择 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}
。
当您在序言中键入定义时,冒号仍然有\catcode
12(其他),因此的定义\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}
你就得不到任何栅栏了。
对您的代码的一些评论。
\addto
已经以babel
不同的方式由 定义,但它完成相同的工作。覆盖此定义可能会导致错误。您可以直接使用\addto
提供的babel
,但我不推荐这样做,因为它执行全球的定义。您可以通过加载etoolbox
并使用其\appto
命令来避免此问题。\cr
matrix
不应在定义的任何环境中使用。行应以amsmath
结尾\\
很多多于\cr
。不要使用
\def
LaTeX,除非你确切地知道你在做什么,特别是知道你要定义的控制序列尚未定义,或者你知道为什么您想重新定义它。对于您来说,\def\matrL
这很好,因为它是一个临时宏,将被重新定义多次。但这\def\addto...
根本不好。
答案3
为了使宏更能抵抗 catcode 更改,您可以将\ifx
primitive 更改为\if
primitive 并添加\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}