feat: better handling of ignored files
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
# git.yazi
|
# git.yazi
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Yazi v0.3.2 or later is required for this plugin to work.
|
||||||
|
|
||||||
Show the status of Git file changes as linemode in the file list.
|
Show the status of Git file changes as linemode in the file list.
|
||||||
|
|
||||||
https://github.com/user-attachments/assets/34976be9-a871-4ffe-9d5a-c4cdd0bf4576
|
https://github.com/user-attachments/assets/34976be9-a871-4ffe-9d5a-c4cdd0bf4576
|
||||||
|
|||||||
@@ -11,11 +11,15 @@ local PATS = {
|
|||||||
local function match(line)
|
local function match(line)
|
||||||
local signs = line:sub(1, 2)
|
local signs = line:sub(1, 2)
|
||||||
for _, p in ipairs(PATS) do
|
for _, p in ipairs(PATS) do
|
||||||
if not signs:find(p[1]) then
|
local path
|
||||||
elseif line:sub(4, 4) == '"' then
|
if signs:find(p[1]) then
|
||||||
return p[2], line:sub(5, -2)
|
path = line:sub(4, 4) == '"' and line:sub(5, -2) or line:sub(4)
|
||||||
|
end
|
||||||
|
if not path then
|
||||||
|
elseif path:find("[/\\]$") then
|
||||||
|
return p[2] == 3 and 30 or p[2], path:sub(1, -2)
|
||||||
else
|
else
|
||||||
return p[2], line:sub(4)
|
return p[2], path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -30,38 +34,73 @@ local function root(cwd)
|
|||||||
until not cwd
|
until not cwd
|
||||||
end
|
end
|
||||||
|
|
||||||
local add = ya.sync(function(st, cwd, repo, changes)
|
local function bubble_up(changed)
|
||||||
st.repos[cwd] = repo
|
local new, empty = {}, Url("")
|
||||||
st.changes[repo] = st.changes[repo] or {}
|
for k, v in pairs(changed) do
|
||||||
for k, v in pairs(changes) do
|
if v ~= 3 and v ~= 30 then
|
||||||
st.changes[repo][k] = v ~= 0 and v or nil
|
local url = Url(k):parent()
|
||||||
|
while url and url ~= empty do
|
||||||
|
local s = tostring(url)
|
||||||
|
new[s] = (new[s] or 0) > v and new[s] or v
|
||||||
|
url = url:parent()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return new
|
||||||
|
end
|
||||||
|
|
||||||
|
local function propagate_down(ignored, cwd, repo)
|
||||||
|
local new, rel = {}, cwd:strip_prefix(repo)
|
||||||
|
for k, v in pairs(ignored) do
|
||||||
|
if v == 30 then
|
||||||
|
if rel:starts_with(k) then
|
||||||
|
new[tostring(repo:join(rel))] = 30
|
||||||
|
elseif cwd == repo:join(k):parent() then
|
||||||
|
new[k] = 3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return new
|
||||||
|
end
|
||||||
|
|
||||||
|
local add = ya.sync(function(st, cwd, repo, changed)
|
||||||
|
st.dirs[cwd] = repo
|
||||||
|
st.repos[repo] = st.repos[repo] or {}
|
||||||
|
for k, v in pairs(changed) do
|
||||||
|
if v == 0 then
|
||||||
|
st.repos[repo][k] = nil
|
||||||
|
elseif v == 30 then
|
||||||
|
st.dirs[k] = ""
|
||||||
|
else
|
||||||
|
st.repos[repo][k] = v
|
||||||
|
end
|
||||||
end
|
end
|
||||||
ya.render()
|
ya.render()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local remove = ya.sync(function(st, cwd)
|
local remove = ya.sync(function(st, cwd)
|
||||||
local repo = st.repos[cwd]
|
local dir = st.dirs[cwd]
|
||||||
if not repo then
|
if not dir then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
ya.render()
|
ya.render()
|
||||||
st.repos[cwd] = nil
|
st.dirs[cwd] = nil
|
||||||
if not st.changes[repo] then
|
if not st.repos[dir] then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, r in pairs(st.repos) do
|
for _, r in pairs(st.dirs) do
|
||||||
if r == repo then
|
if r == dir then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
st.changes[repo] = nil
|
st.repos[dir] = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function setup(st, opts)
|
local function setup(st, opts)
|
||||||
|
st.dirs = {}
|
||||||
st.repos = {}
|
st.repos = {}
|
||||||
st.changes = {}
|
|
||||||
|
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
opts.order = opts.order or 500
|
opts.order = opts.order or 500
|
||||||
@@ -80,19 +119,19 @@ local function setup(st, opts)
|
|||||||
[6] = THEME.git_modified and THEME.git_modified.icon or "*",
|
[6] = THEME.git_modified and THEME.git_modified.icon or "*",
|
||||||
[5] = THEME.git_added and THEME.git_added.icon or "+",
|
[5] = THEME.git_added and THEME.git_added.icon or "+",
|
||||||
[4] = THEME.git_untracked and THEME.git_untracked.icon or "?",
|
[4] = THEME.git_untracked and THEME.git_untracked.icon or "?",
|
||||||
[3] = THEME.git_ignored and THEME.git_ignored.icon or "",
|
[3] = THEME.git_ignored and THEME.git_ignored.icon or "!",
|
||||||
[2] = THEME.git_deleted and THEME.git_deleted.icon or "-",
|
[2] = THEME.git_deleted and THEME.git_deleted.icon or "-",
|
||||||
[1] = THEME.git_updated and THEME.git_updated.icon or "U",
|
[1] = THEME.git_updated and THEME.git_updated.icon or "U",
|
||||||
}
|
}
|
||||||
|
|
||||||
Linemode:children_add(function(self)
|
Linemode:children_add(function(self)
|
||||||
local url = self._file.url
|
local url = self._file.url
|
||||||
local repo = st.repos[tostring(url:parent())]
|
local dir = st.dirs[tostring(url:parent())]
|
||||||
if not repo then
|
local change
|
||||||
return ui.Line("")
|
if dir then
|
||||||
|
change = dir == "" and 3 or st.repos[dir][tostring(url):sub(#dir + 2)]
|
||||||
end
|
end
|
||||||
|
|
||||||
local change = st.changes[repo][tostring(url):sub(#repo + 2)]
|
|
||||||
if not change or icons[change] == "" then
|
if not change or icons[change] == "" then
|
||||||
return ui.Line("")
|
return ui.Line("")
|
||||||
elseif self._file:is_hovered() then
|
elseif self._file:is_hovered() then
|
||||||
@@ -127,37 +166,28 @@ local function fetch(self)
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local changes = {}
|
local changed, ignored = {}, {}
|
||||||
for line in output.stdout:gmatch("[^\r\n]+") do
|
for line in output.stdout:gmatch("[^\r\n]+") do
|
||||||
local sign, path = match(line)
|
local sign, path = match(line)
|
||||||
if not sign then
|
if sign == 30 then
|
||||||
elseif path:find("[/\\]$") then
|
ignored[path] = sign
|
||||||
changes[path:sub(1, -2)] = sign
|
|
||||||
else
|
else
|
||||||
changes[path] = sign
|
changed[path] = sign
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.files[1].cha.is_dir then
|
if self.files[1].cha.is_dir then
|
||||||
local parents, empty_url = {}, Url("")
|
ya.dict_merge(changed, bubble_up(changed))
|
||||||
for k, v in pairs(changes) do
|
ya.dict_merge(changed, propagate_down(ignored, cwd, Url(repo)))
|
||||||
local url = Url(k):parent()
|
else
|
||||||
while url and url ~= empty_url do
|
ya.dict_merge(changed, propagate_down(ignored, cwd, Url(repo)))
|
||||||
local s = tostring(url)
|
|
||||||
parents[s] = (parents[s] or 0) > v and parents[s] or v
|
|
||||||
url = url:parent()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for k, v in pairs(parents) do
|
|
||||||
changes[k] = v
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, p in ipairs(paths) do
|
for _, p in ipairs(paths) do
|
||||||
local s = p:sub(#repo + 2)
|
local s = p:sub(#repo + 2)
|
||||||
changes[s] = changes[s] or 0
|
changed[s] = changed[s] or 0
|
||||||
end
|
end
|
||||||
add(tostring(cwd), repo, changes)
|
add(tostring(cwd), repo, changed)
|
||||||
|
|
||||||
return 3
|
return 3
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user