263 lines
6.3 KiB
Lua
263 lines
6.3 KiB
Lua
local utils = require("nvim-tree.utils")
|
|
|
|
local M = {}
|
|
|
|
local BUFNR_PER_TAB = {}
|
|
local CURSORS = {}
|
|
local TABPAGES = {}
|
|
|
|
--- Debugging only.
|
|
--- Tabs show TABPAGES winnr and BUFNR_PER_TAB bufnr for the tab.
|
|
--- Orphans for inexistent tab_ids are shown at the right.
|
|
--- lib.target_winid is always shown at the right next to a close button.
|
|
--- Enable with:
|
|
--- vim.opt.tabline = "%!v:lua.require('nvim-tree.view').tab_line()"
|
|
--- vim.opt.showtabline = 2
|
|
function M.tab_line()
|
|
local tab_ids = vim.api.nvim_list_tabpages()
|
|
local cur_tab_id = vim.api.nvim_get_current_tabpage()
|
|
|
|
local bufnr_per_tab = vim.deepcopy(BUFNR_PER_TAB)
|
|
local tabpages = vim.deepcopy(TABPAGES)
|
|
|
|
local tl = "%#TabLine#"
|
|
|
|
for i, tab_id in ipairs(tab_ids) do
|
|
-- click to select
|
|
tl = tl .. "%" .. i .. "T"
|
|
|
|
-- style
|
|
if tab_id == cur_tab_id then
|
|
tl = tl .. "%#StatusLine#|"
|
|
else
|
|
tl = tl .. "|%#TabLine#"
|
|
end
|
|
|
|
-- tab_id itself
|
|
tl = tl .. " t" .. tab_id
|
|
|
|
-- winnr, if present
|
|
local tp = TABPAGES[tab_id]
|
|
if tp then
|
|
tl = tl .. " w" .. tp.winnr
|
|
else
|
|
tl = tl .. " "
|
|
end
|
|
|
|
-- bufnr, if present
|
|
local bpt = BUFNR_PER_TAB[tab_id]
|
|
if bpt then
|
|
tl = tl .. " b" .. bpt
|
|
else
|
|
tl = tl .. " "
|
|
end
|
|
|
|
tl = tl .. " "
|
|
|
|
-- remove actively mapped
|
|
bufnr_per_tab[tab_id] = nil
|
|
tabpages[tab_id] = nil
|
|
end
|
|
|
|
-- close last and reset
|
|
tl = tl .. "|%#CursorLine#%T"
|
|
|
|
-- collect orphans
|
|
local orphans = {}
|
|
for tab_id, bufnr in pairs(bufnr_per_tab) do
|
|
orphans[tab_id] = orphans[tab_id] or {}
|
|
orphans[tab_id].bufnr = bufnr
|
|
end
|
|
for tab_id, tp in pairs(tabpages) do
|
|
orphans[tab_id] = orphans[tab_id] or {}
|
|
orphans[tab_id].winnr = tp.winnr
|
|
end
|
|
|
|
-- right-align
|
|
tl = tl .. "%=%#TabLine#"
|
|
|
|
-- print orphans
|
|
for tab_id, orphan in pairs(orphans) do
|
|
-- inexistent tab
|
|
tl = tl .. "%#error#| t" .. tab_id
|
|
|
|
-- maybe winnr
|
|
if orphan.winnr then
|
|
tl = tl .. " w" .. orphan.winnr
|
|
else
|
|
tl = tl .. " "
|
|
end
|
|
|
|
-- maybe bufnr
|
|
if orphan.bufnr then
|
|
tl = tl .. " b" .. orphan.bufnr
|
|
else
|
|
tl = tl .. " "
|
|
end
|
|
tl = tl .. " "
|
|
end
|
|
|
|
-- target win id and close button
|
|
tl = tl .. "|%#TabLine# twi" .. (require("nvim-tree.lib").target_winid or "?") .. " %999X| X |"
|
|
|
|
return tl
|
|
end
|
|
|
|
-- The initial state of a tab
|
|
local tabinitial = {
|
|
-- The position of the cursor { line, column }
|
|
cursor = { 0, 0 },
|
|
-- The NvimTree window number
|
|
winnr = nil,
|
|
}
|
|
|
|
---@param bufnr integer
|
|
---@return boolean
|
|
local function matches_bufnr(bufnr)
|
|
for _, b in pairs(BUFNR_PER_TAB) do
|
|
if b == bufnr then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function M.wipe_rogue_buffer()
|
|
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
|
|
if not matches_bufnr(bufnr) and utils.is_nvim_tree_buf(bufnr) then
|
|
pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
|
|
end
|
|
end
|
|
end
|
|
|
|
---@param bufnr integer|boolean|nil
|
|
---@return integer tab
|
|
function M.create_buffer(bufnr)
|
|
local tab = vim.api.nvim_get_current_tabpage()
|
|
BUFNR_PER_TAB[tab] = bufnr or vim.api.nvim_create_buf(false, false)
|
|
return tab
|
|
end
|
|
|
|
-- setup_tabpage sets up the initial state of a tab
|
|
---@param tabpage integer
|
|
function M.setup_tabpage(tabpage)
|
|
local winnr = vim.api.nvim_get_current_win()
|
|
TABPAGES[tabpage] = vim.tbl_extend("force", TABPAGES[tabpage] or tabinitial, { winnr = winnr })
|
|
end
|
|
|
|
-- save_tab_state saves any state that should be preserved across redraws.
|
|
---@param tabnr integer
|
|
function M.save_tab_state(tabnr)
|
|
local tabpage = tabnr or vim.api.nvim_get_current_tabpage()
|
|
CURSORS[tabpage] = vim.api.nvim_win_get_cursor(M.get_winnr(tabpage) or 0)
|
|
end
|
|
|
|
---@param fn fun(tabpage: integer)
|
|
function M.all_tabs_callback(fn)
|
|
for tabpage, _ in pairs(TABPAGES) do
|
|
fn(tabpage)
|
|
end
|
|
end
|
|
|
|
function M.set_current_win()
|
|
local current_tab = vim.api.nvim_get_current_tabpage()
|
|
TABPAGES[current_tab].winnr = vim.api.nvim_get_current_win()
|
|
end
|
|
|
|
function M.abandon_current_window()
|
|
local tab = vim.api.nvim_get_current_tabpage()
|
|
BUFNR_PER_TAB[tab] = nil
|
|
if TABPAGES[tab] then
|
|
TABPAGES[tab].winnr = nil
|
|
end
|
|
end
|
|
|
|
function M.abandon_all_windows()
|
|
for tab, _ in pairs(vim.api.nvim_list_tabpages()) do
|
|
BUFNR_PER_TAB[tab] = nil
|
|
if TABPAGES[tab] then
|
|
TABPAGES[tab].winnr = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
---@param opts table|nil
|
|
---@return boolean
|
|
function M.is_visible(opts)
|
|
if opts and opts.tabpage then
|
|
if TABPAGES[opts.tabpage] == nil then
|
|
return false
|
|
end
|
|
local winnr = TABPAGES[opts.tabpage].winnr
|
|
return winnr and vim.api.nvim_win_is_valid(winnr)
|
|
end
|
|
|
|
if opts and opts.any_tabpage then
|
|
for _, v in pairs(TABPAGES) do
|
|
if v.winnr and vim.api.nvim_win_is_valid(v.winnr) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
return M.get_winnr() ~= nil and vim.api.nvim_win_is_valid(M.get_winnr() or 0)
|
|
end
|
|
|
|
---@param opts table|nil
|
|
function M.set_cursor(opts)
|
|
if M.is_visible() then
|
|
pcall(vim.api.nvim_win_set_cursor, M.get_winnr(), opts)
|
|
end
|
|
end
|
|
|
|
--- Retrieve the winid of the open tree.
|
|
---@param opts ApiTreeWinIdOpts|nil
|
|
---@return number|nil winid unlike get_winnr(), this returns nil if the nvim-tree window is not visible
|
|
function M.winid(opts)
|
|
local tabpage = opts and opts.tabpage
|
|
if tabpage == 0 then
|
|
tabpage = vim.api.nvim_get_current_tabpage()
|
|
end
|
|
if M.is_visible({ tabpage = tabpage }) then
|
|
return M.get_winnr(tabpage)
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
--- Restores the state of a NvimTree window if it was initialized before.
|
|
function M.restore_tab_state()
|
|
local tabpage = vim.api.nvim_get_current_tabpage()
|
|
M.set_cursor(CURSORS[tabpage])
|
|
end
|
|
|
|
--- Returns the window number for nvim-tree within the tabpage specified
|
|
---@param tabpage number|nil (optional) the number of the chosen tabpage. Defaults to current tabpage.
|
|
---@return number|nil
|
|
function M.get_winnr(tabpage)
|
|
tabpage = tabpage or vim.api.nvim_get_current_tabpage()
|
|
local tabinfo = TABPAGES[tabpage]
|
|
if tabinfo and tabinfo.winnr and vim.api.nvim_win_is_valid(tabinfo.winnr) then
|
|
return tabinfo.winnr
|
|
end
|
|
end
|
|
|
|
--- Returns the current nvim tree bufnr
|
|
---@return number
|
|
function M.get_bufnr()
|
|
return BUFNR_PER_TAB[vim.api.nvim_get_current_tabpage()]
|
|
end
|
|
|
|
---@param winnr number|nil
|
|
function M.clear_tabpage(winnr)
|
|
for i, tabpage in ipairs(TABPAGES) do
|
|
if tabpage.winnr == winnr then
|
|
TABPAGES[i] = nil
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
return M
|