113 lines
2.5 KiB
Lua
113 lines
2.5 KiB
Lua
|
local Finder = {}
|
||
|
|
||
|
local function is_ignored(entry, ignore_dot_dirs, ignored_dirs)
|
||
|
if entry == ".." or entry == "." then
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
if ignore_dot_dirs and string.match(entry, "^%.") then
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
for _, dir in ipairs(ignored_dirs) do
|
||
|
if entry == dir or string.find(entry, dir, 1, true) then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
local function read_dir(dir)
|
||
|
local handle = io.popen('ls -a "' .. dir .. '"')
|
||
|
if not handle then
|
||
|
return nil
|
||
|
end
|
||
|
local result = handle:read("*a")
|
||
|
handle:close()
|
||
|
return result
|
||
|
end
|
||
|
|
||
|
local function is_dir(path)
|
||
|
local f = io.open(path, "r")
|
||
|
if f == nil then
|
||
|
return false
|
||
|
end
|
||
|
local _, _, code = f:read(1)
|
||
|
f:close()
|
||
|
return code == 21
|
||
|
end
|
||
|
|
||
|
local function find_path_recursive(_dir, options)
|
||
|
-- Check max Depth
|
||
|
if options.current_depth > options.max_depth then
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
local entries = read_dir(_dir)
|
||
|
if entries == nil then
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
for entry in string.gmatch(entries, "[^\r\n]+") do
|
||
|
-- Check Ignored
|
||
|
if is_ignored(entry, options.ignore_dot_dirs, options.ignored_dirs) then
|
||
|
goto continue
|
||
|
end
|
||
|
|
||
|
local full_path = _dir .. "/" .. entry
|
||
|
|
||
|
-- Check for File
|
||
|
if entry == options.needle_file then
|
||
|
return full_path
|
||
|
end
|
||
|
|
||
|
-- Check is Dir
|
||
|
if not is_dir(full_path) then
|
||
|
goto continue
|
||
|
end
|
||
|
|
||
|
-- Recursive Call
|
||
|
options.current_depth = options.current_depth + 1
|
||
|
local result = find_path_recursive(full_path, options)
|
||
|
if result ~= nil then
|
||
|
return result
|
||
|
end
|
||
|
|
||
|
-- Cleanup
|
||
|
options.current_depth = options.current_depth - 1
|
||
|
:: continue ::
|
||
|
end
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
function Finder.get_opened_folder()
|
||
|
local cwd = vim.fn.getcwd()
|
||
|
local file_path = vim.fn.expand('%:p:h')
|
||
|
|
||
|
if file_path ~= '' then
|
||
|
return file_path
|
||
|
end
|
||
|
return cwd
|
||
|
end
|
||
|
|
||
|
function Finder.find_project_dir(needle_file, max_depth, priority_dirs, ignored_dirs, ignore_dot_dirs)
|
||
|
local options = {
|
||
|
needle_file = needle_file,
|
||
|
max_depth = max_depth,
|
||
|
priority_dirs = priority_dirs,
|
||
|
ignored_dirs = ignored_dirs,
|
||
|
ignore_dot_dirs = ignore_dot_dirs,
|
||
|
current_depth = 0
|
||
|
}
|
||
|
|
||
|
local dir = Finder.get_opened_folder()
|
||
|
local file = find_path_recursive(dir, options)
|
||
|
if file == nil then
|
||
|
return nil
|
||
|
end
|
||
|
return file:match("(.*/)")
|
||
|
end
|
||
|
|
||
|
return Finder
|