> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-tw/lei-bie-dang/03-writing-your-own-package.md).

# 撰寫你自己的套件

有時候，在文件中使用自己定義的命令和巨集，最好的做法就是從零開始撰寫一個新套件。本文說明新套件的主要結構。

## 簡介

在撰寫新套件之前，首先要做的是判斷你是否真的需要一個新套件。建議先 [在 CTAN（Comprehensive TeX Archive Network，綜合 TeX 檔案網路）上搜尋](http://www.ctan.org/ctan-portal/search/) 看看是否已經有人建立了類似你所需要的東西。

另一件需要記住的重要事項是 [套件與類別之間的差異](/latex/zh-tw/lei-bie-dang/01-understanding-packages-and-class-files.md)。做出錯誤的選擇可能會影響最終成品的彈性。

## 整體結構

所有套件檔案的結構大致可分為以下四個部分：

* ***識別***。此檔案宣告自身為以 LaTeX2ε 語法撰寫的套件。
* ***前置宣告***。在這裡會載入所需的外部套件。此外，檔案的這一部分也會撰寫已宣告選項所需的命令與定義。
* ***選項***。套件會宣告並處理這些選項。
* ***更多宣告***。套件的主要內容。套件幾乎所有功能都在這裡定義。

在接下來的小節中，將會更詳細地說明其結構，並提供一個可運作的範例， *examplepackage.sty*，將會呈現。

### 識別

所有套件都必須具有兩個簡單的命令：

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{examplepackage}[2014/08/24 範例 LaTeX 套件]
```

命令 `\NeedsTeXFormat{LaTeX2e}` 設定套件運作所需的 LaTeX 版本。此外，也可以在方括號中加入日期，以指定所需的最早發行日期。

命令 `ProvidesPackage{examplepackage}[...]` 將此套件識別為 *examplepackage* 而且方括號內包含了發行日期與一些額外資訊。日期格式應為 YYYY/MM/DD

[在 Overleaf 中開啟撰寫套件的範例](https://www.sharelatex.com/project/new/template?zipUrl=/project/53f11ec1eceb82a67658cb02/download/zip\&templateName=PackageExample\&compiler=pdflatex)

### 前置宣告

大多數套件會擴充並自訂既有套件，且也需要一些外部套件才能運作。以下將在範例套件 "examplepackage.sty" 中加入更多程式碼。

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{examplepackage}[2014/08/21 範例套件]

\RequirePackage{imakeidx}
\RequirePackage{xstring}
\RequirePackage{xcolor}
\definecolor{greycolour}{HTML}{525252}
\definecolor{sharelatexcolour}{HTML}{882B21}
\definecolor{mybluecolour}{HTML}{394773}
\newcommand{\wordcolour}{greycolour}
```

這一部分的命令不是初始化之後用來管理選項的一些參數，就是載入外部檔案。

命令 `\RequirePackage` 與廣為人知的 `\usepackage`相當類似，在方括號中加入可選參數也可以。唯一的差別在於 `\usepackage` 不能在 `\documentclass` 命令之前使用。強烈建議在撰寫新套件或類別時使用 `\RequirePackage` 。

[在 Overleaf 中開啟撰寫套件的範例](https://www.sharelatex.com/project/new/template?zipUrl=/project/53f11ec1eceb82a67658cb02/download/zip\&templateName=PackageExample\&compiler=pdflatex)

### 選項

為了讓套件更具彈性，額外的一些選項非常有用。檔案 "examplepackage.sty" 的下一部分會處理傳遞給套件載入語句的參數。

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{examplepackage}[2014/08/21 範例套件]

\RequirePackage{imakeidx}
\RequirePackage{xstring}
\RequirePackage{xcolor}
\definecolor{greycolour}{HTML}{525252}
\definecolor{sharelatexcolour}{HTML}{882B21}
\definecolor{mybluecolour}{HTML}{394773}
\newcommand{\wordcolour}{greycolour}

\DeclareOption{red}{\renewcommand{\wordcolour}{sharelatexcolour}}
\DeclareOption{blue}{\renewcommand{\wordcolour}{mybluecolour}}
\DeclareOption*{\PackageWarning{examplepackage}{未知的 ‘\CurrentOption’}}
\ProcessOptions\relax
```

以下將說明可處理傳遞給套件之選項的主要命令。

命令 `\DeclareOption{}{}` 會處理指定的選項。它接受兩個參數，第一個是選項名稱，第二個是在傳入該選項時要執行的程式碼。

命令 `\OptionNotUsed` 會在編譯器與日誌中輸出訊息，而該選項不會被使用。

命令 `\Declareoption*{}` 會處理所有未明確定義的選項。它只接受一個參數，也就是在傳入未知選項時要執行的程式碼。在這種情況下，它會透過下一個命令印出警告：

`\PackageWarning{}{}`。請參閱 [錯誤處理](#handling-errors) 以了解此命令的功能說明。

`\CurrentOption` 會儲存在特定時刻正在處理的套件選項名稱。

命令 `\ProcessOptions\relax` 會對每個選項執行程式碼，且必須放在所有選項處理命令之後。此命令還有一個帶星號的版本，會依照呼叫命令所指定的確切順序執行各選項。

在範例中，如果選項 *red* 或 *blue* 被傳遞給 `\usepackage` 文件中的命令，則命令 `\wordcolor` 會被重新定義。這兩種顏色以及預設的灰色都已在 [前置宣告](#preliminary-declaration) 在載入 *xcolor* 套件。

[在 Overleaf 中開啟撰寫套件的範例](https://www.sharelatex.com/project/new/template?zipUrl=/project/53f11ec1eceb82a67658cb02/download/zip\&templateName=PackageExample\&compiler=pdflatex)

### 更多宣告

在這一部分，大多數命令都會出現。在「examplepackage.sty」中如下所示。以下可見完整的套件檔案。

```latex
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{examplepackage}[2014/08/21 範例套件]

\RequirePackage{imakeidx}
\RequirePackage{xstring}
\RequirePackage{xcolor}
\definecolor{greycolour}{HTML}{525252}
\definecolor{sharelatexcolour}{HTML}{882B21}
\definecolor{mybluecolour}{HTML}{394773}
\newcommand{\wordcolour}{greycolour}

\DeclareOption{red}{\renewcommand{\wordcolour}{sharelatexcolour}}
\DeclareOption{blue}{\renewcommand{\wordcolour}{mybluecolour}}
\DeclareOption*{\PackageWarning{examplepackage}{未知的 ‘\CurrentOption’}}
\ProcessOptions\relax

%%編號環境
\newcounter{example}[section]
\newenvironment{example}[1][]{\refstepcounter{example}\par\medskip
\noindent \textbf{我的~環境~\theexample. #1} \rmfamily}{\medskip}

%%重要字詞會加入索引並以不同顏色印出
\newcommand{\important}[1]
{\IfSubStr{#1}{!}
    {\textcolor{\wordcolour}{\textbf{\StrBefore{#1}{!}~\StrBehind{#1}{!}}}\index{#1}}
    {\textcolor{\wordcolour}{\textbf{#1}}\index{#1}\kern-1pt}
}
```

此套件定義了新的環境 `範例`，以及一個新命令 `\important`，會以特殊顏色印出字詞並將其加入索引。

若要完整了解每個命令，請參閱 [參考指南](#reference-guide) 以及 [延伸閱讀章節中的連結](#further-reading).

以下是一份使用該套件的文件 *examplepackage.sty*.

```latex
\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage[red]{examplepackage}

\makeindex

\title{套件範例}
\author{Learn ShareLaTeX 團隊}
\date{ }

\begin{document}

\maketitle

\section{簡介}
在這份文件中測試了一個新套件。此套件允許特殊的編號
環境

\begin{example}
這段文字位於特殊環境中，部分粗體文字會被印出
在開頭，並且設定新的縮排。
\end{example}

另外，還有一個針對 \important{重要!字詞} 的特殊命令，它會是
根據在下列項目中使用的參數，以特殊的 \important{顏色} 印出
\important{套件} 載入語句中。因為它很 \important{重要}。

\printindex

\end{document}
```

![WrittingPackagesEx1.png](/files/a6432ccc2d5e8ddfd30b540c911ac72d3da08b2f)

請注意命令

```latex
\usepackage[red]{examplepackage}
```

[在 Overleaf 中開啟撰寫套件的範例](https://www.sharelatex.com/project/new/template?zipUrl=/project/53f11ec1eceb82a67658cb02/download/zip\&templateName=PackageExample\&compiler=pdflatex)

## 錯誤處理

在開發新套件時，處理可能發生的錯誤非常重要，這樣才能讓使用者知道出了問題。編譯器中有四個主要命令可用來回報錯誤。

* `\PackageError{*package-name*}{*error-text*}{*help-text*}`。它接受三個參數，每個都放在大括號內：套件名稱、將會顯示的錯誤文字（編譯過程會暫停），以及當使用者因錯誤而使編譯暫停時按下「h」所會印出的說明文字。
* `\PackageWarning{*package-name*}{*warning-text*}`。在這種情況下，文字會顯示出來，但編譯過程不會停止。它會顯示警告發生的行號。
* `\PackageWarningNoLine{*package-name*}{*warning-text*}`。其作用與前一個命令相同，但不會顯示警告發生的行號。
* `\PackageInfo{*package-name*}{*info-text*}`。在這種情況下，第二個參數中的資訊只會印在 transcript 檔案中，並包含行號。

[在 Overleaf 中開啟撰寫套件的範例](https://www.sharelatex.com/project/new/template?zipUrl=/project/53f11ec1eceb82a67658cb02/download/zip\&templateName=PackageExample\&compiler=pdflatex)

## 參考指南

**套件與類別中常用命令列表**

* `\newcommand{*name*}{*definition*}`。定義一個 [新命令](/latex/zh-tw/zhi-ling/01-commands.md#defining-a-new-command)，第一個參數是新命令的名稱，第二個參數是命令將執行的內容。
* `\renewcommand{}{}`。與 `\newcommand` 相同，但會覆寫既有命令。
* `\providecommand{}{}`。作用與 `\newcommand` 相同，但如果該命令已經定義，則會靜默忽略此命令。
* `\CheckCommand{}{}`。語法與 `\newcommand`相同，但它會檢查命令是否存在且是否具有預期的定義；如果該命令不是 `\CheckCommand` 所預期的。
* `\setlength{}{}`。將第一個參數所傳入元素的長度設為第二個參數所寫的值。
* `\mbox{}`。建立一個包含大括號內所寫元素的方框。
* `\fbox{}`。與 `\mbox`，但會在內容外實際印出一個方框。

## 延伸閱讀

更多資訊請參見

* [了解套件與類別檔](/latex/zh-tw/lei-bie-dang/01-understanding-packages-and-class-files.md)
* [撰寫你自己的 class](/latex/zh-tw/lei-bie-dang/04-writing-your-own-class.md)
* [命令](/latex/zh-tw/zhi-ling/01-commands.md) 和 [環境](/latex/zh-tw/zhi-ling/02-environments.md)
* [LaTeX 中的長度](/latex/zh-tw/ge-shi-hua/01-lengths-in-latex.md)
* [在 LaTeX 中使用顏色](/latex/zh-tw/ge-shi-hua/13-using-colors-in-latex.md)
* [大型專案中的管理](/latex/zh-tw/wen-jian-jie-gou/07-management-in-a-large-project.md)
* [供套件與套件撰寫者使用的 LaTeX2ε](http://www.latex-project.org/guides/clsguide.pdf)
* [TeX 程式設計筆記](http://pgfplots.sourceforge.net/TeX-programming-notes.pdf)
* [分鐘少於小時：使用 LaTeX 資源](https://tug.org/pracjourn/2005-4/hefferon/hefferon.pdf)
* [《The LaTeX Companion》第二版](http://ptgmedia.pearsoncmg.com/images/9780201362992/samplepages/0201362996.pdf)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-tw/lei-bie-dang/03-writing-your-own-package.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
