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

Improve git icons on directories #1809

Merged
merged 16 commits into from
Dec 17, 2022
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
show some icon on opendir even if show_on_open_dir=false
and show all children's status on parent
chomosuke committed Dec 12, 2022

Verified

This commit was created on github.com and signed with GitHub’s verified signature.
commit f65dc0d4e3279df0b5d29f709f216f8456eb1606
2 changes: 1 addition & 1 deletion lua/nvim-tree/actions/moves/item.lua
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ function M.fn(where, what)
for line, node in pairs(nodes_by_line) do
local valid = false
if what == "git" then
valid = explorer_common.shows_git_status(node)
valid = explorer_common.get_git_status(node) ~= nil
elseif what == "diag" then
valid = node.diag_status ~= nil
end
2 changes: 2 additions & 0 deletions lua/nvim-tree/actions/reloaders/reloaders.lua
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ end
function M.reload_node_status(parent_node, projects)
local project_root = git.get_project_root(parent_node.absolute_path)
local status = projects[project_root] or {}
require("nvim-tree.log").line("dev", "reloaders")
-- TODO: when is this called
for _, node in ipairs(parent_node.nodes) do
if node.nodes then
node.git_status = status.dirs and status.dirs[node.absolute_path]
100 changes: 81 additions & 19 deletions lua/nvim-tree/explorer/common.lua
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
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 "!!"
end

local file_status = status.files and status.files[absolute_path]
if file_status then
return file_status
return { file = "!!" }
end

return status.dirs and status.dirs[absolute_path]
return {
file = status.files and status.files[absolute_path],
dir = {
direct = status.dirs.direct[absolute_path],
indirect = status.dirs.indirect[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]
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)
@@ -38,20 +49,71 @@ function M.update_git_status(node, parent_ignored, status)
end
end

function M.shows_git_status(node)
if not node.git_status then
function M.get_git_status(node)
local git_status = node.git_status
if not 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
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
-- status exist, is a open dir
return M.config.git.show_on_dirs and M.config.git.show_on_open_dirs
-- 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,
-- TODO: test if this should be deleted
["DU"] = 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)
2 changes: 1 addition & 1 deletion lua/nvim-tree/explorer/explore.lua
Original file line number Diff line number Diff line change
@@ -13,7 +13,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 = common.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
2 changes: 1 addition & 1 deletion lua/nvim-tree/explorer/reload.lua
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ function M.reload(node, git_status, unloaded_bufnr)

local child_names = {}

local node_ignored = node.git_status == "!!"
local node_ignored = common.is_git_ignored(node)
local nodes_by_path = utils.key_by(node.nodes, "absolute_path")
while true do
local ok, name, t = pcall(vim.loop.fs_scandir_next, handle)
13 changes: 4 additions & 9 deletions lua/nvim-tree/git/init.lua
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ local git_utils = require "nvim-tree.git.utils"
local Runner = require "nvim-tree.git.runner"
local Watcher = require("nvim-tree.watcher").Watcher
local Iterator = require "nvim-tree.iterators.node-iterator"
local explorer_common = require "nvim-tree.explorer.common"

local M = {
config = {},
@@ -103,19 +104,13 @@ local function reload_tree_at(project_root)
end

M.reload_project(project_root)
local project = M.get_project(project_root)

local project_files = project.files and project.files or {}
local project_dirs = project.dirs and project.dirs or {}
local git_status = M.get_project(project_root)

Iterator.builder(root_node.nodes)
:hidden()
:applier(function(node)
local parent_ignored = node.parent.git_status == "!!"
node.git_status = project_dirs[node.absolute_path] or project_files[node.absolute_path]
if not node.git_status and parent_ignored then
node.git_status = "!!"
end
local parent_ignored = explorer_common.is_git_ignored(node.parent)
explorer_common.update_git_status(node, parent_ignored, git_status)
end)
:recursor(function(node)
return node.nodes and #node.nodes > 0 and node.nodes
35 changes: 27 additions & 8 deletions lua/nvim-tree/git/utils.lua
Original file line number Diff line number Diff line change
@@ -55,24 +55,43 @@ function M.should_show_untracked(cwd)
return untracked[cwd]
end

local function nil_insert(t, k)
t = t or {}
t[k] = true
return t
end

function M.file_status_to_dir_status(status, cwd)
local dirs = {}
local direct = {}
for p, s in pairs(status) do
if s ~= "!!" then
local modified = vim.fn.fnamemodify(p, ":h")
dirs[modified] = s
direct[modified] = nil_insert(direct[modified], s)
end
end

for dirname, s in pairs(dirs) do
local modified = dirname
while modified ~= cwd and modified ~= "/" do
modified = vim.fn.fnamemodify(modified, ":h")
dirs[modified] = s
local indirect = {}
for dirname, statuses in pairs(direct) do
for s, _ in pairs(statuses) do
local modified = dirname
while modified ~= cwd and modified ~= "/" do
modified = vim.fn.fnamemodify(modified, ":h")
indirect[modified] = nil_insert(indirect[modified], s)
end
end
end

return dirs
local r = { indirect = indirect, direct = direct }
for _, d in pairs(r) do
for dirname, statuses in pairs(d) do
local new_statuses = {}
for s, _ in pairs(statuses) do
table.insert(new_statuses, s)
end
d[dirname] = new_statuses
end
end
return r
end

return M
34 changes: 23 additions & 11 deletions lua/nvim-tree/renderer/components/git.lua
Original file line number Diff line number Diff line change
@@ -59,20 +59,32 @@ local function warn_status(git_status)
end

local function get_icons_(node)
if not explorer_common.shows_git_status(node) then
local git_statuses = explorer_common.get_git_status(node)
if git_statuses == nil then
return nil
end

local git_status = node.git_status
local icons = M.git_icons[git_status]
if not icons then
if not M.config.highlight_git then
warn_status(git_status)
local inserted = {}
local iconss = {}

for _, git_status in pairs(git_statuses) do
local icons = M.git_icons[git_status]
if not icons then
if not M.config.highlight_git then
warn_status(git_status)
end
return nil
end

for _, icon in pairs(icons) do
if not inserted[icon] then
table.insert(iconss, icon)
inserted[icon] = true
end
end
return nil
end

return icons
return iconss
end

local git_hl = {
@@ -119,12 +131,12 @@ function M.setup_signs(i)
end

local function get_highlight_(node)
local git_status = node.git_status
if not explorer_common.shows_git_status(node) then
local git_status = explorer_common.get_git_status(node)
if git_status == nil then
return
end

return git_hl[git_status]
return git_hl[git_status[1]]
end

function M.setup(opts)