Skip to content

Commit 847c45b

Browse files
Peeeajeclaude
andcommitted
feat: add oil.nvim support for file selection
- Add oil.nvim integration to support file selection with @-mention - Support both visual selection and single file under cursor - Handle directories, files, and symbolic links properly - Add comprehensive unit tests for oil.nvim integration - Update README documentation to include oil.nvim support 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 6f6b8d1 commit 847c45b

File tree

4 files changed

+354
-4
lines changed

4 files changed

+354
-4
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ That's it! For more configuration options, see [Advanced Setup](#advanced-setup)
8888
The `<leader>as` keybinding has context-aware behavior:
8989

9090
- **In normal buffers (visual mode)**: Sends selected text to Claude
91-
- **In nvim-tree/neo-tree buffers**: Adds the file under cursor (or selected files) to Claude's context
91+
- **In nvim-tree/neo-tree/oil.nvim buffers**: Adds the file under cursor (or selected files) to Claude's context
9292

9393
This allows you to quickly add entire files to Claude's context for review, refactoring, or discussion.
9494

9595
#### Features
9696

9797
- **Single file**: Place cursor on any file and press `<leader>as`
98-
- **Multiple files**: Select multiple files (using tree plugin's selection features) and press `<leader>as`
99-
- **Smart detection**: Automatically detects whether you're in nvim-tree or neo-tree
98+
- **Multiple files**: Select multiple files (using tree plugin's selection features or visual selection in oil.nvim) and press `<leader>as`
99+
- **Smart detection**: Automatically detects whether you're in nvim-tree, neo-tree, or oil.nvim
100100
- **Error handling**: Clear feedback if no files are selected or if tree plugins aren't available
101101

102102
### Direct File Addition

lua/claudecode/integrations.lua

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
-- Tree integration module for ClaudeCode.nvim
3-
-- Handles detection and selection of files from nvim-tree and neo-tree
3+
-- Handles detection and selection of files from nvim-tree, neo-tree, and oil.nvim
44
-- @module claudecode.integrations
55
local M = {}
66

@@ -14,6 +14,8 @@ function M.get_selected_files_from_tree()
1414
return M._get_nvim_tree_selection()
1515
elseif current_ft == "neo-tree" then
1616
return M._get_neotree_selection()
17+
elseif current_ft == "oil" then
18+
return M._get_oil_selection()
1719
else
1820
return nil, "Not in a supported tree buffer (current filetype: " .. current_ft .. ")"
1921
end
@@ -178,4 +180,87 @@ function M._get_neotree_selection()
178180
return {}, "No file found under cursor"
179181
end
180182

183+
184+
185+
--- Get selected files from oil.nvim
186+
--- Supports both visual selection and single file under cursor
187+
--- @return table files List of file paths
188+
--- @return string|nil error Error message if operation failed
189+
function M._get_oil_selection()
190+
local success, oil = pcall(require, "oil")
191+
if not success then
192+
return {}, "oil.nvim not available"
193+
end
194+
195+
local bufnr = vim.api.nvim_get_current_buf() --[[@as number]]
196+
local files = {}
197+
198+
-- Check if we're in visual mode
199+
local mode = vim.fn.mode()
200+
if mode == "V" or mode == "v" or mode == "\22" then
201+
-- Visual mode: use the common visual range function
202+
local visual_commands = require("claudecode.visual_commands")
203+
local start_line, end_line = visual_commands.get_visual_range()
204+
205+
-- Get current directory once
206+
local dir_ok, current_dir = pcall(oil.get_current_dir, bufnr)
207+
if not dir_ok or not current_dir then
208+
return {}, "Failed to get current directory"
209+
end
210+
211+
-- Process each line in the visual selection
212+
for line = start_line, end_line do
213+
local entry_ok, entry = pcall(oil.get_entry_on_line, bufnr, line)
214+
if entry_ok and entry and entry.name then
215+
-- Skip parent directory entries
216+
if entry.name ~= ".." and entry.name ~= "." then
217+
local full_path = current_dir .. entry.name
218+
-- Handle various entry types
219+
if entry.type == "file" or entry.type == "link" then
220+
table.insert(files, full_path)
221+
elseif entry.type == "directory" then
222+
-- Ensure directory paths end with /
223+
table.insert(files, full_path:match("/$") and full_path or full_path .. "/")
224+
else
225+
-- For unknown types, return the path anyway
226+
table.insert(files, full_path)
227+
end
228+
end
229+
end
230+
end
231+
232+
if #files > 0 then
233+
return files, nil
234+
end
235+
else
236+
-- Normal mode: get file under cursor with error handling
237+
local ok, entry = pcall(oil.get_cursor_entry)
238+
if not ok or not entry then
239+
return {}, "Failed to get cursor entry"
240+
end
241+
242+
local dir_ok, current_dir = pcall(oil.get_current_dir, bufnr)
243+
if not dir_ok or not current_dir then
244+
return {}, "Failed to get current directory"
245+
end
246+
247+
-- Process the entry
248+
if entry.name and entry.name ~= ".." and entry.name ~= "." then
249+
local full_path = current_dir .. entry.name
250+
-- Handle various entry types
251+
if entry.type == "file" or entry.type == "link" then
252+
return { full_path }, nil
253+
elseif entry.type == "directory" then
254+
-- Ensure directory paths end with /
255+
return { full_path:match("/$") and full_path or full_path .. "/" }, nil
256+
else
257+
-- For unknown types, return the path anyway
258+
return { full_path }, nil
259+
end
260+
end
261+
end
262+
263+
return {}, "No file found under cursor"
264+
end
265+
181266
return M

lua/claudecode/visual_commands.lua

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ function M.get_tree_state()
166166
end
167167

168168
return nvim_tree_api, "nvim-tree"
169+
elseif current_ft == "oil" then
170+
local oil_success, oil = pcall(require, "oil")
171+
if not oil_success then
172+
return nil, nil
173+
end
174+
175+
return oil, "oil"
169176
else
170177
return nil, nil
171178
end
@@ -338,6 +345,35 @@ function M.get_files_from_visual_selection(visual_data)
338345
end
339346
end
340347
files = unique_files
348+
elseif tree_type == "oil" then
349+
local oil = tree_state
350+
local bufnr = vim.api.nvim_get_current_buf()
351+
352+
-- Get current directory once
353+
local dir_ok, current_dir = pcall(oil.get_current_dir, bufnr)
354+
if dir_ok and current_dir then
355+
local integrations = require("claudecode.integrations")
356+
-- Access the process_oil_entry function through a module method
357+
for line = start_pos, end_pos do
358+
local entry_ok, entry = pcall(oil.get_entry_on_line, bufnr, line)
359+
if entry_ok and entry and entry.name then
360+
-- Skip parent directory entries
361+
if entry.name ~= ".." and entry.name ~= "." then
362+
local full_path = current_dir .. entry.name
363+
-- Handle various entry types
364+
if entry.type == "file" or entry.type == "link" then
365+
table.insert(files, full_path)
366+
elseif entry.type == "directory" then
367+
-- Ensure directory paths end with /
368+
table.insert(files, full_path:match("/$") and full_path or full_path .. "/")
369+
else
370+
-- For unknown types, return the path anyway
371+
table.insert(files, full_path)
372+
end
373+
end
374+
end
375+
end
376+
end
341377
end
342378

343379
return files, nil

0 commit comments

Comments
 (0)