![狡猾的 (La)TeX 技巧](https://linux22.com/image/237650/%E7%8B%A1%E7%8C%BE%E7%9A%84%20(La)TeX%20%E6%8A%80%E5%B7%A7.png)
编写 (La)TeX 代码有时需要一定的技巧。以下是我最喜欢的两个示例(无特定顺序)。
以空格结尾的宏
皮特问如何看待\LaTeX
,因为\show\LaTeX
结果是\protect \LaTeX
。Joseph Wright 的建议让我很开心。(我可能应该尝试多出去走走)。
\let\protect\show
\LaTeX
将变量大写
我问如何存储变量中字符串的大写对应部分, 因为
\def\word{abc}
\def\WORD{\MakeUppercase{\word}}
\show\WORD
返回\MakeUppercase {abc}
。Bruno Le Floch 提供了一个极好的解决方案。
\MakeUppercase{\gdef\noexpand\WORD{\word}}
您最喜欢的 (La)TeX 巧妙技巧是什么?
主持人注:这可能应该是社区维基。
答案1
这是我的一石二鸟技术。对表格进行排序并markdown 语法无需改变 catcode。
首先创建一个列表和一个辅助宏来添加元素。
\let\alist\@empty
\def\addtolist#1#2{%
\lst@lAddTo#1{#2}}
创建两个命令,一个基于 A 列(作为主索引)或 B 列进行排序。
\def\RA#1|#2|#3|#4;{%
\addtolist{\alist}{#1#2,}%
\expandafter\gdef\csname#1#2\endcsname{\textit{#1}\cr\relax}
\lst@BubbleSort{\alist}
}
排序宏来自listings
文档类lstdoc
。数据添加如下,使用分号作为行尾分隔符是我使用 Pascal 时遗留下来的,如果最后一列只是数字或单个单词,则可以使用空格。
\RA Lactarius fallax | velvety milk cap |edible |potentially risky;
\RA Lactarius camphoratus | candy cap |edible |aromatic qualities;
在最小情况下,所有内容都放在一个框中,但使用环境或更复杂的宏同样可以很好地工作。更改\RA
为\RB
根据第二列作为主索引进行排序。
\documentclass{article}
\usepackage{lstdoc,booktabs}
\begin{document}
\makeatletter
\let\alist\@empty
\def\addtolist#1#2{%
\lst@lAddTo#1{#2}
}
\def\RA#1|#2|#3|#4;{%
\addtolist{\alist}{#1#2,}%
\expandafter\gdef\csname#1#2\endcsname{\textit{#1}\cr\relax}
\lst@BubbleSort{\alist}
}
\def\RB#1|#2|#3|#4;{%
\addtolist{\alist}{#2#1,}%
\expandafter\gdef\csname#2#1\endcsname{\textit{#1}\cr\relax}
\lst@BubbleSort{\alist}
}
%% adding the data now
\RA Lactarius fallax | velvety milk cap |edible |potentially risky;
\RA Lactarius camphoratus | candy cap |edible |aromatic qualities;
\RA Suillus pungens | slippery Jack |edible |poor taste;
\RA Lactarius affinis | kindred milk |edible |unpalatable;
\RA Calocybe carnea | pink fairhead |edible |potentially risky;
\RA Amateta ocreata | death angel |inedible |highly poisonous;
%% typesetting the table
\newsavebox{\tempbox}
\savebox{\tempbox}{
\centering
\begin{tabular}{llll}
\toprule[1pt]
Species & Common name & Edibility & Remarks\\
\midrule
\@for\i:=\alist \do{\csname\i\endcsname}
\vspace{-14pt}\\\bottomrule
\end{tabular}
}
\begin{table}
\usebox{\tempbox}
\caption{Some mushrooms from Wikipedia}
\end{table}
\end{document}
您可以添加更多技巧,具体取决于您想要实现的目标,稍微改变的定义,\RA
然后\RB
您可以创建指向维基百科文章的自动链接或插入图像。这比使用 DBtools 快得多,也灵活得多。
答案2
一个非常有用的方法是
\romannumeral
扩展其路径上的所有内容,直到找到一个整数。如果整数为负数,则将其扩展为零。这可用于完全扩展某些内容,如下所示:\def\a{\b}\def\b{\c}\def\c{\d}\def\d{1} \expandafter\show\romannumeral-`\0\a
这里
-`0
不是一个完整的数字(它需要一个空格才能变成减去的字符代码0
),因此 TeX 会向前看,并在前进过程中扩展标记。代码将显示1
。另一方面,\expandafter\show\romannumeral0\a
会导致一些意外:经过几次扩展后,\a
会产生1
,而 TeX 现在看到的是\romannumeral01
,它将扩展为i
(如果前面有更多数字,则为其他值)。(感谢 egreg 的评论。)\afterassignment
我还喜欢使用和的组合\futurelet
来提前读取两个标记。例如,\newcommand{\readhead} [2] {\afterassignment\@gobble\futurelet#1{#2}}
将设置
#1
为等于标记列表的第一个标记,然后从输入流中#2
删除。#2
测试给定的标记是否是
-
、、+
数字或其他内容:\newcommand{\test}[1]{% \ifcase\numexpr1\noexpand#11\relax % - \or % other \or % + \else % digit \fi}
如果目标是测试字符的字符代码(不管类别代码),则替换
\noexpand
为,假设这不是太疯狂。\string
\escapechar
测试某个字符是否是字母。
\ifnum\numexpr\uccode`#1/26=3 True\else False\fi
当然,如果有人摆弄大写代码,这就会破坏它。
测试一个字符是否是数字。
\ifnum 9<1#1 True\else False\fi
答案3
我最喜欢的技巧之一是
\begingroup
<assignments>
\def\x{\endgroup<something>}\x
或其变体。例如(来自 LaTeX 内核)
\begingroup
\catcode`P=12
\catcode`T=12
\lowercase{
\def\x{\def\rem@pt##1.##2PT{##1\ifnum##2>\z@.##2\fi}}}
\expandafter\endgroup\x
\def\strip@pt{\expandafter\rem@pt\the}
实际上可以简化为
\begingroup
\catcode`P=12
\catcode`T=12
\lowercase{\endgroup\def\rem@pt#1.#2PT}{#1\ifnum#2>\z@.#2\fi}
\def\strip@pt{\expandafter\rem@pt\the}
需要花点时间思考才能理解其中的原理。Heiko Oberdiek 的软件包中有很多\lowercase
or的用法\uppercase
(其中充满了其他巧妙的技巧)。
另一个关于同一主题的变体,是在看过 Danie Els 的回答后添加的。没有必要通过以下方式全局定义活跃期:
\begingroup
\lccode`\~=`\.
\lowercase{\endgroup
\def\unitcenterdot{\mathcode`\.=\string"8000 \def~{\,{\cdot}\,}}}
\protected\def\unit#1{%
\begingroup\unitcenterdot
\ensuremath{\mathrm{#1}}%
\endgroup}
\protected\def\SI#1#2{\ensuremath{#1\,\unit{#2}}}
(\string
是为了避免出现问题巴别塔可能会激活它)。当\lowercase
执行时,我们有定义
\def\unitcenterdot{\mathcode`\.=\string"8000 \def.{\,{\cdot}\,}}}
(但句号处于活动状态)。这样,我们只在 内部定义活动句号的含义\unit
。这些命令被定义为强大的:将它们放在其他命令的参数中没有问题,因为没有类别代码更改,但有时\write
TeX 会找到没有定义的活动句号。
答案4
我从 Bruno Le Floch 那里学到并偷来的我最喜欢的技巧之一是\slantbox
,正如他在剪切变换一个“盒子”。这名义上将采用一个参数并使用\pdf...
魔法,将其向右倾斜(正倾斜)或向左倾斜(负倾斜)到任意程度。
首先,这是 Bruno 为您的序言编写的魔法代码:
\newsavebox{\foobox}
\newcommand{\slantbox}[2][.5]
{%
\mbox
{%
\sbox{\foobox}{#2}%
\hskip\wd\foobox
\pdfsave
\pdfsetmatrix{1 0 #1 1}%
\llap{\usebox{\foobox}}%
\pdfrestore
}%
}
现在,只需找到创造性的方法来使用它。看起来很简单,但我已经找到了所以用途广泛,可以在我的许多答案中使用它。对于下面列举的许多答案,我将提供图片。
- 为没有倾斜的字体提供倾斜:如何使用 libertine 字体的倾斜变体?
- 倾斜字母以使其与相邻的对象一致:萨拉曼卡的胜利标志
- 改变字母倾斜度以更好地符合传统/历史期望,例如拉普拉斯变换算子的外观:这个拉普拉斯变换符号在 LaTeX 中可用吗?
- 绘制符合斜体文本倾斜度的框:在单词中绘制斜体框作为占位符(围绕单个字母)
- 三维透视绘图:a)绘制带阴影的 3D 堆叠正方形,b)我怎样才能像 Don 一样在 LaTeX 中显示 pi?, C)Tikz - 透视字母,旋转书写,d)“星球大战”文字效果和 e)将文本放置在 3D 立方体的表面上
- 模拟左手书写:用左手写字
- 为任何希腊字体:a)直立希腊字体适合计算机现代和 b)文档标题中的数学模式
- 创建涉及倾斜的自定义符号:“#” 和 “ff” 之间的符号
- 另一个狡猾的伎俩,完全无关
\slantbox
,是我开发的一个简单的宏,用于在不使用包的情况下进行冒泡排序,如下答案所示,使用 LaTeX 压缩数字列表
宏本身是
\def\listterminator{9999}% SET TO *ANY* VALUE KNOWN NOT TO BE IN LIST (POSITIVE OR NEGATIVE)
\newcommand\bubblesort[1]{\def\sortedlist{}\sortlist#1,\listterminator,\relax}
\def\sortlist#1,#2,#3\relax{%
\ifnum#2=\listterminator\relax%
\edef\sortedlist{\sortedlist#1}%
\else
\ifnum#1<#2\relax%
\edef\sortedlist{\sortedlist#1,}%
\sortlist#2,#3\relax%
\else%
\let\tmp\sortedlist%
\def\sortedlist{}%
\expandafter\sortlist\tmp#2,#1,#3\relax%
\fi%
\fi%
}
它接受像这样的输入\bubblesort{1,2,11, 7, 4, 3}
,并在宏中产生排序结果,\sortedlist
效果为1,2, 3, 4, 7,11
。
类似的代码,但修复了上述冒泡排序的两个问题:
- 如果列表中有两个值相等,则无限循环。此版本删除了二元组。
! TeX capacity exceeded, sorry [parameter stack size=...]
对于大列表来说已经修复。
\listterminator
它还通过将对终止值的检查更改为 来消除对 的需要\ifx\undefined#2
。
\def\bubblesort#1{\def\sortedlist{}\sortlist#1,\undefined,\relax}
\def\sortlist#1,#2,#3\relax{%
\ifx\undefined#2%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\edef\sortedlist{\sortedlist#1}}
{%
\ifnum#1<#2
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\edef\sortedlist{\sortedlist#1,}\sortlist#2,#3\relax}
{%
\ifnum#1=#2
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\sortlist#2,#3\relax}%
{%
\let\tmp\sortedlist
\def\sortedlist{}%
\expandafter\sortlist\tmp#2,#1,#3\relax
}%
}%
}%
}