週末讀到 par 這個小巧指令,用於文字段落(paragraph)的格式化,例如在 Vim 裡面用 :'<,'>!par 把選取區內特定格式的段落重排。

看看 Descripton 裡的範例 Par 1.52 - paragraph reformatter 便能大概瞭解其用途。
有趣的是說明文件 par.doc,以我水平實在難懂,好像不屬這世界的寫法;如做智力測驗題目的兒時記憶,讓我半夜對著螢幕靜靜傻笑。

以上樂趣分享,以下簡易筆記(私用性質,請小心誤導


par 轉換大略過程 (how it works)

  1. Text

  2. 根據換行字元拆成 lines

                    line
    Text     =>     line
                    line
                      ⋮
  3. 將 lines 分為幾組 segment

    會找出 protected line(開頭字元符合 protected 字,具體哪些字可另外設定)或 blank line(僅含空白、Tab 等字的行)——這兩種行將直接輸出而不會轉換;而剩下來一段段的 lines 就是 segment。
    line (protected)
    line                        segment 1
    line                        segment 1
    line                 =>     segment 1 (3 lines)
    line (blank)
    line                        segment 2
    line                        segment 2 (n lines)
      ⋮                               ⋮
  4. 將 segment 內容(lines)分為幾組 block

    會找出 bodiless line(內容不是真的本文,例如 /*** ... ****/)和 superfluous line(冗行:整行空白、或既 bodiless 且中間重複字元全為空白)。
    bodiless line - 根據選項(repeat)調整輸出方式,
    superfluous line - 根據選項(expel)可能不輸出。
    segment line                         (只有一行應該不算 block?但仍會在後續步驟處理)
    segment line (bodiless)               
    segment line                 =>       block 1
    segment line                          block 1
    segment line (superfluous)
    segment line                          block 2
          ⋮
  5. 將 block 分為幾組 IP (Input paragraph)

    若選項(div)沒開,一個 block 就是一個 IP
  6. 對每個 IP 中的 lines,拿掉 <prefix>, <suffix>,剩下的字重排

    /* PREFIX WORD, WORD SUFFIX */
    /* PREFIX WORD SUFFIX */
    /* PREFIX WORD. WORD WORD SUFFIX */
                  ↓
    WORD, WORD
    WORD
    WORD. WORD WORD
                  ↓
    WORD, WORD WORD 
    WORD. WORD WORD
  7. 把 <prefix>, <suffix> 插回去

實際上根據選項,過程中各種細節都會影響輸出,不過這邊就沒研究了。


par 使用小抄 (how-to-use-it)

此為上課順手記,不是實戰用的。

par 59f         f (fit) 盡可能保持原寬度(59 字)
par 59l         l (last) 盡可能讓最後一行與其它行同寬
par 59t0        t0 (touch 0) 輸出寬固定為 59
par 59j         j (just) text justified
par 59h3        h (hang) 分開前 3 行與之後行的 prefix, suffix 計算
par 59p         p (prefix) 保證每行的前 59 字和 Input 相同
par 59d         d (div) 每行依照 comprelen+1 個字是否為空格,切割為不同 IP
par 59r         r (repeat, r 不給參數則為 3) 變更 bodiless line 定義,repeat 字元 3 次以上也算為 bodiless(原本只有空白才算)
                r 不為 0 時,會使 repeat 字元最多調整到 59
par 59e         e (expel) 不輸出 superfluous line
par 59q         q (quote) 於不同級的引用插入 vacant line
par 59i         i (invis) 不輸出 quote 插入的 vacant line
par 59g         g (guess) 判斷相連的 curious word, capitalized word 如何連接(例:Dr. Jon 分行時被當作一個字)
par 59gc        c (cap) 所有的詞皆視為 capitalized word
par Q+:+ q      將 "+ " 也視為引用字元(加入 PARQUOTE)再執行 q