代币及其含义

代币及其含义

tikz 声明函数和 babel 法语选项它涉及到 TeX 含义中局部和全局之间的区别的问题。

在链接的问题中,;应该在 a 中停用babel 简写{tikzpicture},这可以通过以下方式完成

\begin{tikzpicture}
   \shorthandoff{;}
   ...
\end{tikzpicture}

答案1

概念全球的当地的与为标记分配含义或为寄存器分配值有关。

代币及其含义

标记是 TeX 的基本食物,有两种:字符标记象征性标记粗略的说,后者就是我们用“反斜杠+字符”来表示的。

字符标记的含义取决于该字符的“字符代码”和“类别代码”的组合;例如,在正常设置下,字符A对应于对 (65,11),而{对应于对 (123,1)。类别代码 1 赋予{其作为组和参数分隔符的特殊含义。类似地,\对应于 (92,0),因此反斜杠充当符号标记的标记。

许多代币都有预定义意思是 TeX 开始工作的时候。每个字符标记都有一个字符代码(不能更改)和一个类别代码(可以稍后更改);一些符号标记是原始,这样 TeX 就不会从零开始。

作业

任何时候,都可以为新的符号标记赋予含义,或者可以更改已知标记的含义(对于字符标记,仅更改类别代码)。TeX 对标记的操作取决于上下文。例如,\tracingmacros是一个(原始)整数寄存器;

\tracingmacros=1

TeX 将分配将值 1 存入整数寄存器,而

\count255=\tracingmacros

存储的当前值\tracingmacros将被赋值为存储在整数寄存器中的值\count255

两者都是作业每次修改存储在寄存器或数组中的标记或值的含义时,我们都在进行赋值。列出所有类型的赋值会太长。除了前面显示的类型外,基本类型还包括:

\def\cs<parameter text>{<replacement text>}
\let\cs=<token>
\catcode<8 bit number>=<4 bit number>
<font selector>

(当使用 LuaTeX 或 XeTeX 时, 为<8 bit number><21 bit number>。最后一种类型表示选择字体作为当前字体的符号标记(当使用或 时,<font selector>LaTeX 会在后台执行此类分配)。还有更多,但这样说太过分了。\bfseries\textit

准确地说,作业不能真正地完成任何\edef时间。TeX 仅在执行命令时才执行赋值(扩展宏时除外);特别是在计算替换文本时或写出操作结果时,它不会执行赋值\write

活跃角色

字符标记的一种特殊类型是类别代码为 13 的标记。当 TeX 发现这样的字符时,它会将其视为符号标记来查找其含义,并且必须用\def或 (或其变体)来分配该含义\let。这是众所周知的 的情况~

群组

按规定每一个赋值(几乎每个赋值,参见“例外”部分)都是有作用域的,当当前组结束。什么是组?TeX 可以通过多种方式打开组:

  1. 使用{不具有参数分隔符作用的 ;该组将以}同一括号级别的 结尾。可以使用\bgroupfor{\egroup for}获得相同效果(简单组)。

  2. 使用\begingroup; 当前组将以相应的\endgroup(结束半单群)。

  3. \vbox当要排版为、\vtop\vcenter的文本\hbox被吸收时(箱体组)。

  4. 当对齐单元格的文本被吸收时;它几乎与框组相同(对齐组)。

  5. $$$启动数学公式时(数学公式组)。开始或结束数学显示的
    标记$$由 LaTeX 自动提供;切勿$$...$$在 LaTeX 中直接使用

  6. 其他特殊情况可以在 TeXbook 或 TeX by Topic 中找到(例如,\left开始一个组,以匹配的 结束\right)。

因此\begingroup\tensl ABC \endgroup DEF将打印“ABCDEF”,因为当前字体的赋值在 时结束其生效\endgroup。相反

\def\my#1{-- #1 --}
\my{\tensl ABC} DEF

将打印“--ABC--防御“并继续使用倾斜的字体,因为\tensl在组内还未看到该声明。

全球任务

每个赋值都可以以 and 为前缀,在这种情况下,其效果将超越当前组。 is ; so\global的缩写\global\def\gdef

\begingroup
\catcode`-=\active % \active here means 13
\gdef-{not a hyphen}
\endgroup

同时显示两种分配方式。 的类别代码-仅在本地更改,但 的含义-作为活动字符被全局分配。每当 TeX 找到 (45,13) 对时, 的定义-将用作活动字符,但-在 之后将不再默认为活动字符\endgroup。稍后将对此进行详细介绍。

乳胶

在 LaTeX 中,什么才算是组?除了上述一般的 TeX 构造之外,环境也会形成组,这是因为 LaTeX 实现\begin和的方式不同\end\begingroup前者和\endgroup后者都存在。但有一个明显的例外,即环境document,但这仅从理论角度来看很重要,因为只能有一个环境。但是,、、、、和的document参数也将被吸收为组,因为它们在内部使用、或。类似地,或环境中的每个单元格都会自己组成一个组,这是对齐组的特殊情况。\mbox\makebox\fbox\framebox\sbox\savebox\parbox\hbox\vbox\vtop\vcentertabulartabbing

LaTeX 命令\newcommand、、\renewcommand\newenvironment\renewenvironment的包装器\def,因此它们仅作用于本地,但不能以 开头\global。因此,除了使用较低级别的命令外,基本上没有办法在 LaTeX 中进行全局分配。LaTeX 的分配是一个例外计数器它们始终是全局的(见底部)。

法语分号的问题

为了应对法语排版的特殊性,babel将一些字符更改为类别代码 13(活动)。这可能会导致 TikZ 出现问题,因为它使用分号作为语句分隔符,但也使用冒号作为语法分隔符。TikZ 的开发人员已尽最大努力避免此设置出现问题,但有时可能会出错。

\usepackage[french]{babel}

具体做什么?细节相当复杂,但除其他事项外,基本上将执行以下操作(然而,这是一个非常广泛的简化):

\begingroup
\catcode`;=\active % \active here means 13
\gdef;{\unskip\penalty10000 \thinspace\string;}
\catcode`:=\active % \active here means 13
\gdef:{\unskip~\string:}
\endgroup
\AtBeginDocument{\catcode`;=\active \catcode`:=\active}

那么当;:在文档中找到不是例如,TikZ 对语句分隔符的期望。

一个例子是tikz 声明函数和 babel 法语选项

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

\begin{document}
\begin{tikzpicture}
  \tikzset{declare function={Carre(\t)=\t*\t;}}
  \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}
\end{document}

语句分隔符的分号\draw被正确解释,因为 TikZ 知道在这种情况下如何处理活动分号。但语句分隔符\tikzset被视为这样却为时已晚。

为了解决这个问题,有两种方法:

  1. \tikzset声明放在序言中,其中分号不是积极的。

  2. 使用本地赋值使分号在tikzpicture环境中处于非活动状态

因此

\documentclass{article}
\usepackage[french]{babel}
\usepackage{tikz}
\tikzset{declare function={Carre(\t)=\t*\t;}}

\begin{document}
\begin{tikzpicture}
  \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}
\end{document}

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

\begin{document}
\begin{tikzpicture}
  \shorthandoff{;}
  \tikzset{declare function={Carre(\t)=\t*\t;}}
  \draw plot [domain=-1:1] (\x,{Carre(\x)});
\end{tikzpicture}
\end{document}

可以工作;\shorthandoff{;}这是 Babel 在本地关闭字符标记活动特性的方式,基本上意味着

\catcode`;=<whatever category code ; had at the start of the job>

而不必强迫我们知道要使用的代码是 12。由于分配是本地的,它将在 结束\end{tikzpicture},因此此后该字符;将再次处于活动状态。

随着 TikZ 3.00 版本的推出,该babel库已被引入,因此当

\usetikzlibrary{babel}

用来。(添加于 2015-01-02)

本地分配的其他用途

假设有人希望除了“一般”定理之外,还有“命名定理”。例如,在某人写的书中,计划有

秩零定理 1.4
格拉姆-施密特定理 2.3

在其他明确标记的声明中定理。一种策略是为每个名称定义一个新的类定理环境,与普通theorem环境共享计数器。不过,可以做得更好:

\newtheorem{theorem}{Theorem}[chapter]
\newtheorem{namedtheoremaux}[theorem]{\protect\thistheoremname}

\newcommand{\thistheoremname}{}
\newenvironment{namedtheorem}[1]
  {\renewcommand{\thistheoremname}{#1}\begin{namedtheoremaux}}
  {\end{namedtheoremaux}}

这样输入就可以

\begin{namedtheorem}{Rank-nullity theorem}
...
\end{namedtheorem}

...

\begin{namedtheorem}{Gram-Schmidt theorem}
...
\end{namedtheorem}

定义中的对于LaTeX 的标准或 提供的标准\protect来说不是必需的;它是用于并且 否则不会造成任何损害。\newtheoremamsthmntheorem

的重新定义\thistheoremname是局部的,因此它只会影响当前namedtheorem环境。

例外

TeX 所做的一些分配是本质上是全球性的. 最常用的此类任务是

\hyphenchar\font=`-
\hyphenchar\font=-1

第一个告诉 TeX,在当前字体中排版时用作连字符的字符应该是普通连字符;第二个告诉 TeX,此字体的连字符被抑制。

说出来不是个好主意

This is a normal paragraph and the following word must not be
{\hyphenchar\font=-1 hyphenated} but others can

因为段落中以及后面使用相同字体的单词将被连字符连接,因为即使前面没有 ,分配也是全局的\global;然而

This is a normal paragraph and the following word must not be
\hyphenchar\font=-1 hyphenated \hyphenchar\font=`- but others can

也不起作用,因为 TeX 对一个字体仅使用一个连字符,即段落结束时与之关联的连字符。

再次使用 LaTeX

计数器上的 LaTeX 操作

  • \setcounter
  • \addtocounter
  • \stepcounter\refstepcounter

实现为全球的作业。相反,\setlength在本地操作(并且在其前面加上\global不起作用)。

答案2

Tobi 的回答并不准确。

\shorthandsoff{;}真的不重新定义 ;,你将 catcode 更改为 ,;以便activeother里面根本tikzpicture不会执行。

这意味着tikzpicture它在内部可以正常工作,但在内部\textbf{...}(或任何其他接受参数的命令)则不行。这是因为字符是在读取时使用 catcode 读取的,而不是在执行时。另一方面,宏赋值( \def\newcommand、 、 ...)是在执行时完成的,因此即使在宏参数中也能正常工作。\let


请注意,如果命令没有将其参数括在组中( 、\begingroup...\endgroup{...}\bgroup...\egroup,则不会使赋值“在参数内部局部化”,而是“在宏的范围内局部化”。请参阅以下示例:

\newcommand\mparen[1]{(#1)}
\def\A{a}

\textbf{\A\ \def\A{b}\A}\ \A % result: a b a

\mparen{\A\ \def\A{b}\A}\ \A % result: a b b

因此,最好在定义中添加分组\mparen

\newcommand\mparen[1]{({#1})}

最后一条注释展示了 catcode 赋值与宏赋值的区别。该命令\makeatletter会赋值@一个 catcode letter,以便可以在宏名称中使用它。该命令\makeatother会还原此操作。因此,请尝试以下示例:

\makeatletter
\newcommand\mparen[1]{(#1)}
\def\A{a}
\def\A@B{b}
\makeatother

\begin{bfseries}
\makeatletter
\A\ \A@B % result: a b
\end{bfseries}

\A\ \A@B % result: a a@B

\textbf{\makeatletter \A\ \A@B}% result: a a@B

\A\ \A@B % result: a a@B

\mparen{\makeatletter \A\ \A@B}% result: a a@B

\A\ \A@B % result: a b

我被要求解释一下最后三行发生了什么。我会一步一步地解释。我r:标记了 TeXReads。o: 我标记的是输出并处理。m:我标记了宏的含义

r: \A 
m: \A -> a
  r: a % we now read the definition of \A
  o: letter `a`
r: \ 
o: space
r: \A % remember, @ is not a letter
m: \A -> a
  r: a
  o: letter `a`
r: @
o: symbol `@`
r: B
o: letter `B`
r: empty line
o: end of paragraph

r: \mparen
m: \mparen#1 -> (#1)
r: {\makeatletter \A\ \A@B} % at this moment, TeX core reads 
     % the arguments. Since @ is still not a letter, sequence \A@B
     % comprises three tokens, `\A`  `@`  `B`
  r: (
  o: symbol `(`
  r: #1
    r: \makeatletter
    o: change of catcode of `@` % notice we ARE NOT IN A GROUP
    r: \A
    m: \A -> a
      r: a
      o: letter `a`
    r: \ 
    o: space
    r: \A
    m: \A -> a
      r: a
      o: letter `a`
    r: @ % catcode is now "letter", but it was actually read
         % couple steps before where catcode was "other"
    o: symbol `@`
    r: B
    o: letter `B`
  r: )
  o: symbol `)`
r: empty line
o: end of paragraph

r: \A
m: \A -> a
  r: a
  o: letter `a`
r: \ 
o: space
r: \A@B % catcode of @ is "letter" now so it's treatened as a part
     % of macro name
m: \A@B -> b
  r: b
  o: letter `b`

答案3

在 TeX 中,每个赋值(定义、计数器更改、catcode 更改等)都是本地的,即,它的作用域位于所谓的“组”内,除非明确将其设为全局。组是两个括号之间的所有内容,即

outside {inside} outside

(括号中括号界定参数的情况除外),环境中的所有内容,即

outside
\begin{env}
   inside
\end{env}
outside

或介于\begingroup和之间的任意值\endgroup

outside
\begingroup
   inside
\endgroup
outside

后者在\begin#1和的定义中使用\end#1

举个例子可以说明:

\documentclass{article}

\newcommand{\A}{A}

\begin{document}
\A\ expands to A

\begin{center}
    \A\ expands to A \\
    \renewcommand{\A}{AA}
    \A\ expands to AA
    
    \newcommand{\B}{B}
    \B\ expands to B
\end{center}

\A\ expands to A and not AA!

\B\ is undefined outside the group here
\end{document}

它的实际用途是保持定义的改变在本地,或者,例如,设置某些单词的字体,如normal {\tiny tiny} normal

问题在于

\begin{tikzpicture}
   \shorthandoff{;}
   ...
\end{tikzpicture}

是必须添加\shorthandoff在每个{tikzpicture}因为它是停用的(即 catcode 更改,请参阅tohecz 答案) 保持在当前 的本地{tikzpicture}。当然,可以将 添加\shorthandoff到前言中,但随后也会切换到普通文本。可以使用 ' 将停用宏添加到 的\begin{tikzpicture}定义etoolbox\AtBeginEnvironment

\AtBeginEnvironment{tikzpicture}{\shorthandoff{;}}

或者在这种情况下使用 TikZ 风格,就像 Jake 说的:

\tikzset{
    every picture/.prefix style={
        execute at begin picture=\shorthandoff{;}
    }
}

相关内容