Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CsvViewToggle command #6

Merged
merged 3 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ After opening a CSV file, use the following commands to interact with the plugin

- `:CsvViewEnable`: Enable CSV view.
- `:CsvViewDisable`: Disable CSV view.
- `:CsvViewToggle`: Toggle CSV view.

### Lua API

- `require('csvview').enable()`: Enable CSV view.
- `require('csvview').disable()`: Disable CSV view.
- `require('csvview').toggle()`: Toggle CSV view.
- `require('csvview').is_enabled()`: Check if CSV view is enabled.

## Highlights

Expand Down
41 changes: 41 additions & 0 deletions lua/csvview/buffer_event.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
local M = {}

---@class CsvViewBufferEvents
---@field on_lines fun(event: "lines", bufnr: integer, changedtick: integer, first: integer, last: integer, last_updated: integer, byte_count: integer, deleted_codepoints: integer, deleted_codeunits: integer): boolean | nil Return `true` to detach from buffer events.
---@field on_reload fun(event: "reload", bufnr: integer) : boolean | nil Return `true` to detach from buffer events.

---Register buffer events. This will attach to the buffer and listen for events.
---When the buffer is reloaded, the events will be re-registered.
---@param bufnr integer
---@param events CsvViewBufferEvents
function M.register(bufnr, events)
-- Re-register events on `:e`
vim.b[bufnr].csvview_update_auid = vim.api.nvim_create_autocmd({ "BufReadPost" }, {
callback = function()
M.register(bufnr, events)
events.on_reload("reload", bufnr)
end,
buffer = bufnr,
once = true,
})

-- Attach to buffer
vim.api.nvim_buf_attach(bufnr, false, {
on_lines = function(...)
return events.on_lines(...)
end,
on_reload = function(...)
return events.on_reload(...)
end,
})
end

---Unregister buffer events.
---This will detach from the buffer and stop listening for events.
---@param bufnr integer
function M.unregister(bufnr)
vim.api.nvim_del_autocmd(vim.b[bufnr].csvview_update_auid)
vim.b[bufnr].csvview_update_auid = nil
end

return M
89 changes: 47 additions & 42 deletions lua/csvview/init.lua
Original file line number Diff line number Diff line change
@@ -1,68 +1,49 @@
local M = {}

local buffer_event = require("csvview.buffer_event")
local config = require("csvview.config")
local metrics = require("csvview.metrics")
local view = require("csvview.view")

--- @type integer[]
local enable_buffers = {}

--- register buffer events
--- check if csv table view is enabled
---@param bufnr integer
---@param events { on_lines:function,on_reload:function}
local function register_events(bufnr, events)
--- on :e
vim.b[bufnr].csvview_update_auid = vim.api.nvim_create_autocmd({ "BufReadPost" }, {
callback = function()
register_events(bufnr, events)
events.on_reload()
end,
buffer = bufnr,
once = true,
})

vim.api.nvim_buf_attach(bufnr, false, {
on_lines = function(...)
if not vim.tbl_contains(enable_buffers, bufnr) then
return true
end
events.on_lines(...)
end,
on_reload = function()
if not vim.tbl_contains(enable_buffers, bufnr) then
return true
end
events.on_reload()
end,
})
end

--- unregister buffer events
---@param bufnr integer
local function unregister_events(bufnr)
vim.api.nvim_del_autocmd(vim.b[bufnr].csvview_update_auid)
vim.b[bufnr].csvview_update_auid = nil
---@return boolean
function M.is_enabled(bufnr)
return vim.tbl_contains(enable_buffers, bufnr)
end

--- enable csv table view
---@param bufnr integer?
---@param opts CsvViewOptions?
function M.enable(bufnr, opts)
bufnr = bufnr or vim.api.nvim_get_current_buf()
if vim.tbl_contains(enable_buffers, bufnr) then
opts = config.get(opts)

if M.is_enabled(bufnr) then
vim.notify("csvview: already enabled for this buffer.")
return
end
table.insert(enable_buffers, bufnr)

-- Calculate fields and enable csv table view.
local fields = {}
opts = config.get(opts)
metrics.compute_csv_metrics(bufnr, opts, function(f, column_max_widths)
fields = f
view.attach(bufnr, fields, column_max_widths, opts)
end)
register_events(bufnr, {
---@type fun(_,_,_,first:integer,last:integer,last_updated:integer)

-- Register buffer events.
buffer_event.register(bufnr, {
on_lines = function(_, _, _, first, last, last_updated)
-- detach if disabled
if not M.is_enabled(bufnr) then
return true
end

-- handle line deletion and addition
if last > last_updated then
-- when line deleted.
for _ = last_updated + 1, last do
Expand All @@ -77,6 +58,7 @@ function M.enable(bufnr, opts)
-- when updated within a line.
end

-- Recalculate only the difference.
local startlnum = first + 1
local endlnum = last_updated
metrics.compute_csv_metrics(bufnr, opts, function(f, column_max_widths)
Expand All @@ -86,6 +68,12 @@ function M.enable(bufnr, opts)
end,

on_reload = function()
-- detach if disabled
if not M.is_enabled(bufnr) then
return true
end

-- Recalculate all fields.
view.detach(bufnr)
metrics.compute_csv_metrics(bufnr, opts, function(f, column_max_widths)
fields = f
Expand All @@ -96,23 +84,37 @@ function M.enable(bufnr, opts)
end

--- disable csv table view
function M.disable()
local bufnr = vim.api.nvim_get_current_buf()
if not vim.tbl_contains(enable_buffers, bufnr) then
---@param bufnr integer?
function M.disable(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
if not M.is_enabled(bufnr) then
vim.notify("csvview: not enabled for this buffer.")
return
end

-- Remove buffer from enabled list.
for i = #enable_buffers, 1, -1 do
if enable_buffers[i] == bufnr then
table.remove(enable_buffers, i)
end
end

unregister_events(bufnr)
-- Unregister buffer events and detach view.
buffer_event.unregister(bufnr)
view.detach(bufnr)
end

--- toggle csv table view
---@param bufnr integer?
function M.toggle(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
if M.is_enabled(bufnr) then
M.disable(bufnr)
else
M.enable(bufnr)
end
end

--- setup
---@param opts CsvViewOptions?
function M.setup(opts)
Expand All @@ -124,6 +126,9 @@ function M.setup(opts)
vim.api.nvim_create_user_command("CsvViewDisable", function()
M.disable()
end, {})
vim.api.nvim_create_user_command("CsvViewToggle", function()
M.toggle()
end, {})
end

return M
2 changes: 0 additions & 2 deletions lua/csvview/view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ end
---@param bufnr integer
function M.detach(bufnr)
if not M._views[bufnr] then
vim.notify("csvview: not attached for this buffer.")
return
end
M._views[bufnr]:clear()
Expand All @@ -213,7 +212,6 @@ end
---@param column_max_widths number[]
function M.update(bufnr, fields, column_max_widths)
if not M._views[bufnr] then
vim.notify("csvview: not attached for this buffer.")
return
end
M._views[bufnr]:update(fields, column_max_widths)
Expand Down
Loading