LaTeX/宏
使用您迄今為止學到的命令生成的文件對於大多數讀者來說看起來是可以接受的。雖然它們看起來並不花哨,但它們遵循所有已確立的良好排版規則,這將使它們易於閱讀,並且看起來很舒適。但是,在某些情況下,LaTeX 沒有提供與您的需求匹配的命令或環境,或者某些現有命令產生的輸出可能不符合您的要求。
在本章中,我們將嘗試提供一些關於如何教 LaTeX 新技巧以及如何使其生成與預設情況下提供的輸出不同的輸出的提示。
與純 TeX 相比,LaTeX 是一種相當高階的語言,因此受到更多限制。下一章 將重點介紹純 TeX,並解釋用於程式設計的高階技術。
新命令
[edit | edit source]要新增您自己的命令,請使用
\newcommand{\name}[num]{definition}
|
命令。基本上,該命令需要兩個引數:要建立的命令的名稱(以反斜槓開頭)和命令的定義。請注意,命令名稱可以但不必用花括號括起來,隨你喜歡。方括號中的num 引數是可選的,它指定新命令接受的引數數量(最多可以接受 9 個引數)。如果缺失,則預設為 0,即不允許引數。
以下兩個示例將幫助您瞭解這個概念。第一個示例定義了一個名為\wbal的命令,它將列印“關於 LaTeX 的華夏公益教科書”。如果您需要一遍又一遍地編寫本書的標題,那麼這樣的命令可能很有用。
\newcommand{\wbal}{The Wikibook about \LaTeX}
This is ‘‘\wbal'' \ldots{} ‘‘\wbal''
|
這是“關於 LaTeX 的華夏公益教科書”……“關於 LaTeX 的華夏公益教科書” |
下一個示例說明了如何定義一個接受一個引數的新命令。 #1 標記將被您指定的引數替換。如果您想使用多個引數,請使用 #2 等等,這些引數將新增到一組額外的方括號中。
\newcommand{\wbalsup}[1] {
This is the Wikibook about LaTeX
supported by #1}
\newcommand{\wbalTwo}[2] {
This is the Wikibook about LaTeX
supported by #1 and #2}
% in the document body:
\begin{itemize}
\item \wbalsup{Wikimedia}
\item \wbalsup{lots of users!}
\item \wbalTwo{John Doe}{Anthea Smith}
\end{itemize}
|
|
將您的新命令命名為 \wbalTwo,而不是 \wbal2,因為數字不能用於命名宏——無效字元將在編譯時出錯。
LaTeX 不允許您建立會覆蓋現有命令的新命令。但是,如果您明確希望這樣做,則有一個特殊命令: \renewcommand。它使用與 \newcommand 命令相同的語法。
在某些情況下,您可能還想使用 \providecommand 命令。它的工作原理與 \newcommand 相似,但如果命令已定義,LaTeX 將靜默地忽略新命令。
使用 LaTex2e,還可以使用以下語法向命令新增預設引數
\newcommand{name}[num][default]{definition}
|
如果 \newcommand 的預設引數存在,則由 num 指定的引數數量中的第一個引數是可選的,其預設值為 default;如果不存在,則所有引數都是必需的。
\newcommand{\wbalTwo}[2][Wikimedia]{
This is the Wikibook about LaTeX
supported by {#1} and {#2}!}
% in the document body:
\begin{itemize}
\item \wbalTwo{John Doe}
\item \wbalTwo[lots of users]{John Doe}
\end{itemize}
|
|
- 注意
- 當使用顯式第一個引數使用命令時,它將用方括號括起來(這裡為 "[lots of users]")。
這是一個常見的示例:如果您正在撰寫一本關於數學的書籍,並且必須使用向量,則必須決定它們的外觀。許多書籍中使用了許多不同的標準。如果a 是一個向量,有些人喜歡在它上面新增一個箭頭 (),其他人則用下劃線表示它(a);另一種常見版本是用粗體表示它(a)。假設您想用箭頭在上面寫您的向量;然後在您的mystyle.sty.
\newcommand{\myvec}[1]{\vec{#1}}
|
檔案中新增以下行,並在新的 \myvec{...} 命令中編寫您的向量。您可以根據自己的意願命名它,但最好選擇一個簡短的名稱,因為您可能會經常編寫它。然後,如果您改變主意,並且希望您的向量看起來不同,您只需更改 \myvec{...} 的定義。只要有可能就使用這種方法:這將為您節省大量時間,並提高文件的一致性。
DeclareRobustCommand
[edit | edit source]有些命令是脆弱的,也就是說它們在某些環境中會失敗。如果一個宏在正文文字中有效但在(例如)圖示題中無效,那麼值得嘗試將 \newcommand{\MyCommand}... 宣告替換為前言中的 \DeclareRobustCommand{\MyCommand}...。這對於在擴充套件時會生成寫入到.aux檔案的文字的宏尤其重要。
用於段落和數學模式的新命令
假設您要宣告一些變數,您希望在段落中以及在數學模式中使用它。這可以透過在 Latex2e 中使用 \ensuremath 命令來實現,如下所示
\newcommand{\mysym}{\ensuremath{a^{2}+y^{2}}}
\newcommand 後面的空格
在定義的新命令後出現不一致的空格是一個常見問題。
例如: "動量是使用 p=mv 計算的。" 請注意公式後面沒有空格。
另一方面 "公式 p=mv 計算動量。", 公式後面有空格。
針對此間距問題,可以使用 xspace 包,它會自動決定是否應該在其後新增空格。
\usepackage{xspace}
\newcommand{\restenergy}{\ensuremath{mv}\xspace}
新環境
[edit | edit source]與 \newcommand 命令一樣,有一個命令可以建立您自己的環境。 \newenvironment 命令使用以下語法
\newenvironment{name}[num][default]{before}{after}
|
此外,\newenvironment 可以有一個可選引數。當遇到 \{name} 命令(開始環境)時,在環境中的文字被處理之前,before 引數中指定的材料將被處理。當遇到 \end{name} 命令(結束環境)時,after 引數中的材料將被處理。
可選的 num 和 default 引數的使用方式與 \newcommand 命令相同。LaTeX 確保你不會定義一個已經存在的環境。如果你想更改現有的環境,可以使用 \renewenvironment 命令。它使用與 \newenvironment 命令相同的語法。
下面的示例演示了 \newenvironment 命令的使用。
\newenvironment{king}
{ \rule{1ex}{1ex}\hspace{\stretch{1}} }
{ \hspace{\stretch{1}}\rule{1ex}{1ex} }
\begin{king}
My humble subjects \ldots
\end{king}
|
額外空格
[edit | edit source]在建立新環境時,你可能會很容易地被潛入的額外空格所困擾,這可能會產生致命的影響。一個例子是,當你想要建立一個標題環境,它抑制它自己的縮排以及下一段的縮排。環境的開始塊中的 \ignorespaces 命令將使它忽略執行開始塊後的任何空格。結束塊有點棘手,因為在環境結束時會進行特殊處理。使用 \ignorespacesafterend,LaTeX 將在特殊“結束”處理發生後發出一個 \ignorespaces。
\newenvironment{simple}%
{\noindent}%
{\par\noindent}
\begin{simple}
See the space\\to the left.
\end{simple}
Same\\here.
|
See the space to the left. Same here. |
\newenvironment{correct}%
{\noindent\ignorespaces}%
{\par\noindent%
\ignorespacesafterend}
\begin{correct}
No space\\to the left.
\end{correct}
Same\\here.
|
No space to the left. Same here. |
此外,如果你在使用時仍然遇到在環境末尾附加額外空格的問題\input用於外部資源,確保環境的開頭、資源和結尾之間沒有空格,例如
\begin{correct}\input{somefile.tex}\end{correct}
|
或
\begin{correct}%
\input{somefile.tex}%
\end{correct}
|
在新環境中宣告命令
[edit | edit source]新的命令可以在 newenvironment 中宣告。在 newenvironment 中宣告的命令透過加倍 # 字元來引用它們的 arguments。在下面的示例中,一個新的環境以及一個巢狀的命令被宣告。
\newenvironment{topics}{
\newcommand{\topic}[2]{ \item{##1 / ##2} }
Topics:
\begin{itemize}
}
{
\end{itemize}
}
|
如果錯誤地將傳遞給 \topics 宏的 arguments 定義為單個 # 字元,則會丟擲以下錯誤訊息。
! Illegal parameter number in definition of \topics.
環境內容作為宏引數
[edit | edit source]一些命令(例如 \verb、\textbf 和 \fcolorbox)期望要修改的文字作為引數傳遞,因此不能放在環境定義的“頭部”或“尾部”。在某些情況下,一個解決方法是使用相應的環境,例如 \{verbatim}...\end{verbatim} 用於 \verb。當不存在相應的環境時,另一種選擇是 environ 包,它將環境內容放在區域性宏 \BODY 中。在下面的示例中,makebold 環境將它的內容加粗。
\documentclass{article}
\usepackage{environ}
\NewEnviron{makebold}{\textbf{\BODY}}
\begin{document}
\begin{makebold}
Some bold text.
\end{makebold}
\end{document}
|
擴充套件引數數量
[edit | edit source]xkeyval 包允許你為命令定義鍵值選項。
\mycommand[key1=value1, key3=value3]{some text}
|
這個包相當完整,文件也很詳盡。我們建議包開發者閱讀它。 [1]
讓我們提供一個簡單的例子[1]
\usepackage{xkeyval}
% ...
\makeatletter
\def\my@emphstyle#1{\csname my@style@#1\endcsname}
%% Predefined styles
\providecommand\my@style@default{\em}
\providecommand\my@style@bold{\bfseries}
\define@key{myemph}{code}{%
\def\my@emphstyle{#1}
}
\define@key{myemph}{style}{%
\def\my@emphstyle{\csname my@style@#1\endcsname}
}
\newcommand\setemph[1]{%
\setkeys{myemph}{#1}
}
\renewcommand\emph[1]{%
{\my@emphstyle #1}
}
\makeatother
Something \emph{important}
\setemph{style=bold}
Something \emph{important}
\setemph{code=\Large\sffamily}
Something \emph{important}
|
算術
[edit | edit source]| 一位讀者要求擴充套件此頁面以包含更多內容。 你可以透過新增新材料(瞭解如何)或在閱覽室尋求幫助。 |
LaTeX 可以運算元字。
calc 包提供了常見的 infix 符號。
\usepackage{calc}
% ...
\newcounter{mine}
\setcounter{mine}{2*17}
\themine
|
對於高精度計算,你可以使用 fp[2] 包。
\usepackage{fp}
% Clip
\[
\FPmul\result{2}{7}
\FPclip\result\result
2*7 = \result
\]
% Infix
\[
\newcommand\result{11}
\sqrt{\sin(2+\result)} \approx
\FPeval\result{round(root(2,sin(result + 2.5)),2)}
\result
\]
% Postfix
\[
\FPupn\result{17 2.5 + 17.5 swap - 2 1 + * 2 swap /} % or \FPupn\result{2 17.5 17 2.5 + - 2 1 + * /}
\FPclip\result\result
(17+2.5 - 17.5) * (2+1) / 2 = \result
\]
% High precision
\[
\FPdiv\result{17}{7}
\frac{17}{7} \approx \FPtrunc\result\result{3}
\result
\]
|
條件語句
[edit | edit source]LaTeX 可以使用條件語句,這要歸功於 ifthen 包。
\usepackage{ifthen}
% ...
\ifthenelse{ \equal{\myvar}{true} }{
This is true.
}{
This is false.
}
|
FYI:對於較新的專案,推薦使用 e-TeX[3],它從 etoolbox 中的 LaTeX 可用。請參見其手冊的 3.6 節。
以下是一個簡短的示例,一個每次使用時都會切換狀態的 bool 值。[4]
\documentclass{article}
\usepackage{etoolbox}
\usepackage{parskip}
\usepackage{tikz}
\newbool{volt}
\newcommand{\onoff}{%
\ifbool{volt}{%
\boolfalse{volt}\candleOn\space ON}{%
\booltrue{volt}\candleOff\space OFF}%
}
\newcommand{\candleOff}{\tikz \draw (0,0) rectangle
(.2,.8);}
\newcommand{\candleOn}{\begin{tikzpicture}\draw (0,0) rectangle
(.2,.8);\draw [fill=orange] (.1,.9) circle
[radius=.1];\end{tikzpicture}
}
\begin{document}
\onoff\par
\onoff\par
\onoff\par
\onoff\par
\end{document}
|
迴圈
[edit | edit source]PGF/TikZ 擴充套件提供了 \foreach 命令。
\usepackage{tikz}
% ...
\foreach \i/\q in {wheat/50g, water/1L, yeast/2g}{
\noindent\i\dotfill\q\\
}
|
如果你只使用 \foreach 而不繪製圖形,你可以直接使用 pgffor 包。
或者,你可以檢視 multido 包。
字串
[edit | edit source]xstring 提供了許多功能。來自 CTAN
- 測試字串的內容
- 提取子字串
- 替換子字串
- 字串長度
- 子字串的位置
- 子字串出現的次數
示例
\usepackage{xstring}
% ...
\newcommand\mystr{Hello World!}
The string ``\mystr'' has \StrLen{\mystr}{} characters.
Predicate ``\mystr{} contains the word Hello'' is \IfSubStr{\mystr}{Hello}{true}{false}.
|
LaTeX 鉤子
[edit | edit source]LaTeX 提供了兩個鉤子
\AtBeginDocument允許你指定一組命令,這些命令將在遇到\{document}時執行。\AtEndDocument對\end{document}執行相同的操作。
這為你提供了更多宏的靈活性。它可以用於覆蓋在序言之後執行的設定。這些鉤子可以呼叫多次。這些命令將按照設定的順序執行。
例如,讓我們用 oldstylenums 替換頁碼。
\usepackage{textcomp}
\AtBeginDocument{%
% Make the page numbers in text figures
\let\myThePage\thepage
\renewcommand{\thepage}{ \oldstylenums{\myThePage} }
}
|
還有一些針對類和包的鉤子。請參見建立包。
命令列 LaTeX
[edit | edit source]如果你在類 Unix 作業系統上工作,你可能正在使用 Makefile 或任何型別的指令碼構建你的 LaTeX 專案。在這種情況下,透過使用命令列引數呼叫 LaTeX,生成同一個文件的不同版本可能很有趣。如果你在文件中新增以下結構
\usepackage{ifthen}
%...
% default value.
\providecommand\blackandwhite{false}
%...
\ifthenelse{ \equal{\blackandwhite}{true} }{
% "black and white" mode; do something..
}{
% "color" mode; do something different..
}
|
現在你可以像這樣呼叫 LaTeX
latex '\providecommand{\blackandwhite}{true}\input{test.tex}'
首先定義命令 \blackandwhite,然後使用 input 讀取實際檔案。透過將 \blackandwhite 設定為 false,可以生成文件的彩色版本。
