舊文字範本

lua-users home
wiki


[!] 版本公告:下方的程式碼屬於較舊的 Lua 版本,Lua 4。此 code 無法在 Lua 5 下執行。此頁面最新版本請至 TextTemplate

新 Lua 程式設計師的一個良好練習是執行 Jon Bentley 的 M1 巨集處理器 [1] 至 Lua。然後檢視 test/examples/www/staff.lua [2],便會明白巨集處理器的主要缺點是它們沒有資料結構,而新增它們並非難事。目標是建立一個函數 template 來製作範本,及另一個函數 fillin 從一表格取得數值,並將之替換為範本中對應的參照。範本語法相當簡單。表格成員和全域變數以其名稱為參照,並以 | 括號括住;環境變數加上 $ 前綴;函數呼叫加上 @ 前綴;Lua 程式碼以 @{ 和 } 包住。以下為如何使用 templatefillin 的範例。
require'temp.lua'
t1 = template[[
==============================================================================
you can access variables: |v|
or environment variables: $HOME
you can call functions: @concat( list, ', ' )
this list has |list.n| elements
   @strrep( '=', list.n )
   @concat( list )
   @strrep( '=', list.n )
or evaluate code inline
     @{ for i=1,4 do OUT = OUT .." list[".. i .."] = ".. list[i] .."\n" end }
you can access global variables:
This example is from |mjd| at |mjdweb|
@{ x = getn(list) }The Lord High Chamberlain has gotten @getn(list)
things for me this year.
@{ diff = x - 2
   more = 'more'
   if diff == 0 then
     diff = 'no'
   elseif diff < 0 then
     more = 'fewer'
   end
}
That is |diff| |more| than he gave me last year.
values can have other variables: |ref|
==============================================================================
]]
mjd = "Mark J. Dominus"
mjdweb = 'http://perl.plover.com/'
L = {}
for i = 1,5 do tinsert( L, strchar(64+i) ) end
x = {
  v = 'this is v',
  list = L,
  ref = "|mjd| made Text::Template.pm" 
}
-- fill in the template t1 with values in table x
write( fillin( x, t1 ) )
以下是上述程式碼的輸出。 TextTemplateExampleOutput temp.lua 的程式碼相當長,所以我把它放到另一個頁面,並加上行號。 TextTemplateCode 請注意,此程式碼需要 Lua 4.1 (beta)。template 函數會從範本字串中移除所有函數呼叫和 Lua 程式碼,並以 Magic 全域變數的名稱取代它們。以下為上述範例中 template 回傳的內容。
==============================================================================
you can access variables: |v|
or environment variables: /home/administrator
you can call functions: |2concat|
this list has |1list| elements
   |3strrep|
   |4concat|
   |5strrep|
or evaluate code inline
     |7ANY|
you can access global variables:
This example is from |mjd| at |mjdweb|
|8ANY|The Lord High Chamberlain has gotten |6getn|
things for me this year.
|9ANY|
That is |diff| |more| than he gave me last year.
values can have other variables: |ref|
==============================================================================
template 也會把所有從範本字串中移除的函數呼叫和 Lua 程式碼包裝好,並將它們放入一個使用 Magic 變數名稱作為索引的表格,且讓所有 Magic 變數指向該表格。以下為 template 根據上述範例產生的程式碼,並使用 dostring 評估。
local Magic = settype( {}, newtype'magic' )
Magic['1list'] = function()
  local self=globals()
  return list.n --
end
setglobal('1list', Magic )
Magic['2concat'] = function()
  local self=globals()
  return concat( list, ', ' ) --
end
setglobal('2concat', Magic )
Magic['3strrep'] = function()
  local self=globals()
  return strrep( '=', list.n ) --
end
setglobal('3strrep', Magic )
Magic['4concat'] = function()
  local self=globals()
  return concat( list ) --
end
setglobal('4concat', Magic )
Magic['5strrep'] = function()
  local self=globals()
  return strrep( '=', list.n ) --
end
setglobal('5strrep', Magic )
Magic['6getn'] = function()
  local self=globals()
  return getn(list) --
end
setglobal('6getn', Magic )
Magic['7ANY'] = function()
  local OUT=''
  local self=globals()
  do  for i=1,4 do OUT = OUT .." list[".. i .."] = ".. list[i] .."\n" end  end
  return OUT
end
setglobal('7ANY', Magic )
Magic['8ANY'] = function()
  local OUT=''
  local self=globals()
  do  x = getn(list)  end
  return OUT
end
setglobal('8ANY', Magic )
Magic['9ANY'] = function()
  local OUT=''
  local self=globals()
  do  diff = x - 2
   more = 'more'
   if diff == 0 then
     diff = 'no'
   elseif diff < 0 then
     more = 'fewer'
   end
 end
  return OUT
end
setglobal('9ANY', Magic )
fillin 函數會取得一個值表格及 template 回傳的字串,並使用 gsub 填入數值。執行這項動作前,它會將值表格設定為全域表格,並將 nil 值的 getglobal 標籤方法設定。因此,若無法在值表格中找到變數,它會嘗試在 sharedvars 表格中尋找,最後才是實際的全域變數表格。這似乎過於複雜,但它可讓範本中的程式碼片段存取值表格和全域變數,如同它們位於範圍內一般。它也會呼叫適當的 Magic 變數相關聯的函數。如果有更好的方法,請修改此部分說明。
近期變更 · 喜好設定
編輯 · 歷史
上次編輯:2007 年 5 月 28 日 格林威治時間下午 8:45 (比對)