tabularize.lua 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. local core = require "core"
  2. local command = require "core.command"
  3. local translate = require "core.doc.translate"
  4. local function gmatch_to_array(text, ptn)
  5. local res = {}
  6. for x in text:gmatch(ptn) do
  7. table.insert(res, x)
  8. end
  9. return res
  10. end
  11. local function tabularize_lines(lines, delim)
  12. local rows = {}
  13. local cols = {}
  14. -- split lines at delimiters and get maximum width of columns
  15. local ptn = "[^" .. delim:sub(1,1):gsub("%W", "%%%1") .. "]+"
  16. for i, line in ipairs(lines) do
  17. rows[i] = gmatch_to_array(line, ptn)
  18. for j, col in ipairs(rows[i]) do
  19. cols[j] = math.max(#col, cols[j] or 0)
  20. end
  21. end
  22. -- pad columns with space
  23. for _, row in ipairs(rows) do
  24. for i = 1, #row - 1 do
  25. row[i] = row[i] .. string.rep(" ", cols[i] - #row[i])
  26. end
  27. end
  28. -- write columns back to lines array
  29. for i, line in ipairs(lines) do
  30. lines[i] = table.concat(rows[i], delim)
  31. end
  32. end
  33. command.add("core.docview", {
  34. ["tabularize:tabularize"] = function()
  35. core.command_view:enter("Tabularize On Delimiter", function(delim)
  36. if delim == "" then delim = " " end
  37. local doc = core.active_view.doc
  38. local line1, col1, line2, col2, swap = doc:get_selection(true)
  39. line1, col1 = doc:position_offset(line1, col1, translate.start_of_line)
  40. line2, col2 = doc:position_offset(line2, col2, translate.end_of_line)
  41. doc:set_selection(line1, col1, line2, col2, swap)
  42. doc:replace(function(text)
  43. local lines = gmatch_to_array(text, "[^\n]*\n?")
  44. tabularize_lines(lines, delim)
  45. return table.concat(lines)
  46. end)
  47. end)
  48. end,
  49. })