|
| 1 | +local ts_utils = require('nvim-treesitter.ts_utils') |
| 2 | +local Table = require('orgmode.parser.table') |
| 3 | +local utils = require('orgmode.utils') |
| 4 | +local config = require('orgmode.config') |
| 5 | +local query = vim.treesitter.query |
| 6 | + |
| 7 | +---@class TsTable |
| 8 | +---@field node userdata |
| 9 | +---@field data table[] |
| 10 | +local TsTable = {} |
| 11 | + |
| 12 | +function TsTable:new(opts) |
| 13 | + local data = {} |
| 14 | + data.node = opts.node |
| 15 | + setmetatable(data, self) |
| 16 | + self.__index = self |
| 17 | + data:_parse_data() |
| 18 | + return data |
| 19 | +end |
| 20 | + |
| 21 | +---@private |
| 22 | +--- Parse table data from node |
| 23 | +function TsTable:_parse_data() |
| 24 | + local rows = {} |
| 25 | + for row in self.node:iter_children() do |
| 26 | + if row:type() == 'hr' then |
| 27 | + table.insert(rows, 'hr') |
| 28 | + end |
| 29 | + if row:type() == 'row' then |
| 30 | + local row_data = {} |
| 31 | + for cell in row:iter_children() do |
| 32 | + if cell:type() == 'cell' then |
| 33 | + local cell_val = '' |
| 34 | + local cell_content = cell:field('contents') |
| 35 | + if cell_content and #cell_content > 0 then |
| 36 | + cell_val = query.get_node_text(cell_content[1], 0) |
| 37 | + end |
| 38 | + table.insert(row_data, cell_val) |
| 39 | + end |
| 40 | + end |
| 41 | + table.insert(rows, row_data) |
| 42 | + end |
| 43 | + end |
| 44 | + |
| 45 | + self.data = rows |
| 46 | +end |
| 47 | + |
| 48 | +function TsTable:rerender() |
| 49 | + local start_row, start_col = self.node:range() |
| 50 | + local tbl = Table.from_list(self.data, start_row + 1, start_col + 1) |
| 51 | + local first_line = vim.api.nvim_buf_get_lines(0, start_row, start_row + 1, true) |
| 52 | + local indent = first_line and first_line[1]:match('^%s*') or '' |
| 53 | + indent = config:get_indent(indent:len()) |
| 54 | + |
| 55 | + local contents = tbl:draw() |
| 56 | + local indented = {} |
| 57 | + for _, content in ipairs(contents) do |
| 58 | + table.insert(indented, string.format('%s%s', indent, content)) |
| 59 | + end |
| 60 | + local view = vim.fn.winsaveview() |
| 61 | + vim.api.nvim_buf_set_lines(0, tbl.range.start_line - 1, tbl.range.end_line - 1, false, indented) |
| 62 | + vim.fn.winrestview(view) |
| 63 | +end |
| 64 | + |
| 65 | +local function format() |
| 66 | + local view = vim.fn.winsaveview() |
| 67 | + -- Go to first non blank char |
| 68 | + vim.cmd([[norm! _]]) |
| 69 | + local node = ts_utils.get_node_at_cursor() |
| 70 | + vim.fn.winrestview(view) |
| 71 | + |
| 72 | + if not node then |
| 73 | + return false |
| 74 | + end |
| 75 | + print(node:type()) |
| 76 | + print(node:type()) |
| 77 | + print(node:type()) |
| 78 | + local table_node = utils.get_closest_parent_of_type(node, 'table', true) |
| 79 | + if not table_node then |
| 80 | + return false |
| 81 | + end |
| 82 | + TsTable:new({ node = table_node }):rerender() |
| 83 | + return true |
| 84 | +end |
| 85 | + |
| 86 | +return { |
| 87 | + format = format, |
| 88 | +} |
0 commit comments