local Finder = {} 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 local function 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 = get_opened_folder() local file = find_path_recursive(dir, options) if file == nil then return nil end return file:match("(.*/)") end return Finder