Skip to content

Commit 3eec502

Browse files
committed
feat(oil): add git status highlights
- Removed the dependency on oil-git.nvim for the Oil file manager. - Added functionality to display Git status highlights in the Oil file manager. - Introduced a new filetype plugin for Oil to manage Git status visually. - Updated the README to reflect the changes in plugins and features.
1 parent b7b205c commit 3eec502

5 files changed

Lines changed: 171 additions & 5 deletions

File tree

lazy-lock.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@
1919
"mini.operators": { "branch": "main", "commit": "40139a281435916ca35c45740e094d4ef6c545be" },
2020
"mini.pairs": { "branch": "main", "commit": "42407ccb80ec59c84e7c91d815f42ed90a8cc093" },
2121
"mini.surround": { "branch": "main", "commit": "1a2b59c77a0c4713a5bd8972da322f842f4821b1" },
22-
"nvim-dap": { "branch": "master", "commit": "14fe46ae16eb272629144a93f7738f5279665a4f" },
22+
"nvim-dap": { "branch": "master", "commit": "1c75a797b4017fec6491f509cf196c8c8833f26f" },
2323
"nvim-dap-view": { "branch": "main", "commit": "280213aa7a553c03fccf97771e340f991706478c" },
2424
"nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" },
2525
"nvim-treesitter-refactor": { "branch": "master", "commit": "d8b74fa87afc6a1e97b18da23e762efb032dc270" },
2626
"nvim-treesitter-textobjects": { "branch": "master", "commit": "89ebe73cd2836db80a22d9748999ace0241917a5" },
2727
"nvim-ts-autotag": { "branch": "main", "commit": "a1d526af391f6aebb25a8795cbc05351ed3620b5" },
2828
"nvim-web-devicons": { "branch": "master", "commit": "19d6211c78169e78bab372b585b6fb17ad974e82" },
29-
"oil-git.nvim": { "branch": "main", "commit": "3abffa67597aab5f915816d71e96cbed76147016" },
3029
"oil.nvim": { "branch": "master", "commit": "bbad9a76b2617ce1221d49619e4e4b659b3c61fc" },
3130
"other.nvim": { "branch": "main", "commit": "1d48e090f6d1d53dda9fb5094af3f2006ebbb858" },
3231
"plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" },

lua/plugins/oil.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,5 @@ return {
6060
enabled = not vim.g.vscode,
6161
dependencies = {
6262
{ "nvim-tree/nvim-web-devicons" },
63-
{ "benomahony/oil-git.nvim" },
6463
},
6564
}

lua/ruicsh/git.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
vim.git = {}
22

3+
vim.git.get_root_dir = function()
4+
local git_toplevel = vim.fn.system("git rev-parse --show-toplevel")
5+
if vim.v.shell_error == 0 then
6+
return vim.trim(git_toplevel)
7+
else
8+
return nil
9+
end
10+
end
11+
312
-- Get blame info for a file/line
413
vim.git.blame = function(o)
514
local opts = o or {}

plugin/filetypes/oil.lua

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
-- Apply Git status highlights in Oil file manager
2+
3+
local augroup = vim.api.nvim_create_augroup("ruicsh/filetype/oil", { clear = true })
4+
local ns = vim.api.nvim_create_namespace("ruicsh/filetype/oil")
5+
6+
local function get_highlight_group(status_code)
7+
if not status_code then
8+
return nil, nil
9+
end
10+
11+
local first_char = status_code:sub(1, 1)
12+
local second_char = status_code:sub(2, 2)
13+
14+
-- Check staged changes first (prioritize staged over unstaged)
15+
if first_char == "A" then
16+
return "OilGitAdded", "+"
17+
elseif first_char == "M" then
18+
return "OilGitModified", "~"
19+
elseif first_char == "R" then
20+
return "OilGitRenamed", ""
21+
end
22+
23+
-- Check unstaged changes
24+
if second_char == "M" then
25+
return "OilGitModified", "~"
26+
end
27+
28+
-- Untracked files
29+
if status_code == "??" then
30+
return "OilGitUntracked", "?"
31+
end
32+
33+
-- Ignored files
34+
if status_code == "!!" then
35+
return "OilGitIgnored", "!"
36+
end
37+
38+
return nil, nil
39+
end
40+
41+
local function get_git_status()
42+
local oil = require("oil")
43+
local current_dir = oil.get_current_dir()
44+
local git_root = vim.git.get_root_dir()
45+
46+
if not git_root or not current_dir then
47+
return {}
48+
end
49+
50+
-- Get relative path from git root to current directory
51+
local rel_path = vim.fs.normalize(vim.fn.fnamemodify(current_dir, ":~:."))
52+
if rel_path == "" then
53+
rel_path = "."
54+
end
55+
56+
local result = vim.system({
57+
"git",
58+
"-C",
59+
git_root,
60+
"status",
61+
"--porcelain",
62+
"--ignored",
63+
"--",
64+
rel_path,
65+
}, { text = true }):wait()
66+
67+
if result.code ~= 0 then
68+
return {}
69+
end
70+
71+
local output = result.stdout
72+
if not output or output == "" then
73+
return {}
74+
end
75+
76+
local status = {}
77+
for line in output:gmatch("[^\r\n]+") do
78+
if #line >= 3 then
79+
local status_code = line:sub(1, 2)
80+
local filepath = line:sub(4)
81+
82+
-- Handle renames (format: "old-name -> new-name")
83+
if status_code:sub(1, 1) == "R" then
84+
local arrow_pos = filepath:find(" %-> ")
85+
if arrow_pos then
86+
filepath = filepath:sub(arrow_pos + 4)
87+
end
88+
end
89+
90+
-- Remove leading "./" if present
91+
if filepath:sub(1, 2) == "./" then
92+
filepath = filepath:sub(3)
93+
end
94+
95+
-- Convert to absolute path
96+
local abs_path = vim.fs.joinpath(git_root, filepath)
97+
98+
status[abs_path] = status_code
99+
end
100+
end
101+
102+
return status
103+
end
104+
105+
local function clear_highlights()
106+
local bufnr = vim.api.nvim_get_current_buf()
107+
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
108+
end
109+
110+
local function apply_git_highlights()
111+
local oil = require("oil")
112+
local current_dir = oil.get_current_dir()
113+
114+
local git_status = get_git_status()
115+
if vim.tbl_isempty(git_status) then
116+
clear_highlights()
117+
return
118+
end
119+
120+
local bufnr = vim.api.nvim_get_current_buf()
121+
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
122+
123+
clear_highlights()
124+
125+
for i, line in ipairs(lines) do
126+
local entry = oil.get_entry_on_line(bufnr, i)
127+
if entry and entry.type == "file" then
128+
local filepath = vim.fs.joinpath(current_dir, entry.name)
129+
130+
local status_code = git_status[filepath]
131+
local hl_group, symbol = get_highlight_group(status_code)
132+
133+
if hl_group and symbol then
134+
-- Find the filename part in the line and highlight it
135+
local name_start = line:find(entry.name, 1, true)
136+
if name_start then
137+
-- Highlight the filename
138+
vim.fn.matchaddpos(hl_group, { { i, name_start, #entry.name } })
139+
140+
-- Add symbol as virtual text at the end of the line
141+
vim.api.nvim_buf_set_extmark(bufnr, ns, i - 1, 0, {
142+
virt_text = { { symbol, hl_group } },
143+
virt_text_pos = "eol",
144+
hl_mode = "combine",
145+
})
146+
end
147+
end
148+
end
149+
end
150+
end
151+
152+
vim.api.nvim_create_autocmd("BufEnter", {
153+
group = augroup,
154+
pattern = "oil://*",
155+
callback = function()
156+
-- Small delay to ensure oil is fully loaded
157+
vim.defer_fn(apply_git_highlights, 50)
158+
end,
159+
})

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ This is my configuration for [Neovim](https://neovim.io/), mostly for frontend d
2525

2626
## Plugins
2727

28-
<sub>37 plugins</sub>
28+
<sub>36 plugins</sub>
2929

3030
### Navigation
3131

@@ -75,7 +75,6 @@ This is my configuration for [Neovim](https://neovim.io/), mostly for frontend d
7575

7676
- [fugitive](https://github.com/tpope/vim-fugitive) - status, commit, push
7777
- [mini.diff](https://github.com/echasnovski/mini.diff) - hunks
78-
- [oil-git-status](https://github.com/benomahony/oil-git.nvim) - git status on file explorer
7978
- [snacks.gitbrowse](https://github.com/folke/snacks.nvim/blob/main/docs/gitbrowse.md) - Open remote repo
8079

8180
### UI
@@ -115,6 +114,7 @@ Custom configuration, keymaps, and features dependent on the file's type.
115114
| --------------------------------------------------------------------------------------------- | ---------- |
116115
| [dockerfile](https://github.com/ruicsh/nvim-config/blob/main/plugin/filetypes/dockerfile.lua) | Dockerfile |
117116
| [help](https://github.com/ruicsh/nvim-config/blob/main/plugin/filetypes/help.lua) | help |
117+
| [oil](https://github.com/ruicsh/nvim-config/blob/main/plugin/filetypes/oil.lua) | Oil |
118118
| [python](https://github.com/ruicsh/nvim-config/blob/main/plugin/filetypes/python.lua) | Python |
119119
| [rust](https://github.com/ruicsh/nvim-config/blob/main/plugin/filetypes/rust.lua) | Rust |
120120
| [terminal](https://github.com/ruicsh/nvim-config/blob/main/plugin/filetypes/terminal.lua) | Terminal |

0 commit comments

Comments
 (0)