local download = require('fff.download') local is_windows = jit.os:lower() == 'windows' --- @return string local function get_lib_extension() if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then return '.dylib' end if is_windows then return '.dll' end return '.so' end --- Resolve a path to an absolute, clean form with native separators. --- Resolves `..` components and on Windows converts forward slashes to --- backslashes so that Windows APIs (LoadLibraryEx) can find the file. --- @param path string --- @return string local function resolve_path(path) local resolved = vim.fn.fnamemodify(path, ':p') if is_windows then resolved = resolved:gsub('/', '\\') end return resolved end -- Determine base_path from the location of this Lua file local info = debug.getinfo(1, 'S') -- Match both forward and backslash directory separators for cross-platform support local base_path = info and info.source and info.source:match('@?(.*[/\\])') or '' -- Fallback: if base_path is empty, use vim APIs if not base_path or base_path == '' then base_path = vim.fn.fnamemodify(vim.fn.resolve(vim.fn.expand(':p')), ':h') .. '/' end local paths = { download.get_binary_cpath_component(), base_path .. '../../../target/release/lib?' .. get_lib_extension(), base_path .. '../../../target/release/?' .. get_lib_extension(), } local cargo_target_dir = os.getenv('CARGO_TARGET_DIR') if cargo_target_dir then table.insert(paths, cargo_target_dir .. '/release/lib?' .. get_lib_extension()) table.insert(paths, cargo_target_dir .. '/release/?' .. get_lib_extension()) end -- Instead of using require (which can find the wrong lib due to cpath pollution), -- load the library directly from the first valid path we find local function try_load_library() for _, path_pattern in ipairs(paths) do local actual_path = resolve_path(path_pattern:gsub('%?', 'fff_nvim')) local stat = vim.uv.fs_stat(actual_path) if stat and stat.type == 'file' then local loader, err = package.loadlib(actual_path, 'luaopen_fff_nvim') if err then return nil, string.format('Error loading library from %s: %s', actual_path, err) end if loader then return loader() end end end return nil, 'No valid library found in any search path' end local backend, load_err = try_load_library() if not backend or load_err then local resolved = {} for _, p in ipairs(paths) do table.insert(resolved, resolve_path(p:gsub('%?', 'fff_nvim'))) end local err_msg = string.format( 'Failed to load fff rust backend.\nError: %s\nSearched paths:\n%s\nMake sure binary exists or make it exists using \n `:lua require("fff.download").download_or_build_binary()`\nor\n`cargo build --release`\n(and rerun neovim after)', tostring(load_err), vim.inspect(resolved) ) error(err_msg) end return backend