From e77860a3397c107fe07f986bf0c4143baec92b75 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Sat, 7 Oct 2023 14:50:31 +0200 Subject: [PATCH] fix: Improved stability --- lua/easytables/options.lua | 2 +- lua/easytables/table.lua | 128 ++++++--------- lua/easytables/window.lua | 311 ++++++++++++++++++++++--------------- 3 files changed, 232 insertions(+), 209 deletions(-) diff --git a/lua/easytables/options.lua b/lua/easytables/options.lua index 1f01f55..98954d5 100644 --- a/lua/easytables/options.lua +++ b/lua/easytables/options.lua @@ -123,7 +123,7 @@ local options = { buf, "n", "", - ":JumpToPrevCell", + ":JumpToPreviousCell", {} ) end diff --git a/lua/easytables/table.lua b/lua/easytables/table.lua index 581569e..14f35b3 100644 --- a/lua/easytables/table.lua +++ b/lua/easytables/table.lua @@ -104,88 +104,6 @@ function M:get_highlighted_cell() return self.highlighted_cell end --- Jumps to next cell in row. If there is no next cell, it jumps to the first cell in the next row. -function M:move_highlight_to_next_cell() - if self.highlighted_cell.col == self:cols_amount() then - if self.highlighted_cell.row == self:rows_amount() then - -- Reset highlight to the first cell - self.highlighted_cell = { - col = 1, - row = 1, - } - else - self.highlighted_cell = { - col = 1, - row = self.highlighted_cell.row + 1, - } - end - else - self.highlighted_cell = { - col = self.highlighted_cell.col + 1, - row = self.highlighted_cell.row, - } - end -end - --- Jumps to previous cell in row. If there is no previous cell, it jumps to the last cell in the previous row. -function M:move_highlight_to_previous_cell() - if self.highlighted_cell.col == 1 then - if self.highlighted_cell.row == 1 then - -- Reset highlight to the last cell - self.highlighted_cell = { - col = self:cols_amount(), - row = self:rows_amount(), - } - else - self.highlighted_cell = { - col = self:cols_amount(), - row = self.highlighted_cell.row - 1, - } - end - else - self.highlighted_cell = { - col = self.highlighted_cell.col - 1, - row = self.highlighted_cell.row, - } - end -end - --- Moves highlight to the right, jumps back to the first cell in the same row if it is already at the rightmost cell. -function M:move_highlight_right() - if self.highlighted_cell.col == self:cols_amount() then - self.highlighted_cell.col = 1 - else - self.highlighted_cell.col = self.highlighted_cell.col + 1 - end -end - --- Moves highlight to the left, jumps back to the last cell in the same row if it is already at the leftmost cell. -function M:move_highlight_left() - if self.highlighted_cell.col == 1 then - self.highlighted_cell.col = self:cols_amount() - else - self.highlighted_cell.col = self.highlighted_cell.col - 1 - end -end - --- Moves highlight to the top, jumps back to the last row if it is already at the topmost row. -function M:move_highlight_up() - if self.highlighted_cell.row == 1 then - self.highlighted_cell.row = self:rows_amount() - else - self.highlighted_cell.row = self.highlighted_cell.row - 1 - end -end - --- Moves highlight to the bottom, jumps back to the first row if it is already at the bottommost row. -function M:move_highlight_down() - if self.highlighted_cell.row == self:rows_amount() then - self.highlighted_cell.row = 1 - else - self.highlighted_cell.row = self.highlighted_cell.row + 1 - end -end - function M:get_cell_positions(col, row, widths) local length = #o.options.table.border.vertical local start_position = 0 @@ -271,4 +189,50 @@ function M:swap_contents(first, second) self:insert(second.col, second.row, first_value) end +function M:swap_current_with_target(target) + self:swap_contents(self:get_highlighted_cell(), target) +end + +---Inserts a new empty row at the given index (zero based) +---Example: 0 would insert a new row at the top of the table +---Example: 1 would insert a new row at the second position of the table +---Example: length of table would insert a new row at the bottom of the table +function M:insert_row(index) + local row = {} + for i = 1, self:cols_amount() do + row[i] = "" + end + + table.insert(self.table, index + 1, row) +end + +---Inserts a new empty column at the given index (zero based) +function M:insert_col(index) + for _, row in ipairs(self.table) do + table.insert(row, index + 1, "") + end +end + +function M:delete_col(col) + if (#self.table[1] == 1) then + error("Cannot delete last column") + return + end + + for _, row in ipairs(self.table) do + table.remove(row, col) + end +end + +function M:delete_row(row) + if (#self.table == 1) then + error("Cannot delete last row") + return + end + + table.remove(self.table, row) + + self.header_enabled = #self.table > 1 +end + return M diff --git a/lua/easytables/window.lua b/lua/easytables/window.lua index 33fc1da..e2431e0 100644 --- a/lua/easytables/window.lua +++ b/lua/easytables/window.lua @@ -220,13 +220,24 @@ function M:update_window() end function M:close() - vim.api.nvim_win_close(self.preview_window, true) - vim.api.nvim_win_close(self.prompt_window, true) - + -- Wrap all in pcall to prevent errors when closing windows + pcall(function() + vim.api.nvim_win_close(self.preview_window, true) + end) + pcall(function() + vim.api.nvim_win_close(self.prompt_window, true) + end) pcall(function() vim.api.nvim_set_current_win(self.previous_window) end) + pcall(function() + vim.api.nvim_buf_delete(self.preview_buffer, { force = true }) + end) + pcall(function() + vim.api.nvim_buf_delete(self.prompt_buffer, { force = true }) + end) + self.preview_window = nil self.prompt_window = nil self.preview_buffer = nil @@ -259,146 +270,194 @@ function M:register_listeners() } ) - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "JumpToNextCell", - function() - self.table:move_highlight_to_next_cell() - self:update_window() - self:_reset_prompt() - end, - {} - ) + local cmds = { + } - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "JumpToPreviousCell", - function() - self.table:move_highlight_to_previous_cell() - self:update_window() - self:_reset_prompt() - end, - {} - ) + for cmd, func in pairs(cmds) do + vim.api.nvim_buf_create_user_command( + self.prompt_buffer, + cmd, + function() + func() + self:update_window() + self:_reset_prompt() + end, + {} + ) + end - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "JumpDown", - function() - self.table:move_highlight_down() - self:update_window() - self:_reset_prompt() - end, - {} - ) + local cmds = { + JumpToNextCell = function() + local cell = self.table:get_highlighted_cell() - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "JumpUp", - function() - self.table:move_highlight_up() - self:update_window() - self:_reset_prompt() - end, - {} - ) + if cell.col == self.table:cols_amount() then + if cell.row == self.table:rows_amount() then + -- Reset highlight to the first cell + return { + col = 1, + row = 1, + } + else + return { + col = 1, + row = cell.row + 1, + } + end + end - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "JumpLeft", - function() - self.table:move_highlight_left() - self:update_window() - self:_reset_prompt() - end, - {} - ) - - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "JumpRight", - function() - self.table:move_highlight_right() - self:update_window() - self:_reset_prompt() - end, - {} - ) - - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "SwapWithRightCell", - function() - local current_cell = self.table:get_highlighted_cell() - - local right_cell = { - row = current_cell.row, - col = current_cell.col == self.table:cols_amount() and 1 or current_cell.col + 1, + return { + col = cell.col + 1, + row = cell.row } - self.table:swap_contents(current_cell, right_cell) - self:_update_active_cell(right_cell) - self:update_window() - self:_reset_prompt() end, - {} - ) + JumpToPreviousCell = function() + local cell = self.table:get_highlighted_cell() - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "SwapWithLeftCell", - function() - local current_cell = self.table:get_highlighted_cell() + if cell.col == 1 then + if cell.row == 1 then + -- Reset highlight to the last cell + return { + col = self.table:cols_amount(), + row = self.table:rows_amount(), + } + else + return { + col = self.table:cols_amount(), + row = cell.row - 1, + } + end + end - local left_cell = { - row = current_cell.row, - col = current_cell.col == 1 and self.table:cols_amount() or current_cell.col - 1, + return { + col = cell.col - 1, + row = cell.row, } - self.table:swap_contents(current_cell, left_cell) - self.table:_update_active_cell(left_cell) - self:update_window() - self:draw_table() - self:_reset_prompt() end, - {} - ) - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "SwapWithUpperCell", - function() - local current_cell = self.table:get_highlighted_cell() + JumpDown = function() + local cell = self.table:get_highlighted_cell() - local upper_cell = { - row = current_cell.row == 1 and self.table:rows_amount() or current_cell.row - 1, - col = current_cell.col, + return { + row = cell.row == self.table:rows_amount() and 1 or cell.row + 1, + col = cell.col, } - self.table:swap_contents(current_cell, upper_cell) - self.table:_update_active_cell(upper_cell) - self:update_window() - self:draw_table() - self:_reset_prompt() end, - {} - ) + JumpUp = function() + local cell = self.table:get_highlighted_cell() - vim.api.nvim_buf_create_user_command( - self.prompt_buffer, - "SwapWithLowerCell", - function() - local current_cell = self.table:get_highlighted_cell() - - local lower_cell = { - row = current_cell.row == self.table:rows_amount() and 1 or current_cell.row + 1, - col = current_cell.col, + return { + row = cell.row == 1 and self.table:rows_amount() or cell.row - 1, + col = cell.col, } - self.table:swap_contents(current_cell, lower_cell) - self.table:_update_active_cell(lower_cell) - self:update_window() - self:draw_table() - self:_reset_prompt() end, - {} - ) + JumpLeft = function() + local cell = self.table:get_highlighted_cell() + + return { + row = cell.row, + col = cell.col == 1 and self.table:cols_amount() or cell.col - 1, + } + end, + JumpRight = function() + local cell = self.table:get_highlighted_cell() + + return { + row = cell.row, + col = cell.col == self.table:cols_amount() and 1 or cell.col + 1, + } + end, + + DeleteColumn = function() self.table:delete_col(self.table:get_highlighted_cell().col) end, + DeleteRow = function() self.table:delete_row(self.table:get_highlighted_cell().row) end, + + InsertColumnRight = function() + self.table:insert_col(self.table:get_highlighted_cell().col) + return { + row = self.table:get_highlighted_cell().row, + col = self.table:get_highlighted_cell().col + 1, + } + end, + InsertColumnLeft = function() + self.table:insert_col(self.table:get_highlighted_cell().col - 1) + return { + row = self.table:get_highlighted_cell().row, + col = self.table:get_highlighted_cell().col, + } + end, + InsertRowBelow = function() + self.table:insert_row(self.table:get_highlighted_cell().row) + return { + row = self.table:get_highlighted_cell().row + 1, + col = self.table:get_highlighted_cell().col, + } + end, + InsertRowAbove = function() + self.table:insert_row(self.table:get_highlighted_cell().row - 1) + return { + row = self.table:get_highlighted_cell().row, + col = self.table:get_highlighted_cell().col, + } + end, + + SwapWithRightCell = function() + local cell = self.table:get_highlighted_cell() + + local target = { + row = cell.row, + col = cell.col == self.table:cols_amount() and 1 or cell.col + 1, + } + self.table:swap_current_with_target(target) + return target + end, + SwapWithLeftCell = function() + local cell = self.table:get_highlighted_cell() + + local target = { + row = cell.row, + col = cell.col == 1 and self.table:cols_amount() or cell.col - 1, + } + self.table:swap_current_with_target(target) + return target + end, + SwapWithUpperCell = function() + local cell = self.table:get_highlighted_cell() + + local target = { + row = cell.row == 1 and self.table:rows_amount() or cell.row - 1, + col = cell.col, + } + self.table:swap_current_with_target(target) + return target + end, + SwapWithLowerCell = function() + local cell = self.table:get_highlighted_cell() + + local target = { + row = cell.row == self.table:rows_amount() and 1 or cell.row + 1, + col = cell.col, + } + self.table:swap_current_with_target(target) + return target + end, + } + + for cmd, func in pairs(cmds) do + vim.api.nvim_buf_create_user_command( + self.prompt_buffer, + cmd, + function() + local new_cell = func() + + if new_cell ~= nil then + self:_update_active_cell(new_cell) + end + + self:update_window() + self:_reset_prompt() + end, + {} + ) + end vim.api.nvim_buf_create_user_command( self.prompt_buffer,