Swift GYB 簡易教程
來自: http://swift.gg/2016/03/04/a-short-swift-gyb-tutorial/
GYB(模板生成) 是一個 Swift 內部使用的工具 ,可以用模板生成源文件。
如果你有多個結構體/類/枚舉在共享同一個通用的結構,并且你不想維護那些相同的代碼,就可以用 GYB。如果你經常需要給不同的對象寫一些相似的方法或者屬性,那你的維護工作(由于粗心的復制/粘貼導致的錯誤)就可以全部交給 GYB。這個工具在 Swift 代碼庫 中廣泛使用,很容易就可以將它應用到你的項目中。
作為一個勤奮的荷蘭豬(校對注:原文 guinea-pig,也可譯為豚鼠)(據我所知,目前唯一使用 GYB 的項目是 Swift-JNI ,該項目是安卓的 Swift 移植項目的一部分)我在一個用于簡化 Swift 位運算的庫 Bitter 中廣泛使用了 GYB,在這個庫里我寫了很多相似的代碼來擴展固定長度的 Swift 整型變量。
有了這個工具,我就不需要手工輸入所有代碼。我只需定義一個模板,就可以用 GYB 工具創建十個擴展。
讓我們來看看如何使用 GYB。
GYB 引擎元素
使用 GYB 模板引擎相當簡單,但是需要一點 Python 知識。模板是由這些元素組成:
-
用 Python 來控制語句流,每行代碼由 % 開始(空格會被忽略),如你所想,每行代碼也由 % 結束,語句可以嵌套。
-
不以 % 開頭的語句被視為文本,會被直接輸出。
-
${VARIABLE_NAME}形式的元素會被 VARIABLE__NAME 的值替換。
-
字符 % 和 $ 分別用 %% 和 $$ 表示。
-
Python 代碼塊可以添加到模板中,用 %{ 和 }% 括起來,代碼塊外的縮進會被剝離,使你的 Python 代碼不會受到影響。
讓我們用這幾個簡單的規則來做一個例子,拿 Bitter 的模板 來說,用 allOne 為所有固定長度的整形變量添加一個計算屬性,就會返回一個由帶有 allOne 的位模式初始化后得到的整型變量/無符號整形變量:
%{ intTypes = [8,16,32,64] }% % for intType in intTypes: % for sign in ['','U']: /// Extension that adds a few additional functionalities to ${sign}Int${intType} extension ${sign}Int${intType} { /// Returns a ${sign}Int${intType} with all ones %if sign == '': public static var allOnes:Int${intType}{return Int${intType}(bitPattern: UInt${intType}.max)} %else: public static var allOnes:UInt${intType}{return UInt${intType}.max} %end } %end %end
</div>
有了 Python 代碼塊,我們就可以在 Swift 中建立一個固定長度整型數組,然后遍歷它并使用內部循環來處理有符號和無符號整數。然后,我們可以根據 符號 變量的值輸出兩個不同的代碼片段。如果標識變量為空(有符號整數)就輸出第一個代碼段,如果不為空(無符號整數),就輸出第二個代碼段。
在這個例子中,我們用到了簡單的 if/else 語句和 foreach 語句,我們也可以使用一切在 Python 中合法的語句,比如 elif 或者 for 的變體。
執行 GYB,會得到 8 個擴展,對應到每一個固定長度整型變量,范圍從 Int8/Uint8 到 Int64/Uint64。
生成源代碼
你可以從 Swift 倉庫下載 GYB:
wget https://github.com/apple/swift/raw/master/utils/gyb wget https://github.com/apple/swift/raw/master/utils/gyb.py chmod +x gyb
</div>
通過如下方式解析模板:
./gyb --line-directive '' -o ../Sources/Bitter/Bitter.swift Bitter.swift.gyb
</div>
-o 選項指定輸出文件,最后一個文件名指定包含模板的文件的名稱。
若 --line-directive '' 參數為缺省,GYB 輸出會增加調試信息,在原始模板中每一部分的輸出描述元素會被執行。
當你在調試自己寫的模板時,調試信息會很有用。一旦模板完成之后,可以禁用調試的注釋,讓輸出清爽一些。
要評論?在 推ter 上戳我。
本文由 SwiftGG 翻譯組翻譯,已經獲得作者翻譯授權,最新文章請訪問http://swift.gg。