You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

templet.lua 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. ------------------------------------------------------------------------------
  2. -- Templet for Lua.
  3. -- Copyright © 2012–2015 Peter Colberg.
  4. -- Distributed under the MIT license. (See accompanying file LICENSE.)
  5. ------------------------------------------------------------------------------
  6. local _M = {}
  7. -- Cache library functions.
  8. local insert, concat = table.insert, table.concat
  9. local find, format, sub = string.find, string.format, string.sub
  10. -- Parse verbatim blocks containing template expressions.
  11. local function parse_expression(result, chunk)
  12. local i, n = 1, #chunk
  13. while i <= n do
  14. local s, e, expr = find(chunk, "$(%b{})", i)
  15. if not s or s > i then
  16. insert(result, format("_put(%q)", sub(chunk, i, s and s - 1)))
  17. end
  18. if not s then break end
  19. insert(result, format("_put(%s)", sub(expr, 2, -2)))
  20. i = e + 1
  21. end
  22. end
  23. -- Parse template statements.
  24. local function parse_statement(result, chunk)
  25. local i, n = 1, #chunk
  26. while i <= n do
  27. local s, e, stmt = find(chunk, "%f[^%z\n]%s*|([^\n]*\n?)", i)
  28. if not s or s > i then
  29. parse_expression(result, sub(chunk, i, s and s - 1))
  30. end
  31. if not s then break end
  32. insert(result, stmt)
  33. i = e + 1
  34. end
  35. end
  36. -- Lua 5.1 uses setfenv, Lua 5.2 uses _ENV
  37. local setfenv = setfenv
  38. local render_to_function
  39. if setfenv then
  40. function render_to_function(render, f, env)
  41. setfenv(render, env)
  42. local status, err = pcall(render, f)
  43. if not status then return error(err) end
  44. end
  45. else
  46. function render_to_function(render, f, env)
  47. local status, err = pcall(render, f, env)
  48. if not status then return error(err) end
  49. end
  50. end
  51. local function render_to_string(render, env)
  52. local t = {}
  53. local f = function(s)
  54. if s ~= nil then insert(t, tostring(s)) end
  55. end
  56. local status, err = pcall(render_to_function, render, f, env)
  57. if not status then return error(err) end
  58. return concat(t)
  59. end
  60. --- Lua 5.2 deprecates loadstring
  61. local load = loadstring or load
  62. local function loadtemplate(s, source)
  63. local result = {"local _put, _ENV = ..."}
  64. parse_statement(result, s)
  65. local render, err = load(concat(result), source)
  66. if not render then return error(err) end
  67. return function(env, f)
  68. local env = env or _G
  69. if not f then
  70. return render_to_string(render, env)
  71. else
  72. return render_to_function(render, f, env)
  73. end
  74. end
  75. end
  76. function _M.loadstring(s)
  77. local status, result = pcall(loadtemplate, s, s)
  78. if not status then return error(result) end
  79. return result
  80. end
  81. function _M.loadfile(filename)
  82. local f, err = io.open(filename, "r")
  83. if not f then return error(err) end
  84. local s = f:read("*a")
  85. local status, result = pcall(loadtemplate, s, "@" .. filename)
  86. if not status then return error(result) end
  87. f:close()
  88. return result
  89. end
  90. return _M