前言

我們之前已經把最主要的部分說的差不多了,上一篇結尾已經開始說一些細枝末節的東西了。這一篇我們繼續說 LaTeX 很重要的一部分,但是如果你只是想做一個普通用戶,拿模板來直接用的話,你大不用費神讀這一部分了,不過你如果想自己寫模板,或者在寫論文時自動化處理一些操作的話,這一節還是有點意思的。

不過我這里要說一件很重要的事,就是 LaTeX 的語法是非常多的,除非專攻 LaTeX 的人,否則幾乎不可能把各種命令都搞清楚。我之前說的那些只能幫助你理解大部分模板的原理,要對他有更深入的理解的話,讀別人的模板絕對是相當有效的學習手段。尤其是你可以發現好多有用的包。同時,TeX StackExchange 絕對是解決你問題絕佳的網站。

說了這么多廢話,我們還是進入正題吧,我們這次主要講 LaTeX 中,值與命令的定義。附帶一些 listings 包的配置分享。

值與命令

調用格式

其實在不同的宏包中,作者可能會自己定義命令的調用方式(參見listings),不過這些就不是我們關心的內容了,我們這里只說最簡單的情景。一個典型的 LaTeX 命令可以有一個可選參數,和 n(n>=0)個必選參數。調用一個命令的典型操作是這樣的:

\afunction[optional]{compulsory1}{compulsory2}

方括號指代可選參數,花括號指代必選參數。當然,方括號內既然是可選參數,你完全可以不提供,就像這樣:

\afunction{compulsory1}{compulsory2}

值定義

命令的使用自然是很簡單的,定義就稍微復雜一些了。我們先說值的定義,用 \newcommand 這個命令就可以:

\documentclass{article} 
\newcommand{\name}{Towdium the Stupid}
 \begin{document} This guy call himself \name . 
\end{document}

編譯結果:

This guy call himself Towdium the Stupid.

命令定義

命令定義就稍微復雜一點。我們這里現設定一個情景吧。我們平時插入獨立的公式有兩種方法,第一種是通過環境:

\begin{equation}
  \mathcal{L}_t{f}=\int^\infty _0 e^{-st}f(t)dt
  \label{eq}
\end{equation}

第二種是用美元符號:

你也許對于這種設定有點糾結:第一種語法很繁瑣,第二種不能使用內文引用(label)。所以我們有沒有辦法建立一種語法簡潔的公式插入格式,同時又支持內文引用呢?這時候你就可以參考下面給出的文檔。當然,最好的方法是自己拿去編譯一下。

\documentclass{article}
\usepackage{ifthen, amsmath}
\newcommand{\eq}[2][]{
  \ifthenelse{\equal{#1}{}}{ %
    \begin{equation*} #2 \end{equation*} %
  }{ %
    \begin{equation} #2 \label{#1} \end{equation} %
  }
}
\begin{document}
Now you can create an equation with inline cite like equation \ref{eq}.
\eq[eq]{\mathcal{L}_t{f}=\int^\infty _0 e^{-st}f(t)dt}
But you can also use it for normal equations:
\eq{\mathcal{L}_t{f}=\int^\infty _0 e^{-st}f(t)dt}
All super easy!
\end{document}

我知道有心編譯的人畢竟是少的,所以,我這里給出結果:

這樣我們便成功地解決了問題,語法簡單,并且同時支持含引用和不含引用的內容。當然你可能一頭霧水,我們就來解釋一下這一段代碼。主要內容在第四行開始,其余部分均是非常普通的語法。這里我們新建了一個命令為 \eq。第一個方括號我們聲明這個命令有兩個參數,第二個方括號是可選參數的默認值,后面則是命令體了。

后面的 if 判斷來自于 ifthen 宏包。大致相當于:

if #1 == '': 
\begin{equation*} #2 \end{equation*}
 else: 
 \begin{equation} #2 \label{#1} \end{equation}

這里 #1 指代第一個參數,即可選參數,默認值為空。#2 指代第二個參數,也就是實際的公式內容。LaTeX 中,命令的參數從1開始編號,如果有可選參數,則可選參數為1,必選參數后移;如果沒有可選參數,則必選參數從1開始計數。這里命令的內容是:如果可選參數為空,即不需要內文引用,則執行前一種不帶序號的格式;如果提供了引用的 label,則執行后一種帶 label 聲明的格式。

你可能注意到了里邊有幾行末尾有迷之 %。這是因為定義的內容會被原封不動的替換到原來文本的位置上,這里行末有換行符,調用之后可能就會造成多余的換行。在行尾加上 % 之后相當于把這個換行符給注釋掉了,也就自然不會有多出的換行符了。

文件導入

說完命令定義之后,可以看到定義命令確實給我們提供了一些便利,但是在導言部分多出了一大坨命令定義,可以說是非常讓人難受了。我們自然有辦法解決這種問題,方法就是使用文件導入。類似于 C 語言的 #inclide。我們可以這樣搞

\documentclass{article}
\usepackage{ifthen, amsmath, filecontents} 

\begin{filecontents}{header.tex} 
\newcommand{\name}{Towdium the Stupid}
 \end{filecontents} 
\input{header} 
\begin{document}
 This guy call himself \name .
 \end{document}

帶你折騰 listings

介紹了文件導入之后,你就可以開始折騰自己的配置文件了,不管是什么模板,只要在需要時導入相關內容,就可以獲得各種預先定義的特性。我平時用的模板也在 教程第二篇 的末尾給出了,需要的話可以自取。當然我并不可能把可以折騰的東西說的面面俱到,我這里只說 listings 的折騰內容,大概展示一下可以達到什么效果。有工夫的話,不妨編譯一下下面這一段代碼。其中我使用了大量的自定義格式,代碼渲染終于可以有所改觀了。

\documentclass{article}
\usepackage{color, listings}
\definecolor{mygray}{rgb}{0.5,0.5,0.4}
\definecolor{mygreen}{rgb}{0,0.7,0.5}
\definecolor{myorange}{rgb}{1.0,0.4,0}
\definecolor{mylilas}{rgb}{0.8,0.3,1.0}
\lstdefinestyle{mybase} {
breaklines=true,
showstringspaces=false,
basicstyle=\small\tt,
frame=single,
xleftmargin=20pt,
xrightmargin=20pt,
  numbersep=9pt,
  numberstyle={\color{black} \footnotesize \sf},
  stringstyle=\color{myorange},
  keywordstyle=\color{mygreen},
  commentstyle=\color{mygray}\ttfamily
}
\lstdefinestyle{mycpp} {
  style=mybase,
  language=C++
}
\lstdefinestyle{myjava} {
  style=mybase,
  language=java
}
\lstdefinestyle{myahdl} {
  style=mybase,
  language = ahdl,
  keywordstyle=\color{mylilas},
  commentstyle=\color{mygreen}
}
\lstdefinelanguage{ahdl}{
  morekeywords={
    AND, ASSERT, BEGIN, BIDIR, BiTS, BURIED,
    CASE, CLIQUE, CONNECTED_PINS, CONSTANT,
    DEFAULTS, DEFINE, DESIGN, DEVICE, DIV,
    ELSE, ELSEIF, END, FOR, FUNCTION,
    GENERATE, GND, HELP_ID,
    IF, INCLUDE, INPUT, IS, LOG2,
    MACHINE, MOD, NAND, NODE, NOR, NOT,
    OF, OPTIONS, OR, OTHERS, OUTPUT,
    PARAMETERS, REPORT, RETURNS,
    SEGMENTS, SEVERITY, STATES, SUBDESIGN,
    TABLE, THEN, TITLE, TO, TRI_STATE_NODE,
    VARIABLE, VCC, WHEN, WITH, XNOR, XOR,
    CARRY, CASCADE, CEIL, DFFE, DFF,
    EXP, FLOOR, GLOBAL, JEFFE, JKFF,
    LATCH, LCELL, MCELL, MEMORY, OPNDRN,
    SOFT, SRFFE, SRFF, TFFE, TFF, TRI,
    WIRE, X
  },
  sensitive=false,
  morecomment=[l]{--},
  morecomment=[s]{\%}{\%},
  tabsize = 4
}
\begin{document}
\begin{lstlisting}[style = mycpp]
/* Hello World in cpp */
#include<stdio.h>
main()
{
  printf("Hello World");
}
\end{lstlisting}
\begin{lstlisting}[style = myjava]
// Hello World in java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}
\end{lstlisting}
\begin{lstlisting}[style = myahdl]
SUBDESIGN dec_count
(
enc, ent, clk:INPUT;
clear:INPUT;
value[3..0]:OUTPUT;
rco:OUTPUT

抱歉這段代碼有點長,只是為了展示更多內容。你可以看到這里我們自己定義了 C++,Java 的語法高亮,甚至添加了 AHDL 的支持,并自定義了高亮。你可能沒有聽說過 AHDL,這并不重要,你只要當他是某門快要消失的語言就好了。編譯結果如下:

這里 \lstdefinestyle 用于自定義自己的格式,\lstdefinelanguage 用于定義新的語言。其余的我也就不多作解釋了,如果你有這方面的需要,網上可以找到很多相關的資料。或者你可以刪減定義中的某些項,觀察其中的影響。我這里只是給出一個具體的例子,展示一下 LaTeX 的自定義程度。

選自 http://www.towdium.me/2017/09/02/latex-for-beginners-4/