codeviewer.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. return function(BOXUI)
  2. local utils = BOXUI.utils
  3. local List = BOXUI.list
  4. local lexer = BOXUI.lexer
  5. local M = utils.newclass("codeviewer", List)
  6. local hsl2rgb = utils.hsl2rgb
  7. local clamp = utils.clamp
  8. local hsl = function(H, S, L, A)
  9. local r, g, b = hsl2rgb((H % 360) / 60, clamp(S, 0, 100) / 100, clamp(L, 0, 100) / 100)
  10. if not A then return {r, g, b, 1} end
  11. return {r, g, b, clamp(A, 0, 100) / 100}
  12. end
  13. local default_colors = {
  14. fore = hsl(0, 0, 0), back = hsl(200, 100, 95), operator = hsl(200, 50, 15),
  15. keyword = hsl(150, 65, 35), string = hsl(340, 60, 30), comment = hsl(0, 0, 50),
  16. number = hsl(200, 80, 50), iden = hsl(200, 60, 25), --line = {1 , 0, 0},
  17. idenlovepre = hsl(340, 75, 60), idenlove = hsl(200, 50, 45),
  18. }
  19. default_colors.activeline = hsl(60, 100, 2)
  20. default_colors.padding = hsl(200, 100, 90)
  21. local operators = {'+', '-', '/', '*', '%', '=', '<', '>', '<=', '>=', '~=', '==', '#'}
  22. for i, v in ipairs(operators) do operators[v] = true end
  23. local insertText = function(t, color, value)
  24. if value == nil or value == "" then return end
  25. table.insert(t, color)
  26. table.insert(t, value)
  27. end
  28. local lnf = function(i) return ("%.3i\t"):format(i) end
  29. local split = utils.split
  30. local loadLua = function(lines, data, colors, haslineno)
  31. --local lines = {}
  32. local ln = 1
  33. local lncolor = colors.comment
  34. local text = haslineno and {lncolor, lnf(ln)} or {}
  35. local t, tn, color
  36. for k, v in lexer.lua(data, {}, {}) do
  37. if operators[k] then k = "operator" end
  38. t, tn = split(v)
  39. color = colors[k] or colors.fore
  40. insertText(text, color, t[1])
  41. for i = 2, tn do -- nothing happens if tn < 2
  42. table.insert(lines, {text = text})
  43. ln = ln + 1
  44. text = haslineno and {lncolor, lnf(ln)} or {}
  45. insertText(text, color, t[i])
  46. end
  47. end
  48. if #text > 0 then
  49. table.insert(lines, {text = text})
  50. ln = ln + 1
  51. end
  52. return lines
  53. end
  54. local loadTxt = function(lines, data, color)
  55. local t = split(data)
  56. --local lines = {}
  57. for i, v in ipairs(t) do
  58. table.insert(lines, {text = {color, v}})
  59. end
  60. return lines
  61. end
  62. local fonts
  63. M.loadFile = function(self, filename, refresh)
  64. if not filename then return end
  65. local ext = filename:match(".([^.]+)$")
  66. ext = ext and ext:lower()
  67. if ext ~= "lua" and ext ~= "txt" then return end
  68. local filedata = love.filesystem.read(filename, 64 * 1024)
  69. if not filedata then return end
  70. local lines = {}
  71. if ext == "lua" then
  72. self.font = fonts["small"]
  73. loadLua(lines, filedata, self.scheme, true)
  74. elseif ext == "txt" then
  75. self.font = fonts["big"]
  76. loadTxt(lines, filedata, self.scheme.fore)
  77. else
  78. -- not really
  79. end
  80. self.title = filename
  81. self.filename = filename
  82. self.extension = ext
  83. self:setItems(lines, refresh)
  84. end
  85. M.clear = function(self)
  86. self.title = "No file"
  87. self.filename = nil
  88. self.extension = nil
  89. self:setItems(nil, true)
  90. end
  91. --utils.freshenprops(M.template_theme, theme)
  92. M.init = function(self, x, y, width, height)
  93. if not fonts then
  94. fonts = {
  95. small = love.graphics.newFont(12),
  96. big = love.graphics.newFont(14)
  97. }
  98. end
  99. self.fonts = fonts
  100. List.init(self, x, y, width, height)
  101. --self.list.theme.itemHeight = fonts["big"]:getHeight() + 2
  102. self.scheme = default_colors
  103. end
  104. BOXUI.add(M)
  105. end