feat(tabs): add tab.sync options (#1698)
* Sync closing of nvim-tree across tabs * chore: remove vim.* "requires" * Sync closing of nvim-tree across tabs * Fix api.close calls * Fix issue from merge * Implement changes * Finish todos and add close_all_tabs * silently refactor options, add doc * fix vinegar example * Refactor close to work with tabid * Close nvim tree if last buffer * close and abandon all tabs on subsequent setup calls Co-authored-by: Alexander Courtis <alex@courtis.org>
This commit is contained in:
parent
1837751efb
commit
c49499413a
@ -177,8 +177,6 @@ Subsequent calls to setup will replace the previous configuration.
|
|||||||
ignore_buffer_on_setup = false,
|
ignore_buffer_on_setup = false,
|
||||||
open_on_setup = false,
|
open_on_setup = false,
|
||||||
open_on_setup_file = false,
|
open_on_setup_file = false,
|
||||||
open_on_tab = false,
|
|
||||||
ignore_buf_on_tab_change = {},
|
|
||||||
sort_by = "name",
|
sort_by = "name",
|
||||||
root_dirs = {},
|
root_dirs = {},
|
||||||
prefer_startup_root = false,
|
prefer_startup_root = false,
|
||||||
@ -360,6 +358,13 @@ Subsequent calls to setup will replace the previous configuration.
|
|||||||
prefix = "[FILTER]: ",
|
prefix = "[FILTER]: ",
|
||||||
always_show_folders = true,
|
always_show_folders = true,
|
||||||
},
|
},
|
||||||
|
tab = {
|
||||||
|
sync = {
|
||||||
|
open = false,
|
||||||
|
close = false,
|
||||||
|
ignore = {},
|
||||||
|
},
|
||||||
|
},
|
||||||
log = {
|
log = {
|
||||||
enable = false,
|
enable = false,
|
||||||
truncate = false,
|
truncate = false,
|
||||||
@ -417,10 +422,6 @@ You can use this option if you don't want the tree to open
|
|||||||
in some scenarios (eg using vim startify).
|
in some scenarios (eg using vim startify).
|
||||||
Type: {string}, Default: `{}`
|
Type: {string}, Default: `{}`
|
||||||
|
|
||||||
*nvim-tree.ignore_buf_on_tab_change*
|
|
||||||
List of filetypes or buffer names that will prevent `open_on_tab` to open.
|
|
||||||
Type: {string}, Default: `{}`
|
|
||||||
|
|
||||||
*nvim-tree.auto_reload_on_write*
|
*nvim-tree.auto_reload_on_write*
|
||||||
Reloads the explorer every time a buffer is written to.
|
Reloads the explorer every time a buffer is written to.
|
||||||
Type: `boolean`, Default: `true`
|
Type: `boolean`, Default: `true`
|
||||||
@ -430,11 +431,6 @@ Creating a file when the cursor is on a closed folder will set the
|
|||||||
path to be inside the closed folder, otherwise the parent folder.
|
path to be inside the closed folder, otherwise the parent folder.
|
||||||
Type: `boolean`, Default: `false`
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
*nvim-tree.open_on_tab*
|
|
||||||
Opens the tree automatically when switching tabpage or opening a new tabpage
|
|
||||||
if the tree was previously open.
|
|
||||||
Type: `boolean`, Default: `false`
|
|
||||||
|
|
||||||
*nvim-tree.sort_by*
|
*nvim-tree.sort_by*
|
||||||
Changes how files within the same directory are sorted.
|
Changes how files within the same directory are sorted.
|
||||||
Can be one of `name`, `case_sensitive`, `modification_time`, `extension` or a
|
Can be one of `name`, `case_sensitive`, `modification_time`, `extension` or a
|
||||||
@ -1002,6 +998,26 @@ The filter can be cleared with the `F` key by default.
|
|||||||
Whether to filter folders or not.
|
Whether to filter folders or not.
|
||||||
Type: `boolean`, Default: `true`
|
Type: `boolean`, Default: `true`
|
||||||
|
|
||||||
|
*nvim-tree.tab*
|
||||||
|
Configuration for tab behaviour.
|
||||||
|
|
||||||
|
*nvim-tree.tab.sync*
|
||||||
|
Configuration for syncing nvim-tree across tabs.
|
||||||
|
|
||||||
|
*nvim-tree.tab.sync.open* (previously `nvim-tree.open_on_tab`)
|
||||||
|
Opens the tree automatically when switching tabpage or opening a new
|
||||||
|
tabpage if the tree was previously open.
|
||||||
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
|
*nvim-tree.tab.sync.close*
|
||||||
|
Closes the tree across all tabpages when the tree is closed.
|
||||||
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
|
*nvim-tree.tab.sync.ignore* (previously `nvim-tree.ignore_buf_on_tab_change`)
|
||||||
|
List of filetypes or buffer names on new tab that will prevent
|
||||||
|
|nvim-tree.tab.sync.open| and |nvim-tree.tab.sync.close|
|
||||||
|
Type: {string}, Default: `{}`
|
||||||
|
|
||||||
*nvim-tree.notify*
|
*nvim-tree.notify*
|
||||||
Configuration for notification.
|
Configuration for notification.
|
||||||
|
|
||||||
@ -1074,8 +1090,9 @@ You can easily implement a toggle using this too:
|
|||||||
>
|
>
|
||||||
local function toggle_replace()
|
local function toggle_replace()
|
||||||
local view = require"nvim-tree.view"
|
local view = require"nvim-tree.view"
|
||||||
|
local api = require"nvim-tree.api"
|
||||||
if view.is_visible() then
|
if view.is_visible() then
|
||||||
view.close()
|
api.tree.close()
|
||||||
else
|
else
|
||||||
require"nvim-tree".open_replacing_current_buffer()
|
require"nvim-tree".open_replacing_current_buffer()
|
||||||
end
|
end
|
||||||
|
|||||||
@ -116,11 +116,11 @@ function M.open_replacing_current_buffer(cwd)
|
|||||||
require("nvim-tree.actions.finders.find-file").fn(bufname)
|
require("nvim-tree.actions.finders.find-file").fn(bufname)
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.tab_change()
|
function M.tab_enter()
|
||||||
if view.is_visible { any_tabpage = true } then
|
if view.is_visible { any_tabpage = true } then
|
||||||
local bufname = vim.api.nvim_buf_get_name(0)
|
local bufname = vim.api.nvim_buf_get_name(0)
|
||||||
local ft = vim.api.nvim_buf_get_option(0, "ft")
|
local ft = vim.api.nvim_buf_get_option(0, "ft")
|
||||||
for _, filter in ipairs(M.config.ignore_buf_on_tab_change) do
|
for _, filter in ipairs(M.config.tab.sync.ignore) do
|
||||||
if bufname:match(filter) ~= nil or ft:match(filter) ~= nil then
|
if bufname:match(filter) ~= nil or ft:match(filter) ~= nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -360,8 +360,8 @@ local function setup_autocommands(opts)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
if opts.open_on_tab then
|
if opts.tab.sync.open then
|
||||||
create_nvim_tree_autocmd("TabEnter", { callback = vim.schedule_wrap(M.tab_change) })
|
create_nvim_tree_autocmd("TabEnter", { callback = vim.schedule_wrap(M.tab_enter) })
|
||||||
end
|
end
|
||||||
if opts.hijack_cursor then
|
if opts.hijack_cursor then
|
||||||
create_nvim_tree_autocmd("CursorMoved", {
|
create_nvim_tree_autocmd("CursorMoved", {
|
||||||
@ -455,8 +455,6 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
ignore_buffer_on_setup = false,
|
ignore_buffer_on_setup = false,
|
||||||
open_on_setup = false,
|
open_on_setup = false,
|
||||||
open_on_setup_file = false,
|
open_on_setup_file = false,
|
||||||
open_on_tab = false,
|
|
||||||
ignore_buf_on_tab_change = {},
|
|
||||||
sort_by = "name",
|
sort_by = "name",
|
||||||
root_dirs = {},
|
root_dirs = {},
|
||||||
prefer_startup_root = false,
|
prefer_startup_root = false,
|
||||||
@ -638,6 +636,13 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
prefix = "[FILTER]: ",
|
prefix = "[FILTER]: ",
|
||||||
always_show_folders = true,
|
always_show_folders = true,
|
||||||
},
|
},
|
||||||
|
tab = {
|
||||||
|
sync = {
|
||||||
|
open = false,
|
||||||
|
close = false,
|
||||||
|
ignore = {},
|
||||||
|
},
|
||||||
|
},
|
||||||
notify = {
|
notify = {
|
||||||
threshold = vim.log.levels.INFO,
|
threshold = vim.log.levels.INFO,
|
||||||
},
|
},
|
||||||
@ -737,7 +742,6 @@ function M.setup(conf)
|
|||||||
_config.open_on_setup_file = opts.open_on_setup_file
|
_config.open_on_setup_file = opts.open_on_setup_file
|
||||||
_config.ignore_buffer_on_setup = opts.ignore_buffer_on_setup
|
_config.ignore_buffer_on_setup = opts.ignore_buffer_on_setup
|
||||||
_config.ignore_ft_on_setup = opts.ignore_ft_on_setup
|
_config.ignore_ft_on_setup = opts.ignore_ft_on_setup
|
||||||
_config.ignore_buf_on_tab_change = opts.ignore_buf_on_tab_change
|
|
||||||
_config.hijack_directories = opts.hijack_directories
|
_config.hijack_directories = opts.hijack_directories
|
||||||
_config.hijack_directories.enable = _config.hijack_directories.enable and netrw_disabled
|
_config.hijack_directories.enable = _config.hijack_directories.enable and netrw_disabled
|
||||||
|
|
||||||
@ -772,9 +776,9 @@ function M.setup(conf)
|
|||||||
setup_vim_commands()
|
setup_vim_commands()
|
||||||
end
|
end
|
||||||
|
|
||||||
if M.setup_called and view.is_visible() then
|
if M.setup_called then
|
||||||
view.close()
|
view.close_all_tabs()
|
||||||
view.abandon_current_window()
|
view.abandon_all_windows()
|
||||||
end
|
end
|
||||||
|
|
||||||
if M.setup_called and core.get_explorer() ~= nil then
|
if M.setup_called and core.get_explorer() ~= nil then
|
||||||
|
|||||||
@ -18,6 +18,8 @@ end
|
|||||||
Api.tree.open = require("nvim-tree").open
|
Api.tree.open = require("nvim-tree").open
|
||||||
Api.tree.toggle = require("nvim-tree").toggle
|
Api.tree.toggle = require("nvim-tree").toggle
|
||||||
Api.tree.close = require("nvim-tree.view").close
|
Api.tree.close = require("nvim-tree.view").close
|
||||||
|
Api.tree.close_in_this_tab = require("nvim-tree.view").close_this_tab_only
|
||||||
|
Api.tree.close_in_all_tabs = require("nvim-tree.view").close_all_tabs
|
||||||
Api.tree.focus = require("nvim-tree").focus
|
Api.tree.focus = require("nvim-tree").focus
|
||||||
Api.tree.reload = require("nvim-tree.actions.reloaders.reloaders").reload_explorer
|
Api.tree.reload = require("nvim-tree.actions.reloaders.reloaders").reload_explorer
|
||||||
Api.tree.change_root = require("nvim-tree").change_dir
|
Api.tree.change_root = require("nvim-tree").change_dir
|
||||||
|
|||||||
@ -289,6 +289,11 @@ local function refactored(opts)
|
|||||||
-- 2022/06/20
|
-- 2022/06/20
|
||||||
utils.move_missing_val(opts, "update_focused_file", "update_cwd", opts, "update_focused_file", "update_root")
|
utils.move_missing_val(opts, "update_focused_file", "update_cwd", opts, "update_focused_file", "update_root")
|
||||||
utils.move_missing_val(opts, "", "update_cwd", opts, "", "sync_root_with_cwd")
|
utils.move_missing_val(opts, "", "update_cwd", opts, "", "sync_root_with_cwd")
|
||||||
|
|
||||||
|
-- 2022/11/07
|
||||||
|
utils.move_missing_val(opts, "", "open_on_tab", opts, "tab.sync", "open", false)
|
||||||
|
utils.move_missing_val(opts, "", "open_on_tab", opts, "tab.sync", "close")
|
||||||
|
utils.move_missing_val(opts, "", "ignore_buf_on_tab_change", opts, "tab.sync", "ignore")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function removed(opts)
|
local function removed(opts)
|
||||||
|
|||||||
@ -117,7 +117,7 @@ function M.open(cwd)
|
|||||||
core.init(cwd or vim.loop.cwd())
|
core.init(cwd or vim.loop.cwd())
|
||||||
end
|
end
|
||||||
if should_hijack_current_buf() then
|
if should_hijack_current_buf() then
|
||||||
view.close()
|
view.close_this_tab_only()
|
||||||
view.open_in_current_win()
|
view.open_in_current_win()
|
||||||
renderer.draw()
|
renderer.draw()
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
local Iterator = require "nvim-tree.iterators.node-iterator"
|
local Iterator = require "nvim-tree.iterators.node-iterator"
|
||||||
|
local notify = require "nvim-tree.notify"
|
||||||
|
|
||||||
local M = {
|
local M = {
|
||||||
debouncers = {},
|
debouncers = {},
|
||||||
@ -266,14 +267,20 @@ function M.table_create_missing(tbl, path)
|
|||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Move a value from src to dst if value is nil on dst
|
--- Move a value from src to dst if value is nil on dst.
|
||||||
-- @param src to copy from
|
--- Remove value from src
|
||||||
-- @param src_path dot separated string of sub-tables
|
--- @param src table to copy from
|
||||||
-- @param src_pos value pos
|
--- @param src_path string dot separated string of sub-tables
|
||||||
-- @param dst to copy to
|
--- @param src_pos string value pos
|
||||||
-- @param dst_path dot separated string of sub-tables, created when missing
|
--- @param dst table to copy to
|
||||||
-- @param dst_pos value pos
|
--- @param dst_path string dot separated string of sub-tables, created when missing
|
||||||
function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos)
|
--- @param dst_pos string value pos
|
||||||
|
--- @param remove boolean default true
|
||||||
|
function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos, remove)
|
||||||
|
if remove == nil then
|
||||||
|
remove = true
|
||||||
|
end
|
||||||
|
|
||||||
local ok, err = pcall(vim.validate, {
|
local ok, err = pcall(vim.validate, {
|
||||||
src = { src, "table" },
|
src = { src, "table" },
|
||||||
src_path = { src_path, "string" },
|
src_path = { src_path, "string" },
|
||||||
@ -281,9 +288,11 @@ function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos)
|
|||||||
dst = { dst, "table" },
|
dst = { dst, "table" },
|
||||||
dst_path = { dst_path, "string" },
|
dst_path = { dst_path, "string" },
|
||||||
dst_pos = { dst_pos, "string" },
|
dst_pos = { dst_pos, "string" },
|
||||||
|
remove = { remove, "boolean" },
|
||||||
})
|
})
|
||||||
if not ok then
|
if not ok then
|
||||||
M.notify.warn("move_missing_val: " .. (err or "invalid arguments"))
|
notify.warn("move_missing_val: " .. (err or "invalid arguments"))
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for pos in string.gmatch(src_path, "([^%.]+)%.*") do
|
for pos in string.gmatch(src_path, "([^%.]+)%.*") do
|
||||||
@ -304,7 +313,9 @@ function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos)
|
|||||||
dst[dst_pos] = src_val
|
dst[dst_pos] = src_val
|
||||||
end
|
end
|
||||||
|
|
||||||
src[src_pos] = nil
|
if remove then
|
||||||
|
src[src_pos] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.format_bytes(bytes)
|
function M.format_bytes(bytes)
|
||||||
|
|||||||
@ -179,21 +179,21 @@ local function switch_buf_if_last_buf()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- save_tab_state saves any state that should be preserved across redraws.
|
-- save_tab_state saves any state that should be preserved across redraws.
|
||||||
local function save_tab_state()
|
local function save_tab_state(tabnr)
|
||||||
local tabpage = vim.api.nvim_get_current_tabpage()
|
local tabpage = tabnr or vim.api.nvim_get_current_tabpage()
|
||||||
M.View.cursors[tabpage] = vim.api.nvim_win_get_cursor(M.get_winnr())
|
M.View.cursors[tabpage] = vim.api.nvim_win_get_cursor(M.get_winnr(tabpage))
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.close()
|
local function close(tabpage)
|
||||||
if not M.is_visible() then
|
if not M.is_visible { tabpage = tabpage } then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
save_tab_state()
|
save_tab_state(tabpage)
|
||||||
switch_buf_if_last_buf()
|
switch_buf_if_last_buf()
|
||||||
local tree_win = M.get_winnr()
|
local tree_win = M.get_winnr(tabpage)
|
||||||
local current_win = vim.api.nvim_get_current_win()
|
local current_win = vim.api.nvim_get_current_win()
|
||||||
for _, win in pairs(vim.api.nvim_list_wins()) do
|
for _, win in pairs(vim.api.nvim_tabpage_list_wins(tabpage)) do
|
||||||
if tree_win ~= win and vim.api.nvim_win_get_config(win).relative == "" then
|
if vim.api.nvim_win_get_config(win).relative == "" then
|
||||||
local prev_win = vim.fn.winnr "#" -- this tab only
|
local prev_win = vim.fn.winnr "#" -- this tab only
|
||||||
if tree_win == current_win and prev_win > 0 then
|
if tree_win == current_win and prev_win > 0 then
|
||||||
vim.api.nvim_set_current_win(vim.fn.win_getid(prev_win))
|
vim.api.nvim_set_current_win(vim.fn.win_getid(prev_win))
|
||||||
@ -207,6 +207,24 @@ function M.close()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.close_this_tab_only()
|
||||||
|
close(vim.api.nvim_get_current_tabpage())
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.close_all_tabs()
|
||||||
|
for tabpage, _ in pairs(M.View.tabpages) do
|
||||||
|
close(tabpage)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.close()
|
||||||
|
if M.View.tab.sync.close then
|
||||||
|
M.close_all_tabs()
|
||||||
|
else
|
||||||
|
M.close_this_tab_only()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function M.open(options)
|
function M.open(options)
|
||||||
if M.is_visible() then
|
if M.is_visible() then
|
||||||
return
|
return
|
||||||
@ -308,10 +326,29 @@ end
|
|||||||
function M.abandon_current_window()
|
function M.abandon_current_window()
|
||||||
local tab = vim.api.nvim_get_current_tabpage()
|
local tab = vim.api.nvim_get_current_tabpage()
|
||||||
BUFNR_PER_TAB[tab] = nil
|
BUFNR_PER_TAB[tab] = nil
|
||||||
M.View.tabpages[tab].winnr = nil
|
if M.View.tabpages[tab] then
|
||||||
|
M.View.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 M.View.tabpages[tab] then
|
||||||
|
M.View.tabpages[tab].winnr = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.is_visible(opts)
|
function M.is_visible(opts)
|
||||||
|
if opts and opts.tabpage then
|
||||||
|
if M.View.tabpages[opts.tabpage] == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local winnr = M.View.tabpages[opts.tabpage].winnr
|
||||||
|
return winnr and vim.api.nvim_win_is_valid(winnr)
|
||||||
|
end
|
||||||
|
|
||||||
if opts and opts.any_tabpage then
|
if opts and opts.any_tabpage then
|
||||||
for _, v in pairs(M.View.tabpages) do
|
for _, v in pairs(M.View.tabpages) do
|
||||||
if v.winnr and vim.api.nvim_win_is_valid(v.winnr) then
|
if v.winnr and vim.api.nvim_win_is_valid(v.winnr) then
|
||||||
@ -450,6 +487,7 @@ function M.setup(opts)
|
|||||||
M.View.height = options.height
|
M.View.height = options.height
|
||||||
M.View.initial_width = get_size()
|
M.View.initial_width = get_size()
|
||||||
M.View.hide_root_folder = options.hide_root_folder
|
M.View.hide_root_folder = options.hide_root_folder
|
||||||
|
M.View.tab = opts.tab
|
||||||
M.View.preserve_window_proportions = options.preserve_window_proportions
|
M.View.preserve_window_proportions = options.preserve_window_proportions
|
||||||
M.View.winopts.number = options.number
|
M.View.winopts.number = options.number
|
||||||
M.View.winopts.relativenumber = options.relativenumber
|
M.View.winopts.relativenumber = options.relativenumber
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user