Update 2026-01-27

This commit is contained in:
2026-01-27 20:50:06 +02:00
parent 8c606045e1
commit 2424bd8153
34 changed files with 2632 additions and 5066 deletions

View File

@@ -15,36 +15,41 @@ ya pkg add yazi-rs/plugins:git
Add the following to your `~/.config/yazi/init.lua`:
```lua
require("git"):setup()
require("git"):setup {
-- Order of status signs showing in the linemode
order = 1500,
}
```
And register it as fetchers in your `~/.config/yazi/yazi.toml`:
```toml
[[plugin.prepend_fetchers]]
id = "git"
name = "*"
run = "git"
id = "git"
url = "*"
run = "git"
[[plugin.prepend_fetchers]]
id = "git"
name = "*/"
run = "git"
id = "git"
url = "*/"
run = "git"
```
## Advanced
> [!NOTE]
> [!NOTE]
> The following configuration must be put before `require("git"):setup()`
You can customize the [Style](https://yazi-rs.github.io/docs/plugins/layout#style) of the status sign with:
- `th.git.modified`
- `th.git.added`
- `th.git.untracked`
- `th.git.ignored`
- `th.git.deleted`
- `th.git.updated`
- `th.git.unknown` - status cannot/not yet determined
- `th.git.modified` - modified file
- `th.git.added` - added file
- `th.git.untracked` - untracked file
- `th.git.ignored` - ignored file
- `th.git.deleted` - deleted file
- `th.git.updated` - updated file
- `th.git.clean` - clean file
For example:
@@ -57,20 +62,24 @@ th.git.deleted = ui.Style():fg("red"):bold()
You can also customize the text of the status sign with:
- `th.git.modified_sign`
- `th.git.added_sign`
- `th.git.untracked_sign`
- `th.git.ignored_sign`
- `th.git.deleted_sign`
- `th.git.updated_sign`
- `th.git.unknown_sign` - status cannot/not yet determined
- `th.git.modified_sign` - modified file
- `th.git.added_sign` - added file
- `th.git.untracked_sign` - untracked file
- `th.git.ignored_sign` - ignored file
- `th.git.deleted_sign` - deleted file
- `th.git.updated_sign` - updated file
- `th.git.clean_sign` - clean file
For example:
```lua
-- ~/.config/yazi/init.lua
th.git = th.git or {}
th.git.unknown_sign = " "
th.git.modified_sign = "M"
th.git.deleted_sign = "D"
th.git.clean_sign = ""
```
## License

View File

@@ -1,4 +1,4 @@
--- @since 25.5.31
--- @since 25.12.29
local WINDOWS = ya.target_family() == "windows"
@@ -7,14 +7,15 @@ local WINDOWS = ya.target_family() == "windows"
-- see `bubble_up`
---@enum CODES
local CODES = {
excluded = 100, -- ignored directory
unknown = 100, -- status cannot/not yet determined
excluded = 99, -- ignored directory
ignored = 6, -- ignored file
untracked = 5,
modified = 4,
added = 3,
deleted = 2,
updated = 1,
unknown = 0,
clean = 0,
}
local PATTERNS = {
@@ -79,7 +80,7 @@ local function bubble_up(changed)
local url = Url(path).parent
while url and url ~= empty do
local s = tostring(url)
new[s] = (new[s] or CODES.unknown) > code and new[s] or code
new[s] = (new[s] or CODES.clean) > code and new[s] or code
url = url.parent
end
end
@@ -116,7 +117,7 @@ local add = ya.sync(function(st, cwd, repo, changed)
st.dirs[cwd] = repo
st.repos[repo] = st.repos[repo] or {}
for path, code in pairs(changed) do
if code == CODES.unknown then
if code == CODES.clean then
st.repos[repo][path] = nil
elseif code == CODES.excluded then
-- Mark the directory with a special value `excluded` so that it can be distinguished during UI rendering
@@ -125,12 +126,7 @@ local add = ya.sync(function(st, cwd, repo, changed)
st.repos[repo][path] = code
end
end
-- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
ui.render()
end)
---@param cwd string
@@ -142,12 +138,7 @@ local remove = ya.sync(function(st, cwd)
return
end
-- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
ui.render()
st.dirs[cwd] = nil
if not st.repos[repo] then
return
@@ -172,31 +163,39 @@ local function setup(st, opts)
local t = th.git or {}
local styles = {
[CODES.ignored] = t.ignored and ui.Style(t.ignored) or ui.Style():fg("darkgray"),
[CODES.untracked] = t.untracked and ui.Style(t.untracked) or ui.Style():fg("magenta"),
[CODES.modified] = t.modified and ui.Style(t.modified) or ui.Style():fg("yellow"),
[CODES.added] = t.added and ui.Style(t.added) or ui.Style():fg("green"),
[CODES.deleted] = t.deleted and ui.Style(t.deleted) or ui.Style():fg("red"),
[CODES.updated] = t.updated and ui.Style(t.updated) or ui.Style():fg("yellow"),
[CODES.unknown] = t.unknown or ui.Style(),
[CODES.ignored] = t.ignored or ui.Style():fg("darkgray"),
[CODES.untracked] = t.untracked or ui.Style():fg("magenta"),
[CODES.modified] = t.modified or ui.Style():fg("yellow"),
[CODES.added] = t.added or ui.Style():fg("green"),
[CODES.deleted] = t.deleted or ui.Style():fg("red"),
[CODES.updated] = t.updated or ui.Style():fg("yellow"),
[CODES.clean] = t.clean or ui.Style(),
}
local signs = {
[CODES.ignored] = t.ignored_sign or "",
[CODES.untracked] = t.untracked_sign or "?",
[CODES.modified] = t.modified_sign or "",
[CODES.added] = t.added_sign or "",
[CODES.deleted] = t.deleted_sign or "",
[CODES.updated] = t.updated_sign or "",
[CODES.unknown] = t.unknown_sign or "",
[CODES.ignored] = t.ignored_sign or "",
[CODES.untracked] = t.untracked_sign or "? ",
[CODES.modified] = t.modified_sign or "",
[CODES.added] = t.added_sign or "",
[CODES.deleted] = t.deleted_sign or "",
[CODES.updated] = t.updated_sign or "",
[CODES.clean] = t.clean_sign or "",
}
Linemode:children_add(function(self)
local url = self._file.url
local repo = st.dirs[tostring(url.base)]
local code
if repo then
code = repo == CODES.excluded and CODES.ignored or st.repos[repo][tostring(url):sub(#repo + 2)]
if not self._file.in_current then
return ""
end
if not code or signs[code] == "" then
local url = self._file.url
local repo = st.dirs[tostring(url.base or url.parent)]
local code = CODES.unknown
if repo then
code = repo == CODES.excluded and CODES.ignored or st.repos[repo][tostring(url):sub(#repo + 2)] or CODES.clean
end
if signs[code] == "" then
return ""
elseif self._file.is_hovered then
return ui.Line { " ", signs[code] }
@@ -208,7 +207,7 @@ end
---@type UnstableFetcher
local function fetch(_, job)
local cwd = job.files[1].url.base
local cwd = job.files[1].url.base or job.files[1].url.parent
local repo = root(cwd)
if not repo then
remove(tostring(cwd))
@@ -246,11 +245,11 @@ local function fetch(_, job)
end
ya.dict_merge(changed, propagate_down(excluded, cwd, Url(repo)))
-- Reset the status of any files that don't appear in the output of `git status` to `unknown`,
-- Reset the status of any files that don't appear in the output of `git status` to `clean`,
-- so that cleaning up outdated statuses from `st.repos`
for _, path in ipairs(paths) do
local s = path:sub(#repo + 2)
changed[s] = changed[s] or CODES.unknown
changed[s] = changed[s] or CODES.clean
end
add(tostring(cwd), repo, changed)

View File

@@ -0,0 +1,12 @@
---@class State
---@field dirs table<string, string|CODES> Mapping between a directory and its corresponding repository
---@field repos table<string, Changes> Mapping between a repository and the status of each of its files
---@class Options
---@field order number The order in which the status is displayed
---@field renamed boolean Whether to include renamed files in the status (or treat them as modified)
-- TODO: move this to `types.yazi` once it's get stable
---@alias UnstableFetcher fun(self: unknown, job: { files: File[] }): boolean, Error?
---@alias Changes table<string, CODES>