fix(git): git folder fixes and improvements (#1809)
* coding style
* outlined git.show_on_open_dirs behavior
* show some icon on opendir even if show_on_open_dir=false
and show all children's status on parent
* fixed renamed icon not showing
* sorted icons
* removed DU from deleted as file will show up in tree
* fixed update_git_status in reloaders not tested
* fixed Api.git.reload()
Tested update_git_status in reloaders.lua
* sort icon only if not git signcolumn
* fixed crashing when root dir isn't git dir
* made git.show_on_dirs doc more concise
* git_statuses -> git_status for consistency
* explorer/common.lua -> explorer/node.lua
* fixed #1784 conflict
* don't order icons
* Revert "don't order icons"
This reverts commit 23f6276ef7.
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
local M = {}
|
||||
|
||||
local function get_dir_git_status(parent_ignored, status, absolute_path)
|
||||
if parent_ignored then
|
||||
return "!!"
|
||||
end
|
||||
|
||||
local file_status = status.files and status.files[absolute_path]
|
||||
if file_status then
|
||||
return file_status
|
||||
end
|
||||
|
||||
return status.dirs and status.dirs[absolute_path]
|
||||
end
|
||||
|
||||
local function get_git_status(parent_ignored, status, absolute_path)
|
||||
return parent_ignored and "!!" or status.files and status.files[absolute_path]
|
||||
end
|
||||
|
||||
function M.has_one_child_folder(node)
|
||||
return #node.nodes == 1 and node.nodes[1].nodes and vim.loop.fs_access(node.nodes[1].absolute_path, "R")
|
||||
end
|
||||
|
||||
function M.update_git_status(node, parent_ignored, status)
|
||||
-- status of the node's absolute path
|
||||
if node.nodes then
|
||||
node.git_status = get_dir_git_status(parent_ignored, status, node.absolute_path)
|
||||
else
|
||||
node.git_status = get_git_status(parent_ignored, status, node.absolute_path)
|
||||
end
|
||||
|
||||
-- status of the link target, if the link itself is not dirty
|
||||
if node.link_to and not node.git_status then
|
||||
if node.nodes then
|
||||
node.git_status = get_dir_git_status(parent_ignored, status, node.link_to)
|
||||
else
|
||||
node.git_status = get_git_status(parent_ignored, status, node.link_to)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.shows_git_status(node)
|
||||
if not node.git_status then
|
||||
-- status doesn't exist
|
||||
return false
|
||||
elseif not node.nodes then
|
||||
-- status exist and is a file
|
||||
return true
|
||||
elseif not node.open then
|
||||
-- status exist, is a closed dir
|
||||
return M.config.git.show_on_dirs
|
||||
else
|
||||
-- status exist, is a open dir
|
||||
return M.config.git.show_on_dirs and M.config.git.show_on_open_dirs
|
||||
end
|
||||
end
|
||||
|
||||
function M.node_destroy(node)
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
|
||||
if node.watcher then
|
||||
node.watcher:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function M.setup(opts)
|
||||
M.config = {
|
||||
git = opts.git,
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -1,6 +1,6 @@
|
||||
local utils = require "nvim-tree.utils"
|
||||
local builders = require "nvim-tree.explorer.node-builders"
|
||||
local common = require "nvim-tree.explorer.common"
|
||||
local explorer_node = require "nvim-tree.explorer.node"
|
||||
local sorters = require "nvim-tree.explorer.sorters"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local live_filter = require "nvim-tree.live-filter"
|
||||
@@ -14,7 +14,7 @@ local function get_type_from(type_, cwd)
|
||||
end
|
||||
|
||||
local function populate_children(handle, cwd, node, git_status)
|
||||
local node_ignored = node.git_status == "!!"
|
||||
local node_ignored = explorer_node.is_git_ignored(node)
|
||||
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
|
||||
local filter_status = filters.prepare(git_status)
|
||||
while true do
|
||||
@@ -40,7 +40,7 @@ local function populate_children(handle, cwd, node, git_status)
|
||||
if child then
|
||||
table.insert(node.nodes, child)
|
||||
nodes_by_path[child.absolute_path] = true
|
||||
common.update_git_status(child, node_ignored, git_status)
|
||||
explorer_node.update_git_status(child, node_ignored, git_status)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -68,7 +68,7 @@ function M.explore(node, status)
|
||||
populate_children(handle, cwd, node, status)
|
||||
|
||||
local is_root = not node.parent
|
||||
local child_folder_only = common.has_one_child_folder(node) and node.nodes[1]
|
||||
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
|
||||
if M.config.group_empty and not is_root and child_folder_only then
|
||||
node.group_next = child_folder_only
|
||||
local ns = M.explore(child_folder_only, status)
|
||||
|
||||
@@ -24,7 +24,9 @@ local function git(path, git_status)
|
||||
end
|
||||
|
||||
-- default status to clean
|
||||
local status = git_status.files[path] or git_status.dirs[path] or " "
|
||||
local status = git_status.files[path]
|
||||
status = status or git_status.dirs.direct[path] and git_status.dirs.direct[path][1]
|
||||
status = status or git_status.dirs.indirect[path] and git_status.dirs.indirect[path][1]
|
||||
|
||||
-- filter ignored; overrides clean as they are effectively dirty
|
||||
if M.config.filter_git_ignored and status == "!!" then
|
||||
@@ -32,7 +34,7 @@ local function git(path, git_status)
|
||||
end
|
||||
|
||||
-- filter clean
|
||||
if M.config.filter_git_clean and status == " " then
|
||||
if M.config.filter_git_clean and not status then
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
local git = require "nvim-tree.git"
|
||||
local watch = require "nvim-tree.explorer.watch"
|
||||
local common = require "nvim-tree.explorer.common"
|
||||
local explorer_node = require "nvim-tree.explorer.node"
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -24,8 +24,8 @@ end
|
||||
|
||||
function Explorer:_load(node)
|
||||
local cwd = node.link_to or node.absolute_path
|
||||
local git_statuses = git.load_project_status(cwd)
|
||||
M.explore(node, git_statuses)
|
||||
local git_status = git.load_project_status(cwd)
|
||||
M.explore(node, git_status)
|
||||
end
|
||||
|
||||
function Explorer:expand(node)
|
||||
@@ -34,7 +34,7 @@ end
|
||||
|
||||
function Explorer:destroy()
|
||||
local function iterate(node)
|
||||
common.node_destroy(node)
|
||||
explorer_node.node_destroy(node)
|
||||
if node.nodes then
|
||||
for _, child in pairs(node.nodes) do
|
||||
iterate(child)
|
||||
@@ -45,7 +45,7 @@ function Explorer:destroy()
|
||||
end
|
||||
|
||||
function M.setup(opts)
|
||||
require("nvim-tree.explorer.common").setup(opts)
|
||||
require("nvim-tree.explorer.node").setup(opts)
|
||||
require("nvim-tree.explorer.explore").setup(opts)
|
||||
require("nvim-tree.explorer.filters").setup(opts)
|
||||
require("nvim-tree.explorer.sorters").setup(opts)
|
||||
|
||||
133
lua/nvim-tree/explorer/node.lua
Normal file
133
lua/nvim-tree/explorer/node.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
local M = {}
|
||||
|
||||
-- node.git_status structure:
|
||||
-- {
|
||||
-- file = string | nil,
|
||||
-- dir = {
|
||||
-- direct = { string } | nil,
|
||||
-- indirect = { string } | nil,
|
||||
-- } | nil,
|
||||
-- }
|
||||
|
||||
local function get_dir_git_status(parent_ignored, status, absolute_path)
|
||||
if parent_ignored then
|
||||
return { file = "!!" }
|
||||
end
|
||||
|
||||
return {
|
||||
file = status.files and status.files[absolute_path],
|
||||
dir = status.dirs and {
|
||||
direct = status.dirs.direct[absolute_path],
|
||||
indirect = status.dirs.indirect[absolute_path],
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function get_git_status(parent_ignored, status, absolute_path)
|
||||
local file_status = parent_ignored and "!!" or status.files and status.files[absolute_path]
|
||||
return { file = file_status }
|
||||
end
|
||||
|
||||
function M.has_one_child_folder(node)
|
||||
return #node.nodes == 1 and node.nodes[1].nodes and vim.loop.fs_access(node.nodes[1].absolute_path, "R")
|
||||
end
|
||||
|
||||
function M.update_git_status(node, parent_ignored, status)
|
||||
local get_status
|
||||
if node.nodes then
|
||||
get_status = get_dir_git_status
|
||||
else
|
||||
get_status = get_git_status
|
||||
end
|
||||
|
||||
-- status of the node's absolute path
|
||||
node.git_status = get_status(parent_ignored, status, node.absolute_path)
|
||||
|
||||
-- status of the link target, if the link itself is not dirty
|
||||
if node.link_to and not node.git_status then
|
||||
node.git_status = get_status(parent_ignored, status, node.link_to)
|
||||
end
|
||||
end
|
||||
|
||||
function M.get_git_status(node)
|
||||
local git_status = node.git_status
|
||||
if not git_status then
|
||||
-- status doesn't exist
|
||||
return nil
|
||||
end
|
||||
|
||||
if not node.nodes then
|
||||
-- file
|
||||
return git_status.file and { git_status.file }
|
||||
end
|
||||
|
||||
-- dir
|
||||
if not M.config.git.show_on_dirs then
|
||||
return nil
|
||||
end
|
||||
|
||||
local status = {}
|
||||
if not node.open or M.config.git.show_on_open_dirs then
|
||||
-- dir is closed or we should show on open_dirs
|
||||
if git_status.file ~= nil then
|
||||
table.insert(status, git_status.file)
|
||||
end
|
||||
if git_status.dir ~= nil then
|
||||
if git_status.dir.direct ~= nil then
|
||||
for _, s in pairs(node.git_status.dir.direct) do
|
||||
table.insert(status, s)
|
||||
end
|
||||
end
|
||||
if git_status.dir.indirect ~= nil then
|
||||
for _, s in pairs(node.git_status.dir.indirect) do
|
||||
table.insert(status, s)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- dir is open and we shouldn't show on open_dirs
|
||||
if git_status.file ~= nil then
|
||||
table.insert(status, git_status.file)
|
||||
end
|
||||
if git_status.dir ~= nil and git_status.dir.direct ~= nil then
|
||||
local deleted = {
|
||||
[" D"] = true,
|
||||
["D "] = true,
|
||||
["RD"] = true,
|
||||
["DD"] = true,
|
||||
}
|
||||
for _, s in pairs(node.git_status.dir.direct) do
|
||||
if deleted[s] then
|
||||
table.insert(status, s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if #status == 0 then
|
||||
return nil
|
||||
else
|
||||
return status
|
||||
end
|
||||
end
|
||||
|
||||
function M.is_git_ignored(node)
|
||||
return node.git_status and node.git_status.file == "!!"
|
||||
end
|
||||
|
||||
function M.node_destroy(node)
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
|
||||
if node.watcher then
|
||||
node.watcher:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function M.setup(opts)
|
||||
M.config = {
|
||||
git = opts.git,
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -1,6 +1,6 @@
|
||||
local utils = require "nvim-tree.utils"
|
||||
local builders = require "nvim-tree.explorer.node-builders"
|
||||
local common = require "nvim-tree.explorer.common"
|
||||
local explorer_node = require "nvim-tree.explorer.node"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local sorters = require "nvim-tree.explorer.sorters"
|
||||
local live_filter = require "nvim-tree.live-filter"
|
||||
@@ -15,7 +15,7 @@ local M = {}
|
||||
local function update_status(nodes_by_path, node_ignored, status)
|
||||
return function(node)
|
||||
if nodes_by_path[node.absolute_path] then
|
||||
common.update_git_status(node, node_ignored, status)
|
||||
explorer_node.update_git_status(node, node_ignored, status)
|
||||
end
|
||||
return node
|
||||
end
|
||||
@@ -29,7 +29,7 @@ end
|
||||
|
||||
local function update_parent_statuses(node, project, root)
|
||||
while project and node and node.absolute_path ~= root do
|
||||
common.update_git_status(node, false, project)
|
||||
explorer_node.update_git_status(node, false, project)
|
||||
node = node.parent
|
||||
end
|
||||
end
|
||||
@@ -53,7 +53,7 @@ function M.reload(node, git_status, unloaded_bufnr)
|
||||
|
||||
local child_names = {}
|
||||
|
||||
local node_ignored = node.git_status == "!!"
|
||||
local node_ignored = explorer_node.is_git_ignored(node)
|
||||
local nodes_by_path = utils.key_by(node.nodes, "absolute_path")
|
||||
while true do
|
||||
local name, t = utils.fs_scandir_next_profiled(handle, cwd)
|
||||
@@ -82,7 +82,7 @@ function M.reload(node, git_status, unloaded_bufnr)
|
||||
|
||||
if n.type ~= t then
|
||||
utils.array_remove(node.nodes, n)
|
||||
common.node_destroy(n)
|
||||
explorer_node.node_destroy(n)
|
||||
nodes_by_path[abs] = nil
|
||||
end
|
||||
end
|
||||
@@ -119,14 +119,14 @@ function M.reload(node, git_status, unloaded_bufnr)
|
||||
if child_names[n.absolute_path] then
|
||||
return child_names[n.absolute_path]
|
||||
else
|
||||
common.node_destroy(n)
|
||||
explorer_node.node_destroy(n)
|
||||
return nil
|
||||
end
|
||||
end, node.nodes)
|
||||
)
|
||||
|
||||
local is_root = not node.parent
|
||||
local child_folder_only = common.has_one_child_folder(node) and node.nodes[1]
|
||||
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
|
||||
if M.config.group_empty and not is_root and child_folder_only then
|
||||
node.group_next = child_folder_only
|
||||
local ns = M.reload(child_folder_only, git_status)
|
||||
|
||||
Reference in New Issue
Block a user