Skip to content

Commit 55aba11

Browse files
Peeeajeclaude
andauthored
feat: add oil.nvim support for file selection (#27)
* 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 <noreply@anthropic.com> * fix: add missing oil.nvim filetype checks for window selection - Add oil filetype check in diff.lua's _find_main_editor_window() - Add oil filetype check in open_file.lua's find_main_editor_window() - Add oil filetype check in init.lua's ClaudeCodeSend command These changes ensure oil.nvim buffers are properly excluded when searching for main editor windows, preventing diff views and file opens from appearing in the oil explorer window. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: remove unnecessary variable * fix: run formatter --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2412f95 commit 55aba11

File tree

7 files changed

+354
-4
lines changed

7 files changed

+354
-4
lines changed

README.md

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

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

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

106106
#### Features
107107

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

113113
### Direct File Addition

lua/claudecode/diff.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ local function find_main_editor_window()
4949
or filetype == "neo-tree-popup"
5050
or filetype == "ClaudeCode"
5151
or filetype == "NvimTree"
52+
or filetype == "oil"
5253
or filetype == "aerial"
5354
or filetype == "tagbar"
5455
)

lua/claudecode/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ function M._create_commands()
409409

410410
local is_tree_buffer = current_ft == "NvimTree"
411411
or current_ft == "neo-tree"
412+
or current_ft == "oil"
412413
or string.match(current_bufname, "neo%-tree")
413414
or string.match(current_bufname, "NvimTree")
414415

lua/claudecode/integrations.lua

Lines changed: 84 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,85 @@ function M._get_neotree_selection()
178180
return {}, "No file found under cursor"
179181
end
180182

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

lua/claudecode/tools/open_file.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ local function find_main_editor_window()
7575
or filetype == "neo-tree-popup"
7676
or filetype == "ClaudeCode"
7777
or filetype == "NvimTree"
78+
or filetype == "oil"
7879
or filetype == "aerial"
7980
or filetype == "tagbar"
8081
)

lua/claudecode/visual_commands.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ function M.get_tree_state()
174174
end
175175

176176
return nvim_tree_api, "nvim-tree"
177+
elseif current_ft == "oil" then
178+
local oil_success, oil = pcall(require, "oil")
179+
if not oil_success then
180+
return nil, nil
181+
end
182+
183+
return oil, "oil"
177184
else
178185
return nil, nil
179186
end
@@ -346,6 +353,34 @@ function M.get_files_from_visual_selection(visual_data)
346353
end
347354
end
348355
files = unique_files
356+
elseif tree_type == "oil" then
357+
local oil = tree_state
358+
local bufnr = vim.api.nvim_get_current_buf()
359+
360+
-- Get current directory once
361+
local dir_ok, current_dir = pcall(oil.get_current_dir, bufnr)
362+
if dir_ok and current_dir then
363+
-- Access the process_oil_entry function through a module method
364+
for line = start_pos, end_pos do
365+
local entry_ok, entry = pcall(oil.get_entry_on_line, bufnr, line)
366+
if entry_ok and entry and entry.name then
367+
-- Skip parent directory entries
368+
if entry.name ~= ".." and entry.name ~= "." then
369+
local full_path = current_dir .. entry.name
370+
-- Handle various entry types
371+
if entry.type == "file" or entry.type == "link" then
372+
table.insert(files, full_path)
373+
elseif entry.type == "directory" then
374+
-- Ensure directory paths end with /
375+
table.insert(files, full_path:match("/$") and full_path or full_path .. "/")
376+
else
377+
-- For unknown types, return the path anyway
378+
table.insert(files, full_path)
379+
end
380+
end
381+
end
382+
end
383+
end
349384
end
350385

351386
return files, nil

0 commit comments

Comments
 (0)