精華區beta PttNewhand 關於我們 聯絡資訊
作者: piaip (piaip) 看板: BBSLua 標題: [文件] BBS-Lua 規格與 API 說明文件 時間: Sun Jan 6 21:52:29 2008 ===================================================================== Interface: 0.119 本文件最後更新時間: 2008/01/25 20:00 最新版本請至 PTT2 BBSLua 板取得 本文件為推廣說明用,轉錄不需通知原作者 (推文會被不定期刪除,請見諒) 但由於 BBS-Lua 目前變動非常頻繁,建議您附上原出處方便閱讀者取得最新版 ===================================================================== 提醒您: BBS-Lua 系統還在初期開發中,所有的架構/API 都隨時可能大改! 請有您現在的作品可能忽然就跑不動的心理準備。 BBS-Lua 是在 BBS 裡面跑程式語言的機制,選用的程式語言是 Wow UI 所使用的 Lua。 關於此程式語言請見 http://www.lua.org/pil/ http://www.lua.org/manual/5.1/manual.html 這份文件說明了如何在 BBS 上使用 Lua (也就是 BBS-Lua 計畫), 以及目前可使用的 API 相關說明。 2008 Jan, piaip ===================================================================== ● BBS-Lua 的格式 BBS-Lua 的程式使用一般文章發文即可。 程式碼要用特殊的標籤前後標起來。 這個標籤寫成: (須在行首,前面不可有空白) --#BBSLUA 讓我們來看個最簡單的範例吧: --#BBSLUA print("Hello, world") --#BBSLUA 這就是一個最簡單的 BBS-Lua 程式。 執行它的方法,目前是在閱讀文章時按下 L 鍵(大小寫皆可)。 另外, 緊接著 --#BBSLUA 的下一行可以給定版本及作者資訊, (中間不可有空行) 稱之為 TOC Tag。 格式為: -- Name: Value TOC 可由 BBS-Lua 中使用 toc.xxx 來存取,同時也可以讓 BBS-Lua 系統警告 是否有相容性的問題。 目前支援的 TOC Tag 有: -- Interface: BBS-Lua API 版本號碼 (可方便系統警示不相容的訊息) -- Title: 程式名稱 -- Notes: 程式說明 -- Author: 作者資訊 -- Version: 程式自訂的版號 -- Date: 最後修改日期 -- LatestRef: 最新版的位置 (格式為: #AID Board 站名或任意字串/註解) Interface 的號碼,請填上您開發時參考的文件編號 (見本文開頭) Title 是有點特殊的欄位,BBS-Lua 系統會盡量把同樣 Title 的程式 視為同一系列不同版本的程式。這會影響到 LatestRef 與某些輸出入 API 的行為。 LatestRef 是個很特殊的 Tag。 若希望別人執行您的程式時一律執行到最新版的, 就加上這個 Tag,填上您最新版程式的 AID 與看板。 以後您只要修改這份 最新版的文章,所有之前轉錄的人執行時都會自動切換為執行 AID 指定的新版。 (注意: 如果 Ref 隱板,則只有能看到該隱板的人才能執行到最新板) 另外要注意的是,使用 LatestRef 時新舊兩邊檔案的 LatestRef 欄與 Title 欄 要完全相等。 這是為了避免因轉信造成的誤認現象。 (LatestRef 在不支援 AID 系統的 BBS 將無作用,請把它當成備案而非必需品) 下面是一個完整的範例: --#BBSLUA -- Interface: 0.119 -- Title: 貪食蛇 -- Notes: 在 BBS 上玩貪食蛇, Ctrl-C 可中斷 -- Author: Hung-Te Lin <[email protected]> -- Version: 0.1 -- Date: 2008/01/09 -- LatestRef: #17WE60Ag BBSLua ptt2.cc print("hello, world"); --#BBSLUA 建議您平時最少加上 Interface/Title 資訊,其它則是可加可不加: --#BBSLUA -- Interface: 0.119 -- Title: BBS-Lua 範例 print("hello, world."); --#BBSLUA ===================================================================== ● 版權/智財權/著作權的保護與使用授權 由於 BBS-Lua 與文章結合的本質,所有的 BBS-Lua 程式碼都是可見的。 你可以參考別人的程式來改善自己的程式;但請注意這不代表作者放棄對 該程式的版權/智財權/著作權。 我們鼓勵所有的創作者在程式碼內宣告自己想使用的授權,也希望所有的 使用者能尊重創作者的權利。 當然我們更歡迎創作者們使用各種開放源碼 (Open Source) 的授權, 如: GPL/LGPL http://www.gnu.org/licenses/ BSD License http://www.opensource.org/licenses/bsd-license.php MIT License http://www.opensource.org/licenses/mit-license.php 原始的 Lua 使用的就是 MIT License。 其它更多資訊可參考 www.opensource.org (英) 或 www.openfoundry.org (中文)。 若想使用非程式專屬的授權方式,還可以參考 Createive Commons [創用CC] http://creativecommons.org.tw/ 。 授權的放置位置,可以跟 Toc 混在一起,如 -- License: MIT License 也可以隨你高興放在文章的顯眼之處。 ===================================================================== ● 開發與除錯 雖然在 BBS 上編輯、測試除錯是很有趣的事情,不過寫起大程式總不太方便。 UNIX 的使用者,可以直接抓 source 回去編譯 BBS-Lua (BBS-Lua 目前 source 放在 PTT 的 source 裡,請見 http://ptt.cc) Windows 的使用者,我們提供了 Win32 模擬器,請由下列網址取得最新版: http://ntu.csie.org/~piaip/bbslua/bbslua.exe (注意: 此網址未來可能會改變) 使用方法是把你的 BBSLua 程式(純文字檔) 拉到此模擬器檔案上即可執行 或是在命令列打入 bbslua filename ===================================================================== ● BBS-Lua 與標準 Lua 異同之處 目前的 BBS-Lua 使用的是標準 Lua 5.1,除了下列不同: - print() 被轉換為 BBS 輸出 - os library 無法使用 - io library 無法使用 - debug library 無法使用 - package library 無法使用 - dofile / loadfile 無法使用 (但 load/loadstring 可使用) - 可使用 math library - 可使用 string library - 可使用 table library - 可使用 bitlib ( http://luaforge.net/projects/bitlib ) ===================================================================== ● API 說明 目前 BBS-Lua 提供的專屬輸出入功能有: [輸出] bbs.addstr(str, ...) 畫字到目前位置 bbs.outs(str, ...) 畫字到目前位置 (同 addstr) bbs.title(str) 移至左上角繪製標題 bbs.print(str, ...) 印完所印字串後再加上一個換行 (bbs.outs(str,...,"\n")) print(str, ...) 同 bbs.print * 全系列畫字函式都可以接受 ANSI 指令 * 注意: 輸出並不會立刻反應在畫面上,要等 refresh() 或其它輸入函式才會作全螢幕的更新。請見 refresh()說明 * 若已有鍵盤輸入則在輸入處理完前可能不會更新螢幕顯示 [移動] bbs.getyx() 傳回游標目前位置 (y, x), y/x 由 (0,0)表左上角 bbs.getmaxyx() 傳回目前螢幕大小 (my,mx), 實際可移動範圍到(my-1,mx-1) bbs.move(y,x) 移動到 (y,x) (也就是 ANSI 的 *[x;yH) bbs.moverel(dy,dx) 移動到游標目前位置加上 (dy,dx) 的位移量 [清除] bbs.clear() 清除整個畫面+回到左上角 bbs.clrtoeol() 清至行尾 bbs.clrtobot() 清至螢幕底端 [2D繪圖] bbs.rect(r,c,title) 以目前游標位置為起點,用目前色彩屬性繪製一個 高度 r (row) 寬度 c (cols) 的視窗。 若有指定 title (可省略) 則會置中輸出字串 [更新畫面] bbs.refresh() 呼叫此命令時才會真的更新畫面 (呼叫輸入等待指令如 getch/getstr/pause/kbhit/sleep 時也會自動更新) 另外注意: 0.110 前為了加速輸出,在使用者已有輸入資料且 程式尚未處理時, refresh() 完全不會更新輸出。 0.110 後,一般輸入指令的自動更新在輸入資料未處理完時 不會更新畫面,但 refresh() 會強制更新。 註: 由於這關乎總輸出資料量,我們不保證未來會維持這個行為 或許哪天就會改回有輸入資料未處理完前不更新輸出。 [顏色、屬性與 ANSI 控制碼] bbs.color(c1,c2,...) 直接切換 ANSI 屬性 (也就是 *[c1;..m,不用再 bbs.outs()) 不指定參數時 bbs.color() = bbs.outs("*[m") (重設屬性) bbs.setattr(c1,c2,...) 同 color() bbs.ANSI_COLOR(c1,...) 傳回 ANSI 屬性字串 (不馬上變屬性,要配合 outs 才會變) bbs.ANSI_RESET 傳回 "*[m" 字串 bbs.ESC 傳回 ANSI 的 Escape (*: ASCII 27, 0x1b) bbs.strip_ansi(s) 傳回無 ANSI 碼的 s 字串 [輸入] bbs.getch() 輸入單鍵 (會等到有輸入為止) 特殊按鍵為大寫名: UP DOWN LEFT RIGHT ENTER BS TAB HOME END INS DEL PGUP PGDN F1 ... F12 另外與 Ctrl 合按的複合鍵會以 ^X 的形式出現。 注意: 某些連線程式常會為「偵測全形字」多送按鍵 會導致收方向鍵時重複 2 次按鍵 要避免這個問題的解決方法是呼叫 getch() 前確認游標 位置不在雙位元字的第一個 Byte 上面 (Leading Byte)。 另外若游標位置為非雙位元字,前面那個字也不能是雙位元。 記得更新前把游標擺在連續的非雙位元字或是 雙位元字的第二個 byte 上面。 另外的方法就是關閉連線軟體端的偵測, 改回讓伺服器端偵測才是王道 bbs.getdata(n,echo,str) 畫 n 個字元的輸入框並輸入字串 echo (可省略) = 0 時只輸入不畫字 (可作密碼輸入) str (可省略) 為預設已輸入字串 bbs.getstr(n,echo,str) 同 getdata bbs.pause(msg) 在底部畫暫停訊息並等輸入單鍵 (傳回值同 getch()) msg 可省略 (會顯示標準暫停訊息) [輸入緩衝區控制] 注意所有緩衝區控制指令等待時間都可能會有最小值 此最小值會因站台設定而不同 bbs.kbhit(wait) 傳回使用者是否有按鍵 (若無輸入則會等待最多 wait 秒) wait 可省略 bbs.kbreset() 清空輸入緩衝區 (吃掉所有已輸入的鍵) bbs.kball(sec) 等待 sec(可省略) 秒,並傳回所有已輸入的鍵 (可用 {bbs.kball()} 轉換成表格以供處理) 適合 framerate 固定,又會同時輸入多個鍵的程式使用 範例: a = {bbs.kball(0.5)}; -- 處理所有鍵 for i=1,#a do ... a[i] ... end b = bbs.kball(0.5); -- 只處理第一個鍵 if bbs.kball(0.5) then ... end -- 只判斷有無按鍵 [時間] bbs.time() 現在時間 (以數字表示),精準度到秒 (呼叫處理速度較快) bbs.now() 同 time() bbs.ctime() 現在時間 (以字串表示) bbs.clock() 高精準度的時間 (可到秒的小數點以下但呼叫處理速度較慢) bbs.sleep(sec) 停止執行 sec 秒 (可到小數點以下) [BBS 資訊] bbs.userid 目前使用者的 id (0.119 後改為變數而非函式) bbs.usernick 目前使用者的暱稱 (0.119+) bbs.sitename BBS 站名 bbs.interface BBS-Lua API 版本號碼 [程式 TOC 資訊] toc.interface TOC 中的 Interface: 資訊 toc.title TOC 中的 Title: 資訊 toc.notes TOC 中的 Notes: 資訊 toc.author TOC 中的 Author: 資訊 toc.version TOC 中的 Version: 資訊 toc.date TOC 中的 Date: 資訊 toc.latestref TOC 中的 LatestRef: 資訊 [位元操作 (bitlib) ] bit.cast(a) cast a to the internally-used integer type bit.bnot(a) returns the one's complement of a bit.band(w1, ...) returns the bitwise and of the w's bit.bor(w1, ...) returns the bitwise or of the w's bit.bxor(w1, ...) returns the bitwise exclusive or of the w's bit.lshift(a, b) returns a shifted left b places bit.rshift(a, b) returns a shifted logically right b places bit.arshift(a, b) returns a shifted arithmetically right b places [資料儲存與讀取] (尚未上線!) store.load(c) 回傳分類 c 內已儲存的資料 (若失敗或無資料則回傳 nil) store.save(c,s) 儲存 s 的內容到分類 c (超過 limit 的部份不會存入, 傳回值為 true/false 代表是否有成功存入。) store.limit(c) 回傳分類 c 的大小限制 store.iolimit() 回傳資料存取 API (load/save) 的呼叫次數限制 store.USER 分類: 使用者目錄 store.GLOBAL 分類: 全站共享 資料的存取牽涉到非常多的安全問題。 所以 BBS-Lua 只開放上面的 API, 讓每個 BBS-Lua 程式都可以存取一小塊專屬於它的資料。 這個資料會以檔案的形式存在 BBS 站內,但請注意各 BBS 站會不定期的 清掉過久無人存取的檔案。 換言之,請把這些檔案當成暫存檔。 你可以利用這些檔案來製作排行榜、即時資訊交流,但請別把重要的資訊 存在裡面。 我們不會保證這些檔案的安全性與永久性。 使用方法非常簡單。 load() 會以字串的形式傳回全部的檔案內容, save() 則會把傳入的字串寫入檔案中。 每個檔案的大小限制可由 limit() 取得, 超過的部份會被自動忽略。 檔案位置的選擇方式,稱之為「分類 (Category)」。 目前開放的兩個分類為 store.USER (使用者目錄) 與 store.GLOBAL (全站共享)。 前者會隨使用者而不同 (可製作各類進度存檔),後者則是所有人共用一個檔 (可製作全站排行等) 範例: store.save(store.USER, "abcd"); a = store.load(store.USER); 另外要注意的是, load() save() 兩個 API 是 atomic 的,但沒有其它 Lock 機制。 換言之,使用 store.GLOBAL 時如果你 load() 之後很久才寫入, 中間可能會遇到其它使用者先改變了內容而不知,所以 store.GLOBAL 在 load() 與 save() 兩個呼叫中間的程式盡量越少越好。 為了避免過量或惡意的資料存取造成系統效能問題,每次執行 BBSLua 程式時 所能執行的 I/O (load/save) 呼叫次數是有限制的,這個限制可由 store.iolimit() 取得。 請避免不必要的 I/O。 超過此限制後所有的 I/O 呼叫都會失敗。 最後,每個程式所存取的實際檔案都是不同的。 若修改程式想沿用舊的存檔 則必須直接編輯文章而非發表新文章。 若想讓轉錄文共用一個存檔,則可利用 LatestRef。 ===================================================================== ● 版本更新注意事項 === 2008/01/06 2:03 前的作品昇級要注意: (0.101) === 1. -- BBSLUA 改前後加上 --#BBSLUA 2. stand_title 改 title 3. bbs.outs(bbs.ANSI_COLOR(1,33) .. "test" .. bbs.ANSI_RESET); 建議改成 bbs.color(1,33); bbs.outs("test"); bbs.color(); === 2008/01/06 13:00 後有效: (0.102) === 1. 新增 getmaxyx(), moverel() 2. chattr() 改為 setattr() 3. igetch() 停止支援,請用 getch 4. getnstr() 停止支援,請用 getstr 或 getdata 5. vmsg() 停止支援,請用 pause 6. bbs.outs() / bbs.addstr() 可改為寫 print(),不用加前面的 bbs. === 2008/01/06 15:55 後有效: (0.103) === 1. 新增 bbs.userid() 為目前使用者 id 2. 新增 bbs.kbhit() === 2008/01/06 17:05 後有效: (0.104) === 1. print()/bbs.print() 現在會比 outs() 多印一個換行 2. 修正跑久會停住的問題 === 2008/01/06 21:53 後有效: (0.105) === 1. 新增 bbs.clock() === 2008/01/07 10:50 後有效: (0.106) === 1. 新增 bbs.sleep(),暫時只開放最多 10 秒 === 2008/01/07 11:50 後有效: (0.107) === 1. 修正 bbs.sleep() 未處理 Ctrl-C 的問題,重新開放上限 2. 新增 bbs.kbreset() === 2008/01/07 14:15 後有效: (0.108) === 1. 新增 bitlib ( http://luaforge.net/projects/bitlib ) 為標準之一, 方便移植用 C 寫的程式 === 2008/01/07 21:05 後有效: (0.109) === 1. 新增 bbs.interface bbs.sitename 2. 格式新增 TOC tags (toc.*) === 2008/01/08 01:00 後有效: (0.110) === 1. 由於太多人無法理解 refresh() 與 input queue 的關係,此版起 refresh() 會無視輸入緩衝區強制更新。 === 2008/01/08 03:00 後有效: (0.111) === 1. 修正 co-routine yield/resume 不正常的問題 === 2008/01/08 23:45 後有效: (0.112) 1. 修正 bbs.pause() 傳回值,現在與 bbs.getch() 相同 2. 修正 bbs.color(): 無參數時等於 bbs.color(0) (重設顏色) === 2008/01/10 19:40 後有效: (0.113) === 1. 新增 toc.date 與新的開始畫面 2. 新增 bbs.box === 2008/01/10 21:00 後有效: (0.114) === 1. bbs.box 改名為 bbs.rect === 2008/01/11 01:36 後有效: (0.115) === 1. 新增 bbs.strip_ansi() 2. 修正 bbs.getdata() 無法中斷的問題 3. bbs.getdata() 若輸入空字串,現在傳回值為 "" 而非 nil === 2008/01/12 13:15 後有效: (0.116) === 1. 執行熱鍵由 P 改為 L, 大小寫均有效 2. 結束執行後不再將畫面變灰 3. 語法錯誤的行數更為準確了 (感謝 kcwu) 4. Windows BBS-Lua 模擬器! http://ntu.csie.org/~piaip/bbslua/bbslua.exe === 2008/01/14 20:50 後有效: (0.117) === 1. getdata() 新增 str 參數為預設輸入值 2. TOC 新增 LatestRef ,解決轉錄後版本不同步的問題 3. 編輯器增加簡易 BBS-Lua syntax highlight === 2008/01/16 17:45 後有效: (0.118) === 1. 新增 bbs.kball(sec) === 2008/01/19 14:00 後有效: (0.119) === 1. LatestRef 要兩邊 LatestRef/Title 欄位值相同才有效,以解決跨站轉信的問題 2. 改變 bbs.userid 為變數而非函式 3. 新增 bbs.usernick === 2008/??/?? ??:?? 後有效: (0.201) === 1. store API 上線 === 未制定 API: - TOC about dialogs - (2.0) communiction api -- ※ 發信站: 批踢踢兔(ptt2.cc) ◆ From: 140.112.30.54 puttogether:轉錄至某隱形看板 01/20 22:19 joeytseng:轉錄至某隱形看板 01/23 14:59 windfall:轉錄至某隱形看板 01/25 16:33 ReverbHorn:轉錄至某隱形看板 02/11 18:31 Ekaterine:轉錄至看板 SeekForBliss 02/11 19:57 mike1026915:轉錄至看板 mike1026915 02/24 02:59 HellCloud:轉錄至某隱形看板 03/04 22:32 jackwei:轉錄至看板 Jackwei 04/11 15:07 hialan:轉錄至看板 hialan 04/12 22:46 kstingray:轉錄至看板 kappy 05/25 02:21 TsuKi0410:轉錄至某隱形看板 05/26 20:34 lamboxd:轉錄至看板 LamboXD 07/06 17:11 averycrazy:轉錄至看板 IrelativityY 07/28 11:20 isme1086:轉錄至某隱形看板 08/11 23:06 cockroach00:轉錄至看板 gogodie 08/15 23:31 ramknarf:轉錄至某隱形看板 09/11 17:20 ricksimon:轉錄至某隱形看板 09/11 19:51 Yoyoli:轉錄至看板 Louisyaya 09/17 11:09 asdfghjk0126:轉錄至某隱形看板 09/21 02:36 EmiruKitty:轉錄至看板 KittySpot 10/06 00:38 yoway945:轉錄至看板 yovi945 11/22 20:23 CYBASTER:轉錄至看板 CYBASTER 02/22 14:46