perlpodspec - 純文字文件:格式規格和注意事項
這份文件是 Pod 標記語言的詳細注意事項。大多數人只要閱讀 perlpod 就能知道如何撰寫 Pod,但這份文件可能會回答一些關於剖析和呈現 Pod 的問題。
在此文件中,「必須」/「不得」、「應」/「不應」和「可」具有其慣例(參閱 RFC 2119)含義:「X 必須執行 Y」表示如果 X 未執行 Y,則違反此規範,且應確實修正。「X 應執行 Y」表示建議執行,但如果理由充分,X 可不執行 Y。「X 可執行 Y」僅表示 X 可隨意執行 Y(儘管由讀者自行判斷「而且我認為如果 X 執行 Y 會很好」與「如果 X 執行 Y,我並不會真的介意」之間的任何含義)。
特別注意,當我說「解析器應執行 Y」時,如果呼叫應用程式明確要求解析器不執行 Y,則解析器可不執行 Y。我經常將此表述為「解析器應在預設情況下執行 Y。」這不要求解析器提供選項以關閉 Y 功能(例如擴充逐字段落中的標籤),儘管它暗示可能會提供此類選項。
Pod 嵌入在檔案中,通常是 Perl 原始檔,儘管您可以撰寫一個檔案,其中僅包含 Pod。
檔案中的列包含零個或多個非換行字元,以換行或檔案結尾為終止符。
換行序列通常是與平台相關的概念,但 Pod 解析器應將其理解為表示 CR(ASCII 13)、LF(ASCII 10)或 CRLF(ASCII 13 後立即接續 ASCII 10),以及任何其他系統特定含義。檔案中的第一個 CR/CRLF/LF 序列可用作識別換行序列的基礎,以解析檔案的其餘部分。
空白列是完全由零個或多個空格(ASCII 32)或標籤(ASCII 9)組成,並以換行或檔案結尾為終止符的列。非空白列是包含一個或多個非空格或標籤字元(並以換行或檔案結尾為終止符)的列。
(注意:許多較舊的 Pod 解析器不接受由空格/標籤然後是換行組成的列作為空白列。它們認為空白的唯一列是完全不包含任何字元,並以換行為終止符的列。)
空白在此文件中用作空格、標籤和換行序列的總稱。(此術語本身通常是指實際的空白。也就是說,Pod 原始檔中的空白字元序列,而不是「E<32>」,後者是一種格式化程式碼,表示空白字元。)
Pod 解析器是一個模組,用於解析 Pod(無論這是否涉及呼叫回呼、建構解析樹或直接格式化它)。Pod 格式器(或Pod 轉譯器)是一個模組或程式,用於將 Pod 轉換為其他格式(HTML、純文字、TeX、PostScript、RTF)。Pod 處理器可能是格式器或轉譯器,或可能是對 Pod 執行其他操作的程式(例如計算字數、掃描索引點等)。
Pod 內容包含在Pod 塊中。Pod 塊以符合 m/\A=[a-zA-Z]/
的行開頭,並持續到符合 m/\A=cut/
的下一行,或在沒有 m/\A=cut/
行的情況下持續到檔案結尾。
請注意,剖析器預期不會區分看起來像 Pod 但在引號字串中的內容,例如 here 文件。
在 Pod 塊中,有Pod 段落。Pod 段落由非空白文字行組成,並以一個或多個空白行分隔。
在 Pod 處理的目的上,Pod 塊中有四種類型的段落
命令段落(也稱為「指令」)。此段落的第一行必須符合 m/\A=[a-zA-Z]/
。命令段落通常為一行,如下所示
=head1 NOTES
=item *
但它們可能跨越多行(非空白行)
=for comment
Hm, I wonder what it would look like if
you tried to write a BNF for Pod from this.
=head3 Dr. Strangelove, or: How I Learned to
Stop Worrying and Love the Bomb
某些命令段落允許在其內容中使用格式化程式碼(即在符合 m/\A=[a-zA-Z]\S*\s*/
的部分之後),如下所示
=head1 Did You Remember to C<use strict;>?
換句話說,「head1」的 Pod 處理處理常式會對「Did You Remember to C<use strict;>?」套用與一般段落相同的處理(即解析並假設適當地格式化「C<...>」等格式化程式碼,且以實際空格和/或 tab 形式存在的空白並不重要)。
逐字段落。此段落的第一行必須是實際空格或 tab,且此段落不得位於 "=begin 識別碼", ... "=end 識別碼" 序列中,除非「識別碼」以冒號 (":") 開頭。也就是說,如果段落以實際空格或 tab 開頭,但位於 "=begin 識別碼", ... "=end 識別碼" 區域中,則為資料段落,除非「識別碼」以冒號開頭。
空白在逐字段落中很重要(儘管在處理過程中,tab 可能會展開)。
一般段落。如果段落的第一行既不符合 m/\A=[a-zA-Z]/
也不符合 m/\A[ \t]/
,且如果段落不位於 "=begin 識別碼", ... "=end 識別碼" 序列中,除非「識別碼」以冒號 (":") 開頭,則此段落為一般段落。
資料段落。這是位於 "=begin 識別碼" ... "=end 識別碼" 序列中的段落,其中「識別碼」不以實際冒號 (":") 開頭。在某種意義上,資料段落根本不是 Pod 的一部分(即實際上是「帶外」的),因為它不受大多數 Pod 解析的約束;但在此處指定,因為 Pod 剖析器需要能夠為其呼叫事件,或以某種形式將其儲存在剖析樹中,或至少僅在其周圍剖析。
例如:考慮下列段落
# <- that's the 0th column
=head1 Foo
Stuff
$foo->bar
=cut
在此,「=head1 Foo」和「=cut」是命令段落,因為每行的第一行都符合 m/\A=[a-zA-Z]/
。「[space][space]$foo->bar」是逐字段落,因為它的第一行以實際空白字元開頭(且周圍沒有 "=begin"..."=end" 區域)。
「=begin 識別碼」...「=end 識別碼」指令會停止解析其所圍繞的段落,不將其解析為一般或逐字段落,但前提是識別碼不能以冒號開頭。這部分會在「關於資料段落和「=begin/=end」區域」章節中詳細討論。
本節旨在補充和說明 perlpod 中的「指令段落」 中的討論。以下是目前已識別的 Pod 指令
此指令表示段落中剩餘文字為標題。該文字可能包含格式化代碼。範例
=head1 Object Attributes
=head3 What B<Not> to Do!
=head5
和 =head6
皆於 2020 年新增,可能並非所有 Pod 解析器都支援。 Pod::Simple 3.41 於 2020 年 10 月釋出,支援這兩者,並提供對所有 Pod::Simple 為基礎的 Pod 解析器的支援。
此指令表示此段落開始一個 Pod 區塊。(如果我們已經在 Pod 區塊中,此指令完全不會產生任何效果。)如果此指令段落中在「=pod」之後有任何文字,都必須忽略。範例
=pod
This is a plain Pod paragraph.
=pod This text is ignored.
此指令表示此行是先前開始的 Pod 區塊的結尾。如果行中在「=cut」之後有任何文字,都必須忽略。範例
=cut
=cut The documentation ends here.
=cut
# This is the first line of program text.
sub foo { # This is the second.
嘗試使用「=cut」指令開始一個 Pod 區塊會產生錯誤。在這種情況下,Pod 處理器必須停止解析輸入檔案,並且預設會發出警告。
此指令表示這是清單/縮排區域的開頭。如果「=over」之後有任何文字,它必須只包含一個非零的正數字。此數字的語意會在後方的「關於 =over...=back 區域」章節中說明。格式化代碼不會展開。範例
=over 3
=over 3.5
=over
此指令表示清單中的項目從這裡開始。格式化代碼會被處理。此段落中剩餘文字(可選)的語意會在後方的「關於 =over...=back 區域」章節中說明。範例
=item
=item *
=item *
=item 14
=item 3.
=item C<< $thing->stuff(I<dodad>) >>
=item For transporting us beyond seas to be tried for pretended
offenses
=item He is at this time transporting large armies of foreign
mercenaries to complete the works of death, desolation and
tyranny, already begun with circumstances of cruelty and perfidy
scarcely paralleled in the most barbarous ages, and totally
unworthy the head of a civilized nation.
此命令表示這是由最近的 "=over" 命令開始的區域的結束。它不允許在 "=back" 命令後有文字。
這將標記後面的段落(直到相對應的 "=end formatname")為某種特殊處理。除非 "formatname" 以冒號開頭,否則包含的非命令段落為資料段落。但如果 "formatname" 確實 以冒號開頭,則非命令段落為一般段落或資料段落。這在「"關於資料段落和 "=begin/=end" 區域"」一節中有詳細說明。
建議 formatname 符合正規表示法 m/\A:?[-a-zA-Z0-9_]+\z/
。formatname 之後空白後面的所有內容都是參數,格式化程式在處理此區域時可能會使用該參數。這個參數不能在 "=end" 段落中重複。實作人員應預期 "=begin"/"=end"/"=for" 的第一個參數的語意和語法未來會擴充。
這標記由相對應的 "=begin formatname" 區域開啟的區域的結束。如果 "formatname" 不是最近開啟的 "=begin formatname" 區域的 formatname,則這是一個錯誤,並且必須產生錯誤訊息。這在「"關於資料段落和 "=begin/=end" 區域"」一節中有詳細說明。
這與下列同義:
=begin formatname
text...
=end formatname
也就是說,它會建立一個由單一段落組成的區域;如果 "formatname" 以冒號開頭,則該段落將被視為一般段落;如果 "formatname" 沒有 以冒號開頭,則 "text..." 將組成一個資料段落。沒有辦法使用 "=for formatname text..." 將 "text..." 表示為逐字段落。
此命令應出現在文件開頭(至少在任何非美國 ASCII 資料之前!),宣告此文件以編碼 encodingname 編碼,它必須是 Encode 辨識的編碼名稱。(Encode::Supported 中 Encode 支援的編碼清單在此很有用。)如果 Pod 解析器無法解碼宣告的編碼,它應發出警告,並可能完全中止解析文件。
有多個 "=encoding" 行的文件應被視為錯誤。如果非第一個 "=encoding" 行只是第一行的重複(例如,如果有一個 "=encoding utf8" 行,之後還有另一個 "=encoding utf8" 行),Pod 處理器可能會靜默容忍此情況。但如果同一個文件中有多個矛盾的 "=encoding" 行,Pod 處理器應提出抱怨(例如,如果文件開頭有一個 "=encoding utf8",之後還有 "=encoding big5")。辨識 BOM 的 Pod 處理器也可能會在看到與 BOM 矛盾的 "=encoding" 行時提出抱怨(例如,如果有一個帶有 UTF-16LE BOM 的文件有一個 "=encoding shiftjis" 行)。
如果 Pod 處理器看到除了上面列出的命令之外的任何命令(例如「=head」、「=haed1」、「=stuff」、「=cuttlefish」或「=w123」),該處理器預設必須將其視為錯誤。它不得處理以該命令開頭的段落,預設必須警告這是錯誤,並且可能會中止解析。Pod 解析器可以允許特定應用程式將上述已知命令清單新增到清單中,並為每個新增命令規定是否應處理格式化代碼。
此規格的未來版本可能會新增其他命令。
(請注意,在此文件和 perlpod 的先前草稿中,格式化代碼稱為「內部序列」,此術語仍可能出現在 Pod 解析器的文件和 Pod 處理器的錯誤訊息中。)
格式化代碼有兩種語法
格式化代碼以大寫字母(僅 US-ASCII [A-Z])開頭,後接「<」,任意數量的字元,並以第一個匹配的「>」結尾。範例
That's what I<you> think!
What's C<CORE::dump()> for?
X<C<chmod> and C<unlink()> Under Different Operating Systems>
格式化代碼以大寫字母(僅 US-ASCII [A-Z])開頭,後接兩個或更多個「<」,一個或多個空白字元,任意數量的字元,一個或多個空白字元,並以第一個匹配的兩個或更多個「>」序列結尾,其中「>」的數量等於此格式化代碼開頭的「<」數量。範例
That's what I<< you >> think!
C<<< open(X, ">>thing.dat") || die $! >>>
B<< $foo->bar(); >>
使用此語法,在「C<<<」和「>>>」(或任何字母)之後的空白字元不會呈示。它們不表示空白,僅是格式化代碼本身的一部分。也就是說,以下所有內容都是同義詞
C<thing>
C<< thing >>
C<< thing >>
C<<< thing >>>
C<<<<
thing
>>>>
依此類推。
最後,多角括號形式不會改變巢狀格式化代碼的詮釋,表示以下四個範例行的意義相同
B<example: C<$a E<lt>=E<gt> $b>>
B<example: C<< $a <=> $b >>>
B<example: C<< $a E<lt>=E<gt> $b >>>
B<<< example: C<< $a E<lt>=E<gt> $b >> >>>
在解析 Pod 時,一個特別棘手的部分是正確解析(可能巢狀的!)格式化代碼。實作者應參閱 Pod::Parser 中的 parse_text
常式中的程式碼,作為正確實作的範例。
I<text>
-- 斜體文字請參閱 perlpod 中的「格式化代碼」 中的簡要討論。
B<text>
-- 粗體文字請參閱 perlpod 中的「格式化代碼」 中的簡要討論。
C<code>
-- 程式碼文字請參閱 perlpod 中的「格式化代碼」 中的簡要討論。
F<filename>
-- 檔案名稱樣式請參閱 perlpod 中的「格式化代碼」 中的簡要討論。
X<topic name>
-- 索引條目請參閱 perlpod 中的「格式化代碼」 中的簡要討論。
此程式碼並不尋常,因為大多數格式器會完全捨棄此程式碼及其內容。其他格式器會以隱藏式程式碼呈現,可用於建立目前文件的索引。
Z<>
-- 空值(無效)格式化程式碼在 perlpod 中的「格式化程式碼」 中簡要討論。
此程式碼並不尋常,因為它不應該有任何內容。也就是說,處理器可能會在看到 Z<potatoes>
時抱怨。無論是否抱怨,都應該忽略 potatoes 文字。
L<name>
-- 超連結此程式碼的複雜語法在 perlpod 中的「格式化程式碼」 中有詳細討論,實作細節則在 關於 L<...> 程式碼 中討論。解析 L<content> 的內容很棘手。特別是,必須檢查內容是否看起來像 URL,或者是否必須按字面上的「|」和/或「/」(順序正確!)進行拆分,等等,在解析 E<...> 程式碼之前。
E<escape>
-- 字元跳脫請參閱 perlpod 中的「格式化程式碼」,以及 實作 Pod 處理器的注意事項 中的幾點。
S<text>
-- 文字包含不換行空白此格式化程式碼在語法上很簡單,但在語意上很複雜。它的意思是此程式碼的可列印內容中的每個空白都表示不換行空白。
考慮
C<$x ? $y : $z>
S<C<$x ? $y : $z>>
兩者都表示由「$x」、「一個空白」、「?」、「一個空白」、「:」、「一個空白」和「$z」組成的等寬(c[ode] 樣式)文字。不同的是,在後者中,使用 S 程式碼,這些空白不是「正常」空白,而是不換行空白。
如果 Pod 處理器看到任何格式化代碼,而這些代碼不在上述清單中(例如「N<...>」或「Q<...>」等),該處理器預設必須將其視為錯誤。Pod 剖析器可以允許特定應用程式將其他已知格式化代碼新增到上述清單中;Pod 剖析器甚至可以允許針對每個額外指令規定是否需要某種特殊處理,例如 L<...> 所需的處理。
此規格的未來版本可能會新增其他格式化代碼。
歷史備註:少數較舊的 Pod 處理器不會將「>」視為「C<」代碼的結尾,如果「>」的前面緊接著一個「-」。這是為了讓此
C<$foo->bar>
剖析為等同於此
C<$foo-E<gt>bar>
而不是等同於只包含「$foo-」的「C」格式化代碼,然後在「C」格式化代碼之外有一個「bar>」。此問題已透過新增類似此類的語法解決
C<< $foo->bar >>
相容的剖析器不得將「->」視為特殊字元。
格式化代碼絕對不能跨越段落。如果一個代碼在一個段落中開啟,而該段落的結尾沒有找到結尾代碼,Pod 剖析器必須關閉該格式化代碼,並應提出抱怨(例如「第 123 行開始的段落中未終止的 I 代碼:『時間物件不是...』」)。因此,這兩個段落
I<I told you not to do this!
Don't make me say it again!>
...不得剖析為兩個斜體段落(I 代碼從一個段落開始,從另一個段落結束)。相反地,第一個段落應產生警告,但除此之外,上述代碼必須剖析為
I<I told you not to do this!>
Don't make me say it again!E<gt>
(在 SGMLish 術語中,所有 Pod 指令都類似區塊層級元素,而所有 Pod 格式化代碼都類似內嵌層級元素。)
以下是與 Pod 處理相關的各種需求和建議的長篇章節。
Pod 格式化程式應容忍逐字區塊中任何長度的行,即使這表示必須中斷這些行(對於非常長的列可能需要中斷多次)以避免文字超出頁面側邊。Pod 格式化程式可能會警告此類換行。此類警告特別適用於長度超過 100 個字元的行,這些行通常不是故意的。
Pod 剖析器必須辨識所有三種已知的換行格式:CR、LF 和 CRLF。請參閱 perlport。
Pod 解析器應接受任何長度的輸入行。
由於 Perl 會辨識檔案開頭的 Unicode 位元組順序標記,表示該檔案以 UTF-16(無論是大端序或小端序)或 UTF-8 編碼,因此 Pod 解析器也應如此。否則,如果檔案中第一個高位元組序列看起來像是有效的 UTF-8 序列,則應將字元編碼理解為 UTF-8,否則為 CP-1252(本規格的早期版本使用 Latin-1 而不是 CP-1252)。
本規格的未來版本可能會說明 Pod 如何接受其他編碼。假設在 Pod 解析中對其他編碼的處理方式與 XML 解析相同:無論特定 Pod 檔案宣告的編碼為何,內容都將以 Unicode 字元儲存在記憶體中。
著名的 Unicode 位元組順序標記如下:如果檔案以兩個文字位元組值 0xFE 0xFF 開頭,這是大端序 UTF-16 的 BOM。如果檔案以兩個文字位元組值 0xFF 0xFE 開頭,這是小端序 UTF-16 的 BOM。在 ASCII 平台上,如果檔案以三個文字位元組值 0xEF 0xBB 0xBF 開頭,這是 UTF-8 的 BOM。一種可移植到 EBCDIC 平台的機制是
my $utf8_bom = "\x{FEFF}";
utf8::encode($utf8_bom);
一種天真的,但通常足夠的啟發法在 ASCII 平台上,用於測試沒有 BOM 的檔案中的第一個高位元組序列(無論是在程式碼中或在 Pod 中!),以查看該序列是否有效作為 UTF-8(RFC 2279)是檢查序列中的第一個位元組是否在範圍 0xC2 - 0xFD 且下一個位元組是否在範圍 0x80 - 0xBF 中。如果是這樣,解析器可以推論這個檔案是 UTF-8,並且檔案中的所有高位元組序列都應假設為 UTF-8。否則,解析器應將檔案視為 CP-1252。(一個更好的檢查,並且在 EBCDIC 平台上也能運作,是將序列的副本傳遞給 utf8::decode(),它會對序列執行完整的有效性檢查,如果它是有效的 UTF-8,則傳回 TRUE,否則傳回 FALSE。此函式總是預先載入,因為它是用 C 編寫的,而且速度很快,而且最多只會呼叫一次,所以您不必因為效能問題而避免它。)在一個不太可能的情況下,一個真正的非 UTF-8 檔案中的第一個高位元組序列碰巧看起來像是 UTF-8,我們可以透過在該行之前加上一個註解行,其中包含一個明顯不是有效 UTF-8 的高位元組序列,來迎合我們的啟發法(以及任何更智慧的啟發法)。僅包含「#」、一個 e-acute 和任何非高位元組位元組的行就足以建立這個檔案的編碼。
Pod 處理器必須將「=for [標籤] [內容...]」段落視為與「=begin [標籤]」段落、內容和「=end [標籤]」段落具有相同意義。(解析器可以合併這兩個結構,或讓它們保持不同,並期望格式化器仍會以相同方式處理它們。)
在將 Pod 呈現為允許註解的格式(即幾乎任何格式,除了純文字以外)時,Pod 格式化器必須插入註解文字,識別其名稱和版本號,以及用於處理 Pod 的任何模組的名稱和版本號。最小範例
%% POD::Pod2PS v3.14159, using POD::Parser v1.92
<!-- Pod::HTML v3.14159, using POD::Parser v1.92 -->
{\doccomm generated by Pod::Tree::RTF 3.14159 using Pod::Tree 1.08}
.\" Pod::Man version 3.14159, using POD::Parser version 1.92
格式化器也可以插入其他註解,包括:Pod 格式化器程式發布日期、格式化器作者的聯絡地址、目前時間、輸入檔案名稱、生效的格式化選項、使用的 Perl 版本等。
除了以其他方式發出錯誤/警告(例如發訊息到 STDERR 或 die
)之外,格式化器也可以選擇將錯誤/警告標記為註解。
Pod 解析器可以發出警告或錯誤訊息(「未知 E 碼 E<zslig>!」)到 STDERR(無論是透過列印到 STDERR,或 warn
ing/carp
ing,或 die
ing/croak
ing),但必須允許抑制所有此類 STDERR 輸出,並允許選擇以其他方式報告錯誤/警告,無論是透過觸發回呼、或在文件物件的某些屬性中標記錯誤,或某些類似的不顯眼機制——甚至附加「Pod 錯誤」區段到文件的已解析表單的結尾。
在文件異常的情況下,Pod 解析器可能會中止解析。即使如此,仍應避免使用 die
ing/croak
ing;如果可能,解析器函式庫可以簡單地關閉輸入檔案,並在(部分)記憶體中文件的結尾新增文字,例如「*** 格式化已中止 ***」。
在了解格式化碼(例如 E<...>、B<...>)的段落中(即不是逐字段落,但包括一般段落,以及產生可呈現文字的命令段落,例如「=head1」),一般應將文字空白視為「不重要」,因為一個文字空白與任何(非零)數量的文字空白、文字換行和文字標籤具有相同的意義(只要這不會產生空白行,因為那些空白行會終止段落)。Pod 解析器應壓縮每個已處理段落中的文字空白,但可以提供一個選項來覆寫此設定(因為某些處理任務不需要它),或可以遵循其他特殊規則(例如,特別處理句點-空白-空白或句點-換行序列)。
Pod 解析器不應預設嘗試將撇號 (') 和引號 (") 轉換為智慧引號(小 9、66、99 等),也不應嘗試將反引號 (`) 轉換為任何東西,除了單個反引號字元(與開啟引號字元不同!),也不應將「--」轉換為任何東西,除了兩個減號。它們絕不應對 C<...> 格式化碼中的文字執行任何這些操作,也絕不應對逐字段落中的文字執行任何這些操作。
在將 Pod 呈現為具有兩種連字號 (-) 的格式時,一種是非斷行連字號,另一種是可斷行連字號(例如「物件導向」,可以跨行拆分為「物件-」,換行,「導向」),鼓勵格式化器通常將「-」轉換為非斷行連字號,但可以套用啟發法將其中一些轉換為可斷行連字號。
Pod 格式化程式應盡力避免將 Perl 程式碼的字詞拆開到不同行。例如,在某些格式化系統中,「Foo::Bar」可能會被拆成「Foo::」換行「Bar」,甚至「Foo::-」換行「Bar」。應盡可能避免這種情況,方法是停用所有字詞中間的換行,或使用「禁止換行」代碼將特定帶有內部標點符號的字詞包起來(在某些格式中,這可能不是單一代碼,而是要在字詞中的每個字元對之間插入不換行的零寬度空白)。
Pod 解析器在處理逐字段落時,應預設將 tab 符號展開,然後再傳遞給格式化程式或其他處理器。解析器也可以允許選項來覆寫此設定。
Pod 解析器在將一般和逐字段落傳遞給格式化程式之前,應預設移除段落結尾的換行符號。例如,雖然您現在正在閱讀的段落,在 Pod 原始碼中可以視為以結尾換行符號結束(且包含該換行符號),但應將其處理為以結束此句點的句號結束(且包含該句號)。
Pod 解析器在報告錯誤時,應盡力報告近似行號(「Thing/Foo.pm 的第 52 段落中有巢狀 E<>,接近第 633 行!」),而不是僅指出段落編號(「Thing/Foo.pm 的第 52 段落中有巢狀 E<>!」)。如果這有問題,則段落編號至少應附上該段落的摘錄(「Thing/Foo.pm 的第 52 段落中有巢狀 E<>,開頭為『C<interest rate> 屬性的讀取/寫入存取器…』」)。
Pod 解析器在處理一系列逐字段落時,應將它們視為一個包含空白行的巨大逐字段落。亦即,這兩行之間有空白行的
use Foo;
print Foo->VERSION
應在傳遞給格式化程式或其他處理器之前,統一成一個段落(「\tuse Foo;\n\n\tprint Foo->VERSION」)。解析器也可以允許選項來覆寫此設定。
雖然這在事件驅動的 Pod 解析器中實作起來可能太過繁瑣,但對於回傳剖析樹的解析器來說卻很簡單。
Pod 格式化程式在可行的情況下,建議避免將短逐字段落(例如少於十二行)拆分到不同頁面。
Pod 解析器必須將僅包含空白和/或標籤的行視為「空白行」,例如分隔段落。(一些較舊的解析器只會將兩個相鄰的新行視為「空白行」,但不會將新行、空白和新行視為空白行。這是不相容的行為。)
Pod 格式化程式/處理器的作者應盡力避免撰寫自己的 Pod 解析器。CPAN 中已經有許多解析器,具有廣泛的介面樣式,其中之一 Pod::Simple 附帶有現代版本的 Perl。
Pod 文件中的字元可以傳達為字面值,或以 E<n> 碼中的數字傳達,或以等效的助記符傳達,例如 E<eacute>,它與 E<233> 完全相同。這些數字是 Latin1/Unicode 值,即使在 EBCDIC 平台上也是如此。
使用 E<n> 數字碼參照字元時,32-126 範圍內的數字是指那些眾所周知的 US-ASCII 字元(Unicode 也在那裡定義,具有相同的意義),所有 Pod 格式化程式都必須忠實地呈現。E<> 數字在 0-31 和 127-159 範圍內的字元不應使用(既不能作為字面值,也不能作為 E<number> 碼),除了換行(ASCII 13、ASCII 13 10 或 ASCII 10)和標籤(ASCII 9)的字面位元組序列。
160-255 範圍內的數字是指 Latin-1 字元(Unicode 也在那裡定義,具有相同的意義)。255 以上的數字應理解為是指 Unicode 字元。
請注意,有些格式化程式無法可靠地呈現 32-126 以外的字元;許多格式化程式能夠處理 32-126 和 160-255,但無法處理 255 以上的字元。
除了眾所周知的「E<lt>」和「E<>>」小於和等於符號碼之外,Pod 解析器還必須理解「E<sol>」表示「/」(實心斜線、斜線)和「E<verbar>」表示「|」(垂直線、管道)。Pod 解析器還應該理解「E<lchevron>」和「E<rchevron>」作為字元 171 和 187 的舊式碼,即「左指向雙角引號」=「左指向引號」和「右指向雙角引號」=「右指向引號」。 (這些看起來像小「<<」和「>>」,現在最好用 HTML/XHTML 碼「E<laquo>」和「E<raquo>」來表示。)
Pod 解析器應理解在 www.W3.org
上最新的 XHTML 規格中實體宣告中定義的所有「E<html>」碼。Pod 解析器必須至少理解定義 160-255(Latin-1)範圍內字元的實體。Pod 解析器在遇到一些未知的「E<identifier>」碼時,不應僅將其替換為空字串(至少預設如此),但可以將其作為由字面字元 E、小於、identifier、大於組成的字串傳遞。或者,Pod 解析器可以提供處理此類未知「E<identifier>」碼的替代選項,方法是觸發特別針對此類碼的事件,或在記憶體中文件樹中新增特殊節點類型。此類「E<identifier>」可能對某些處理器具有特殊意義,或者某些處理器可能會選擇將它們新增到特殊錯誤報告中。
Pod 剖析器也必須支援字元 34(雙引號,")、字元 38(&符號,&)的 XHTML 代碼「E<quot>」和字元 39(單引號,')的「E<apos>」
請注意,在所有「E<whatever>」的情況中,whatever(無論是 htmlname 或任何基底的數字)都只能包含字母數字字元,亦即 whatever 必須符合 m/\A\w+\z/
。因此 "E< 0 1 2 3 >" 無效,因為它包含空格,而空格不是字母數字字元。這大概不需要 Pod 處理器特別處理;" 0 1 2 3 " 看起來不像任何基底的數字,因此大概會在類似 HTML 名稱的表格中查詢。由於沒有(也無法有)稱為 " 0 1 2 3 " 的類似 HTML 實體,因此這將被視為錯誤。不過,Pod 處理器可能會將 "E< 0 1 2 3 >" 或「E<e-acute>」視為語法上無效,可能會產生與僅未知(但理論上有效)htmlname(例如「E<qacute>」[sic])產生的錯誤訊息(或警告或事件)不同的錯誤訊息。不過,Pod 剖析器不需要做出這種區分。
請注意,E<number> 不得解釋為「目前/原生字元集中的碼點number」。它永遠只表示「Unicode 中碼點number 所代表的字元」。(這與 XML 中 &#number; 的語意相同。)
這可能會需要許多格式化程式擁有表格,用於將可處理的 Unicode 碼點(例如 e-acute 字元的「\xE9」)對應到目標輸出格式中傳達此類序列所需的跳脫序列或代碼。例如,轉換為 *roff 的轉換器會知道「\xE9」(無論是直接傳達或透過 E<...> 序列傳達)要傳達為「e\\*'」。類似地,在 Mac OS 應用程式視窗中呈現 Pod 的程式大概需要知道「\xE9」對應到 MacRoman 編碼中的碼點 142,而 MacRoman 編碼(在撰寫本文時)是 Mac OS 的原生編碼。此類 Unicode2whatever 對應大概已經廣泛提供給常見的輸出格式。(此類對應可能不完整!不期望實作人員為了呈現契若基語音節、伊特魯里亞符文、拜占庭音樂符號或 Unicode 能編碼的其他任何奇怪事物而竭盡全力。)而且,如果 Pod 文件使用此類對應中找不到的字元,格式化程式應將其視為無法呈現的字元。
如果 Pod 格式化程式的實作人員意外地找不到從 Unicode 字元對應到目標格式中跳脫的令人滿意的預先存在的表格(例如,從 Unicode 字元到 *roff 跳脫的良好表格),則有必要建立此類表格。如果您處於這種情況,您應該從範圍 0x00A0 - 0x00FF 的字元開始,這大部分是使用頻繁的重音字元。然後(在耐心允許且細心驅使下)繼續處理(X)HTML 標準群組判定為重要到值得為其制定助記符號的字元。這些字元在 www.W3.org 網站上的(X)HTML 規格中宣告。在撰寫本文時(2001 年 9 月),最新的實體宣告檔案為
http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent
http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent
http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent
然後,您可以瀏覽 0x2000-0x204D 範圍內任何其餘的 Unicode 顯著字元(請參閱 www.unicode.org 上的字元表),以及任何其他您感興趣的字元。例如,在 xhtml-symbol.ent 中,有下列條目
<!ENTITY infin "∞"> <!-- infinity, U+221E ISOtech -->
雖然 Pod 解析器(希望)已經處理將「infin」對應到字元「\x{221E}」的對應,但此檔案中出現這個字元表示它相當重要,足以包含在格式化器的表格中,這個表格會將 Unicode 顯著字元對應到用於呈現這些字元的程式碼。因此,例如對於 Unicode 到 *roff 的對應,這將符合下列條目
"\x{221E}" => '\(in',
我們熱切希望未來會有越來越多的格式(和格式化器)直接支援 Unicode 字元(就像 (X)HTML 使用 ∞
、∞
或 ∞
一樣),減少將 Unicode 對應到 my_escapes 的特殊對應需求。
當遇到無法呈現的字元時(這與解析器無法解析為任何內容,無論是否可呈現的未知 E<thing> 序列不同),由個別 Pod 格式化器決定要顯示什麼。將帶有變音符號的拉丁字母(例如「E<eacute>」/「E<233>」)對應到對應的無重音 US-ASCII 字母(例如簡單的字元 101,「e」)是一種良好的做法,但顯然這通常不可行,而且無法呈現的字元可能會表示為「?」或類似的字元。在嘗試合理的折衷方案(例如從 E<233> 到「e」)時,Pod 格式化器可以使用 Pod::Escapes 中的 %Latin1Code_to_fallback 表格,或在有需要時使用 Text::Unidecode。
例如,這段 Pod 文字
magic is enabled if you set C<$Currency> to 'E<euro>'.
可能會呈現為:「如果您將 $Currency
設定為『?』,就會啟用魔法」或「如果您將 $Currency
設定為『[euro]』,就會啟用魔法」,或「如果您將 $Currency
設定為 '[x20AC]',就會啟用魔法」等。
Pod 格式化器也可以在註解或警告中記錄遇到哪些無法呈現的字元。
E<...> 可以自由出現在任何格式化程式碼中(除了出現在另一個 E<...> 或 Z<> 中)。也就是說,「X<The E<euro>1,000,000 Solution>」是有效的,而「L<The E<euro>1,000,000 Solution|Million::Euros>」也是有效的。
有些 Pod 格式器輸出格式會將不換行空白實作為單一字元(我稱之為「NBSP」),而其他格式器輸出的格式會將不換行空白實作為以「不要將此換行」程式碼包覆的空白。請注意,在 Pod 層級,兩種程式碼都可能出現:Pod 可以包含 NBSP 字元(無論是字面值,還是「E<160>」或「E<nbsp>」程式碼);而且 Pod 可以包含「S<foo I<bar> baz>」程式碼,其中此類程式碼中的「單純空白」(字元 32)用來表示不換行空白。Pod 剖析器應考慮支援將「S<foo I<bar> baz>」選用剖析為「fooNBSPI<bar>NBSPbaz」,反之亦然,將以 NBSP 連接的字詞群選用剖析為每個群組都在 S<...> 程式碼中,以便格式器可以使用最符合輸出格式需求的表示方式。
有些處理器可能會發現,最容易實作 S<...>
程式碼的方式是將 S 內容下的剖析樹中每個空白替換為 NBSP。但請注意:替換不應套用於所有文字中的空白,而僅套用於可列印文字中的空白。(此區別在 Pod 剖析器實作的特定樹/事件模型中可能顯而易見,也可能不顯而易見。)例如,考量這個不尋常的案例
S<L</Autoloaded Functions>>
這表示可見連結文字中間的空白不得換行。換句話說,這與下列相同
L<"AutoloadedE<160>Functions"/Autoloaded Functions>
然而,錯誤套用的空白轉 NBSP 替換可能會(錯誤地)產生等同於下列的結果
L<"AutoloadedE<160>Functions"/AutoloadedE<160>Functions>
...這幾乎肯定無法作為超連結(假設此格式器輸出的格式支援超文字)。
格式器可能會選擇僅不支援 S 格式程式碼,特別是在輸出格式根本沒有 NBSP 字元/程式碼,也沒有「不要將此換行」程式碼的情況下。
除了上面討論的 NBSP 字元,實作人員應注意拉丁語系-1 中的其他「特殊」字元,即「軟連字元」,又稱為「可選連字元」,例如 E<173>
= E<0xAD>
= E<shy>
)。此字元表示一個可選的連字元化點。也就是說,它通常不會顯示,但如果格式化程式在該點換行,則可能會顯示為「-」。Pod 格式化程式應視情況執行下列其中一項動作:1) 使用具有相同意義的程式碼顯示此字元(例如,RTF 中的「\-」),2) 傳遞此字元,並預期格式化程式會將此字元視為可選連字元,或 3) 刪除它。
例如
sigE<shy>action
manuE<shy>script
JarkE<shy>ko HieE<shy>taE<shy>nieE<shy>mi
這些字元會傳達給格式化程式,如果要對「sigaction」或「manuscript」進行連字元化,則應將其寫成「sig-[換行]action」或「manu-[換行]script」(如果它沒有進行連字元化,則 E<shy>
根本不會顯示)。如果要對「Jarkko」和/或「Hietaniemi」進行連字元化,則只能在有 E<shy>
程式碼的地方進行。
在實務上,預計此字元不會經常使用,但格式化程式應支援或刪除它。
如果您認為想要在 Pod 中新增一個新指令(例如「=biblio」指令),請考慮是否可以使用 for 或 begin/end 序列來達到相同的效果:=for biblio ... 或 =begin biblio ... =end biblio。不支援「=for biblio」等指令的 Pod 處理器只會忽略它,而如果看到「=biblio」,則可能會發出很大的抱怨。
在本文檔中,「Pod」一直是文件格式名稱的首選拼法。您也可以使用「POD」或「pod」。對於(通常)採用 Pod 格式的文件,您可以使用「pod」、「Pod」或「POD」。了解這些區別很有用;但通常不必過度糾結於拼寫方式。
從 perlpod 中的一瞥,您就可以看出 L<...> 程式碼是 Pod 格式化程式碼中最複雜的。以下幾點希望能釐清它的意義以及處理器應如何處理它。
在剖析 L<...> 程式碼時,Pod 剖析器必須區分至少四個屬性
連結文字。如果沒有,則必須為 undef
。(例如,在「L<Perl 函式|perlfunc>」中,連結文字為「Perl 函式」。在「L<Time::HiRes>」和「L<|Time::HiRes>」中,沒有連結文字。請注意,連結文字可能包含格式化。)
可能推論出的連結文字;亦即,如果沒有實際的連結文字,則這是我們將推論出的文字來取代它。(例如,對於「L<Getopt::Std>」,推論出的連結文字為「Getopt::Std」。)
名稱或 URL,或 undef
(如果沒有)。(例如,在「L<Perl 函式|perlfunc>」中,名稱(有時也稱為頁面)為「perlfunc」。在「L</CAVEATS>」中,名稱為 undef
。)
區段(在較舊的 perlpod 中又稱為「項目」),或 undef
(如果沒有)。例如,在「L<Getopt::Std/DESCRIPTION>」中,「DESCRIPTION」是區段。(請注意,這與手冊頁區段不同,例如「man 5 crontab」中的「5」。Pod 意義中的「區段 Foo」表示由標題或項目引導的文字部分,其文字為「Foo」。)
Pod 剖析器也可能注意到其他屬性,包括
一個標記,表示項目 3(如果存在)是一個 URL(例如「http://lists.perl.org」),在這種情況下不應有區段屬性;一個 Pod 名稱(例如「perldoc」和「Getopt::Std」);或可能是一個手冊頁名稱(例如「crontab(5)」)。
原始的 L<...> 內容,在文字以「|」、「/」等分割,以及 E<...> 程式碼展開之前。
(上述僅編號以供下方簡潔參考。並不要求將這些作為實際清單或陣列傳遞。)
例如
L<Foo::Bar>
=> undef, # link text
"Foo::Bar", # possibly inferred link text
"Foo::Bar", # name
undef, # section
'pod', # what sort of link
"Foo::Bar" # original content
L<Perlport's section on NL's|perlport/Newlines>
=> "Perlport's section on NL's", # link text
"Perlport's section on NL's", # possibly inferred link text
"perlport", # name
"Newlines", # section
'pod', # what sort of link
"Perlport's section on NL's|perlport/Newlines"
# original content
L<perlport/Newlines>
=> undef, # link text
'"Newlines" in perlport', # possibly inferred link text
"perlport", # name
"Newlines", # section
'pod', # what sort of link
"perlport/Newlines" # original content
L<crontab(5)/"DESCRIPTION">
=> undef, # link text
'"DESCRIPTION" in crontab(5)', # possibly inferred link text
"crontab(5)", # name
"DESCRIPTION", # section
'man', # what sort of link
'crontab(5)/"DESCRIPTION"' # original content
L</Object Attributes>
=> undef, # link text
'"Object Attributes"', # possibly inferred link text
undef, # name
"Object Attributes", # section
'pod', # what sort of link
"/Object Attributes" # original content
L<https://www.perl.org/>
=> undef, # link text
"https://www.perl.org/", # possibly inferred link text
"https://www.perl.org/", # name
undef, # section
'url', # what sort of link
"https://www.perl.org/" # original content
L<Perl.org|https://www.perl.org/>
=> "Perl.org", # link text
"https://www.perl.org/", # possibly inferred link text
"https://www.perl.org/", # name
undef, # section
'url', # what sort of link
"Perl.org|https://www.perl.org/" # original content
請注意,您可以透過它們符合 m/\A\w+:[^:\s]\S*\z/
的事實,來區分 URL 連結和任何其他內容。因此,L<http://www.perl.com>
是 URL,但 L<HTTP::Response>
不是。
對於沒有「文字|」部分的 L<...> 代碼,舊格式化程式在實際顯示連結或交叉參照時表現出很大的差異。例如,L<crontab(5)> 會呈現為「crontab(5)
手冊頁」,或「在 crontab(5)
手冊頁中」,或僅為「crontab(5)
」。
Pod 處理器現在必須將「文字|」較少的連結視為以下內容
L<name> => L<name|name>
L</section> => L<"section"|/section>
L<name/section> => L<"section" in name|name/section>
請注意,章節名稱可能包含標記。即,如果章節以
=head2 About the C<-M> Operator
或
=item About the C<-M> Operator
開頭,則連結到它的外觀如下
L<somedoc/About the C<-M> Operator>
格式化程式可能會選擇忽略標記,以解析連結,並僅使用章節名稱中的可呈現字元,如下所示
<h1><a name="About_the_-M_Operator">About the <code>-M</code>
Operator</h1>
...
<a href="somedoc#About_the_-M_Operator">About the <code>-M</code>
Operator" in somedoc</a>
先前版本的 perlpod 區分 L<name/"section">
連結和 L<name/item>
連結(及其目標)。這些在目前的規格中已在語法和語義上合併,而 section 可以指「=headn 標題內容」命令或「=item 項目內容」命令。此規格未指定在給定文件中有數個項目都看似產生相同 section 識別碼(例如,在 HTML 中,數個項目都產生相同的 anchorname,在 <a name="anchorname">...</a> 元素中)的情況下應有的行為。Pod 處理器能夠控制此行為時,應使用第一個此類錨點。亦即,L<Foo/Bar>
指的是 Foo 中的第一個「Bar」章節。
但對於某些處理器/格式,這無法輕易控制;就像 HTML 範例一樣,多個模糊的 <a name="anchorname">...</a> 的行為最容易留給瀏覽器決定。
在 L<text|...>
代碼中,文字可能包含用於格式化或 E<...> 轉譯的格式化代碼,如下所示
L<B<ummE<234>stuff>|...>
對於沒有「名稱|」部分的 L<...>
代碼,只能出現 E<...>
和 Z<>
代碼。亦即,作者不應使用「L<B<Foo::Bar>>
」。
但請注意,格式化代碼和 Z<> 可以出現在 L<...> 的任何和所有部分(即在 名稱、章節、文字和 網址 中)。
作者不得巢狀 L<...> 代碼。例如,「L<The L<Foo::Bar> man page>」應視為錯誤。
請注意,Pod 作者可以在「L<text|name>」(以及 L<text|/"sec">)的「文字」部分中使用格式化代碼。
換句話說,這是有效的
Go read L<the docs on C<$.>|perlvar/"$.">
有些輸出格式允許將「L<...>」代碼渲染為超連結,但可能不允許格式化連結文字;在這種情況下,格式化程式必須忽略該格式化。
在撰寫本文時,L<name>
值有兩種型態:一種是 Pod 頁面的名稱,例如 L<Foo::Bar>
(可能是 @INC / PATH 目錄中的實際 Perl 模組或程式,或是這些位置中的 .pod 檔案);另一種是 Unix 手冊頁面的名稱,例如 L<crontab(5)>
。理論上,L<chmod>
在稱為「chmod」的 Pod 頁面或 Unix 手冊頁面「chmod」(在任何手冊章節中)之間是模稜兩可的。但是,括號中的字串(例如「crontab(5)」)足以表示正在討論的不是 Pod 頁面,因此可能是 Unix 手冊頁面。對於許多 Pod 處理器來說,此區別並不重要,但某些渲染為超文字格式的處理器可能需要區分它們,才能知道如何渲染給定的 L<foo>
代碼。
先前版本的 perlpod 允許使用 L<section>
語法(例如 L<Object Attributes>
),這不容易與 L<name>
語法區分,且與 L<"section">
語法區分也不容易。此語法不再包含在規格中,並已由 L</section>
語法取代(其中斜線以前是可選的)。Pod 剖析器應至少在一段時間內容忍 L<"section">
語法。區分 L<section>
與 L<name>
的建議啟發式方法是,如果它包含任何空白,則它是一個區段。Pod 處理器應警告此為不建議使用的語法。
「=over」...「=back」區域用於各種類型的清單結構。(我這裡使用術語「區域」僅作為從「=over」到匹配的「=back」的所有內容的集合術語。)
「=over 縮排層級」...「=back」中的非零數字縮排層級用於提供格式化程式一個提示,說明它應該跳過多少「空格」(em 或大致等效的單位),儘管許多格式化程式必須將此轉換為絕對測量值,該測量值可能與文件基本字體中的空格(或 M)的大小不完全匹配。其他格式化程式可能必須完全忽略此數字。沒有任何明確的縮排層級參數等於縮排層級值 4。如果存在縮排層級但不是與 m/\A(\d*\.)?\d+\z/
匹配的正數,Pod 處理器可能會抱怨。
提醒 Pod 格式化程式作者,「=over」...「=back」可能會對應到輸出格式中的幾個不同結構。例如,在將 Pod 轉換為 (X)HTML 時,它可以對應到 <ul>...</ul>、<ol>...</ol>、<dl>...</dl> 或 <blockquote>...</blockquote>。類似地,「=item」可以對應到 <li> 或 <dt>。
每個「=over」...「=back」區塊應為下列其中之一
包含只有「=item *」指令的「=over」...「=back」區塊,每個指令後接一些一般/逐字段落、其他巢狀「=over」...「=back」區塊、「=for...」段落和「=begin」...「=end」區塊。
(Pod 處理器必須容忍空白的「=item」,就像它是「=item *」一樣。)「*」是否呈現為文字星號、「o」或某種實際項目符號,取決於 Pod 格式化程式,且可能取決於巢狀層級。
包含只有 m/\A=item\s+\d+\.?\s*\z/
段落的「=over」...「=back」區塊,每個段落(或每組段落)後接一些一般/逐字段落、其他巢狀「=over」...「=back」區塊、「=for...」段落和/或「=begin」...「=end」程式碼。請注意,每個區段中的數字必須從 1 開始,且必須按順序進行,不得跳過數字。
(Pod 處理器必須容忍像「=item 1」這樣的行,就像它們是「=item 1.」一樣,帶有句點。)
包含只有「=item [文字]」指令的「=over」...「=back」區塊,每個指令(或每組指令)後接一些一般/逐字段落、其他巢狀「=over」...「=back」區塊或「=for...」段落和「=begin」...「=end」區塊。
「=item [文字]」段落不應符合 m/\A=item\s+\d+\.?\s*\z/
或 m/\A=item\s+\*\s*\z/
,也不應僅符合 m/\A=item\s*\z/
。
不包含任何「=item」段落的「=over」...「=back」區塊,且僅包含一些一般/逐字段落,以及可能也包含一些巢狀「=over」...「=back」區塊、「=for...」段落和「=begin」...「=end」區塊。Pod 中這種沒有項目的「=over」...「=back」區塊在意義上等同於 HTML 中的「<blockquote>...</blockquote>」元素。
請注意,對於上述所有情況,您可以透過檢查「=over」指令後的第 1 個(非「=cut」、非「=pod」)Pod 段落,來確定您擁有的「=over」...「=back」類型。
Pod 格式化程式必須容忍「=item 文字...」段落中任意大量的文字。實際上,大多數此類段落都很短,例如
=item For cutting off our trade with all parts of the world
但它們可能會任意長
=item For transporting us beyond seas to be tried for pretended
offenses
=item He is at this time transporting large armies of foreign
mercenaries to complete the works of death, desolation and
tyranny, already begun with circumstances of cruelty and perfidy
scarcely paralleled in the most barbarous ages, and totally
unworthy the head of a civilized nation.
Pod 處理器應容忍沒有附帶段落的「=item *」/「=item 數字」指令。中間的項目是一個範例
=over
=item 1
Pick up dry cleaning.
=item 2
=item 3
Stop by the store. Get Abba Zabas, Stoli, and cheap lawn chairs.
=back
沒有「=over」...「=back」區塊可以包含標題。處理器可能會將此類標題視為錯誤。
請注意,「=over」...「=back」區塊應有一些內容。也就是說,作者不應有像這樣的空區塊
=over
=back
看到這種沒有內容的「=over」...「=back」區塊的 Pod 處理器可能會忽略它,或可能會將它報告為錯誤。
處理器必須容忍文件結尾處的「=over」清單(即沒有對應的「=back」),但可能會對此類清單發出警告。
Pod 格式化程式作者應注意此結構
=item Neque
=item Porro
=item Quisquam Est
Qui dolorem ipsum quia dolor sit amet, consectetur, adipisci
velit, sed quia non numquam eius modi tempora incidunt ut
labore et dolore magnam aliquam quaerat voluptatem.
=item Ut Enim
在語意上是模稜兩可的,這使得格式化決策有點困難。一方面,它可能是提到一個項目「Neque」、提到另一個項目「Porro」,以及提到另一個項目「Quisquam Est」,而只有最後一個需要說明段落「Qui dolorem ipsum quia dolor...」;然後是項目「Ut Enim」。在這種情況下,您會希望以這種方式格式化它
Neque
Porro
Quisquam Est
Qui dolorem ipsum quia dolor sit amet, consectetur, adipisci
velit, sed quia non numquam eius modi tempora incidunt ut
labore et dolore magnam aliquam quaerat voluptatem.
Ut Enim
但它同樣可能是對三個(相關或等效)項目「Neque」、「Porro」和「Quisquam Est」的討論,後面跟著一個解釋它們的段落,然後是一個新項目「Ut Enim」。在這種情況下,您可能希望以這種方式格式化它
Neque
Porro
Quisquam Est
Qui dolorem ipsum quia dolor sit amet, consectetur, adipisci
velit, sed quia non numquam eius modi tempora incidunt ut
labore et dolore magnam aliquam quaerat voluptatem.
Ut Enim
但(在可預見的未來),Pod 沒有提供任何方法讓 Pod 作者區分上述「=item」群集結構所指的哪個群組。因此,格式化程式應以這種方式格式化它
Neque
Porro
Quisquam Est
Qui dolorem ipsum quia dolor sit amet, consectetur, adipisci
velit, sed quia non numquam eius modi tempora incidunt ut
labore et dolore magnam aliquam quaerat voluptatem.
Ut Enim
也就是說,項目之間的間距(至少大致上)應與段落之間的間距相等(儘管該間距可能遠小於一行文字的完整高度)。這讓讀者可以利用(上下文)線索來找出「Qui dolorem ipsum...」段落適用於「Quisquam Est」項目還是所有三個項目「Neque」、「Porro」和「Quisquam Est」。雖然這不是理想的情況,但這比提供可能實際上與作者意圖相反的格式化提示要好。
資料段落通常用於內嵌非 Pod 資料,這些資料將在將文件呈現為特定格式時使用(通常是傳遞)。
=begin rtf
\par{\pard\qr\sa4500{\i Printed\~\chdate\~\chtime}\par}
=end rtf
順便一提,使用單一「=for」段落也可以達到完全相同的效果
=for rtf \par{\pard\qr\sa4500{\i Printed\~\chdate\~\chtime}\par}
(儘管它在形式上不是資料段落,但它與資料段落具有相同的含義,Pod 解析器可能會將其解析為資料段落。)
資料段落的另一個範例
=begin html
I like <em>PIE</em>!
<hr>Especially pecan pie!
=end html
如果這些是一般的段落,Pod 解析器會嘗試將「E</em>」(在第一個段落)擴充為格式化代碼,就像「E<lt>」或「E<eacute>」。但由於這是在「=begin 識別碼」...「=end 識別碼」區域而且識別碼「html」前面沒有「:」前綴,因此此區域的內容會儲存為資料段落,而不是當成一般段落處理(或如果它們以空格和/或標籤開頭,則當成逐字段落處理)。
再舉一個例子:在撰寫本文時,不支援「biblio」識別碼,但假設撰寫了一些處理器來辨識它,作為(例如)表示書目參考(在一般段落中一定包含格式化代碼)的方式。表示「biblio」段落是要用一般處理方式處理的事實,會透過在每個「biblio」識別碼前面加上冒號來表示
=begin :biblio
Wirth, Niklaus. 1976. I<Algorithms + Data Structures =
Programs.> Prentice-Hall, Englewood Cliffs, NJ.
=end :biblio
這會向解析器發出訊號,表示此 begin...end 區域中的段落會以一般/逐字段落的方式進行一般處理(同時仍標記為僅供了解「biblio」識別碼的處理器使用)。使用下列方式也能產生相同的結果
=for :biblio
Wirth, Niklaus. 1976. I<Algorithms + Data Structures =
Programs.> Prentice-Hall, Englewood Cliffs, NJ.
這些識別碼上的「:」表示「即使結果會是針對某些特殊目標,也要正常處理這些內容」。我建議解析器 API 將「biblio」報告為目標識別碼,但也要報告它有一個「:」前綴。(類似地,對於上述「html」,將「html」報告為目標識別碼,並注意沒有「:」前綴。)
請注意,識別碼以冒號開頭的「=begin 識別碼」...「=end 識別碼」區域可以包含命令。例如
=begin :biblio
Wirth's classic is available in several editions, including:
=for comment
hm, check abebooks.com for how much used copies cost.
=over
=item
Wirth, Niklaus. 1975. I<Algorithmen und Datenstrukturen.>
Teubner, Stuttgart. [Yes, it's in German.]
=item
Wirth, Niklaus. 1976. I<Algorithms + Data Structures =
Programs.> Prentice-Hall, Englewood Cliffs, NJ.
=back
=end :biblio
不過,請注意,識別碼不以冒號開頭的「=begin 識別碼」...「=end 識別碼」區域不應直接包含「=head1」...「=head4」命令,也不應包含「=over」、「=back」或「=item」。例如,這可能會被視為無效
=begin somedata
This is a data paragraph.
=head1 Don't do this!
This is a data paragraph too.
=end somedata
Pod 處理器可能會發出訊號,表示上述(特別是「=head1」段落)有錯誤。不過,請注意,下列不應被視為錯誤
=begin somedata
This is a data paragraph.
=cut
# Yup, this isn't Pod anymore.
sub excl { (rand() > .5) ? "hoo!" : "hah!" }
=pod
This is a data paragraph too.
=end somedata
這也是有效的
=begin someformat
This is a data paragraph.
And this is a data paragraph.
=begin someotherformat
This is a data paragraph too.
And this is a data paragraph too.
=begin :yetanotherformat
=head2 This is a command paragraph!
This is an ordinary paragraph!
And this is a verbatim paragraph!
=end :yetanotherformat
=end someotherformat
Another data paragraph!
=end someformat
上述「=begin :yetanotherformat」...「=end :yetanotherformat」區域的內容不是資料段落,因為立即包含的區域的識別碼(「:yetanotherformat」)以冒號開頭。實際上,大多數包含資料段落的區域只會包含資料段落;不過,上述巢狀結構在 Pod 中是語法上有效的,即使它很罕見。但是,某些格式的處理常式(例如「html」)只會接受資料段落,不接受巢狀區域;如果它們看到(針對它們)的巢狀區域或命令(「=end」、「=pod」和「=cut」除外),它們可能會抱怨。
也可以考慮這個有效的結構
=begin :biblio
Wirth's classic is available in several editions, including:
=over
=item
Wirth, Niklaus. 1975. I<Algorithmen und Datenstrukturen.>
Teubner, Stuttgart. [Yes, it's in German.]
=item
Wirth, Niklaus. 1976. I<Algorithms + Data Structures =
Programs.> Prentice-Hall, Englewood Cliffs, NJ.
=back
Buy buy buy!
=begin html
<img src='wirth_spokesmodeling_book.png'>
<hr>
=end html
Now now now!
=end :biblio
在那裡,「=begin html」...「=end html」區域嵌套在較大的「=begin :biblio」...「=end :biblio」區域內。請注意,「=begin html」...「=end html」區域的內容是資料段落,因為緊鄰的區域識別碼(「html」)不會以冒號開頭。
Pod 剖析器在處理一系列資料段落時(在單一區域內),應將它們視為一個大型資料段落,其中包含空白行。因此,上述「=begin html」...「=end html」的內容可能會儲存為兩個資料段落(一個包含「<img src='wirth_spokesmodeling_book.png'>\n」,另一個包含「<hr>\n」),但應儲存為單一資料段落(包含「<img src='wirth_spokesmodeling_book.png'>\n\n<hr>\n」)。
Pod 處理器應容忍空的「=begin something」...「=end something」區域、空的「=begin :something」...「=end :something」區域,以及沒有內容的「=for something」和「=for :something」段落。也就是說,應容忍以下內容
=for html
=begin html
=end html
=begin :biblio
=end :biblio
順帶一提,請注意,沒有簡單的方法可以表達以類似指令開頭的資料段落。請考慮
=begin stuff
=shazbot
=end stuff
在那裡,「=shazbot」將被剖析為 Pod 指令「shazbot」,而不是資料段落「=shazbot\n」。但是,您可以使用此程式碼表達包含「=shazbot\n」的資料段落
=for stuff =shazbot
需要這樣做的情況可能相當罕見。
請注意,=end 指令必須與目前開啟的 =begin 指令相符。也就是說,它們必須正確嵌套。例如,這是有效的
=begin outer
X
=begin inner
Y
=end inner
Z
=end outer
而這是無效的
=begin outer
X
=begin inner
Y
=end outer
Z
=end inner
後者無效,因為當看到「=end outer」指令時,目前開啟的區域格式名稱為「inner」,而不是「outer」。(只是「outer」碰巧是較高層級區域的格式名稱。)這是錯誤的。處理器預設必須將此報告為錯誤,並可能停止處理包含該錯誤的文件。這項推論是,區域不能「重疊」。也就是說,上述後者區塊並未表示包含 X 和 Y 的「outer」區域,重疊包含 Y 和 Z 的「inner」區域。但由於它是無效的(所有明顯重疊的區域都會是無效的),因此它並不表示這個,或任何東西。
類似地,這是無效的
=begin thing
=end hting
這是錯誤的,因為該區域是由「thing」開啟,而「=end」嘗試關閉「hting」[原文如此]。
這也是無效的
=begin thing
=end
這是無效的,因為每個「=end」指令都必須有格式名稱參數。
perlpod、perlsyn 中的「POD:內嵌文件」、podchecker
Sean M. Burke