diff --git a/lua/avante/file_selector.lua b/lua/avante/file_selector.lua index aa6e280..4af6ac6 100644 --- a/lua/avante/file_selector.lua +++ b/lua/avante/file_selector.lua @@ -363,26 +363,14 @@ end function FileSelector:get_selected_files_contents() local contents = {} for _, file_path in ipairs(self.selected_filepaths) do - --- Lookup if the file is loaded in a buffer - local bufnr = vim.fn.bufnr(file_path) - if bufnr ~= -1 and vim.api.nvim_buf_is_loaded(bufnr) then - -- If buffer exists and is loaded, get buffer content - local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) - local content = table.concat(lines, "\n") - local filetype = vim.api.nvim_get_option_value("filetype", { buf = bufnr }) - table.insert(contents, { path = file_path, content = content, file_type = filetype }) + local lines, filetype, error = Utils.read_file_from_buf_or_disk(file_path) + lines = lines or {} + filetype = filetype or "unknown" + if error ~= nil then + Utils.error("error reading file: " .. error) else - -- Fallback: read file from disk - local file, open_err = io.open(file_path, "r") - if file then - local content = file:read("*all") - file:close() - -- Detect the file type using the specific file's content - local filetype = vim.filetype.match({ filename = file_path, contents = { content } }) or "unknown" - table.insert(contents, { path = file_path, content = content, file_type = filetype }) - else - Utils.debug("error reading file:", open_err) - end + local content = table.concat(lines, "\n") + table.insert(contents, { path = file_path, content = content, file_type = filetype }) end end return contents diff --git a/lua/avante/llm_tools.lua b/lua/avante/llm_tools.lua index e326760..9d75346 100644 --- a/lua/avante/llm_tools.lua +++ b/lua/avante/llm_tools.lua @@ -120,9 +120,9 @@ function M.read_file_toplevel_symbols(opts, on_log) local filetype = RepoMap.get_ts_lang(abs_path) local repo_map_lib = RepoMap._init_repo_map_lib() if not repo_map_lib then return "", "Failed to load avante_repo_map" end - local definitions = filetype - and repo_map_lib.stringify_definitions(filetype, Utils.file.read_content(abs_path) or "") - or "" + local lines = Utils.read_file_from_buf_or_disk(abs_path) + local content = lines and table.concat(lines, "\n") or "" + local definitions = filetype and repo_map_lib.stringify_definitions(filetype, content) or "" return definitions, nil end diff --git a/lua/avante/repo_map.lua b/lua/avante/repo_map.lua index 9cb99fd..c639922 100644 --- a/lua/avante/repo_map.lua +++ b/lua/avante/repo_map.lua @@ -64,9 +64,9 @@ function RepoMap._build_repo_map(project_root, file_ext) vim.iter(filepaths):each(function(filepath) if not Utils.is_same_file_ext(file_ext, filepath) then return end local filetype = RepoMap.get_ts_lang(filepath) - local definitions = filetype - and repo_map_lib.stringify_definitions(filetype, Utils.file.read_content(filepath) or "") - or "" + local lines = Utils.read_file_from_buf_or_disk(filepath) + local content = lines and table.concat(lines, "\n") or "" + local definitions = filetype and repo_map_lib.stringify_definitions(filetype, content) or "" if definitions == "" then return end table.insert(output, { path = Utils.relative_path(filepath), @@ -127,10 +127,9 @@ function RepoMap._get_repo_map(file_ext) local update_repo_map = vim.schedule_wrap(function(rel_filepath) if rel_filepath and Utils.is_same_file_ext(file_ext, rel_filepath) then local abs_filepath = PPath:new(project_root):joinpath(rel_filepath):absolute() - local definitions = repo_map_lib.stringify_definitions( - RepoMap.get_ts_lang(abs_filepath), - Utils.file.read_content(abs_filepath) or "" - ) + local lines = Utils.read_file_from_buf_or_disk(abs_filepath) + local content = lines and table.concat(lines, "\n") or "" + local definitions = repo_map_lib.stringify_definitions(RepoMap.get_ts_lang(abs_filepath), content) if definitions == "" then return end local found = false for _, m in ipairs(repo_map) do diff --git a/lua/avante/sidebar.lua b/lua/avante/sidebar.lua index 17abcba..12c3a63 100644 --- a/lua/avante/sidebar.lua +++ b/lua/avante/sidebar.lua @@ -255,11 +255,12 @@ local function transform_result_content(selected_files, result_content, prev_fil Utils.warn("Not a file: " .. filepath) goto continue end - local content = Utils.file.read_content(filepath) - if content == nil then + local lines = Utils.read_file_from_buf_or_disk(filepath) + if lines == nil then Utils.warn("Failed to read file: " .. filepath) goto continue end + local content = table.concat(lines, "\n") the_matched_file = { filepath = filepath, content = content, @@ -534,11 +535,12 @@ local function ensure_snippets_no_overlap(snippets_map) for filepath, snippets in pairs(snippets_map) do table.sort(snippets, function(a, b) return a.range[1] < b.range[1] end) - local original_content = "" + local original_lines = {} local file_exists = Utils.file.exists(filepath) - if file_exists then original_content = Utils.file.read_content(filepath) or "" end - - local original_lines = vim.split(original_content, "\n") + if file_exists then + local original_lines_ = Utils.read_file_from_buf_or_disk(filepath) + if original_lines_ then original_lines = original_lines_ end + end local new_snippets = {} local last_end_line = 0 @@ -584,9 +586,7 @@ local function insert_conflict_contents(bufnr, snippets) -- sort snippets by start_line table.sort(snippets, function(a, b) return a.range[1] < b.range[1] end) - local content = table.concat(Utils.get_buf_lines(0, -1, bufnr), "\n") - - local lines = vim.split(content, "\n") + local lines = Utils.get_buf_lines(0, -1, bufnr) local offset = 0 @@ -714,7 +714,15 @@ end ---@param snippets_map table<string, AvanteCodeSnippet[]> ---@return table<string, AvanteCodeSnippet[]> function Sidebar:minimize_snippets(snippets_map) - local original_lines = api.nvim_buf_get_lines(self.code.bufnr, 0, -1, false) + local original_lines = {} + + if vim.tbl_count(snippets_map) > 0 then + local filepaths = vim.tbl_keys(snippets_map) + local original_lines_, _, err = Utils.read_file_from_buf_or_disk(filepaths[1]) + if err ~= nil then return {} end + if original_lines_ then original_lines = original_lines_ end + end + local results = {} for filepath, snippets in pairs(snippets_map) do diff --git a/lua/avante/utils/init.lua b/lua/avante/utils/init.lua index 2dbbdcf..881cc40 100644 --- a/lua/avante/utils/init.lua +++ b/lua/avante/utils/init.lua @@ -890,4 +890,32 @@ function M.is_same_file(filepath_a, filepath_b) return M.uniform_path(filepath_a function M.trim_think_content(content) return content:gsub("^<think>.-</think>", "", 1) end +---@param file_path string +---@return string[]|nil lines +---@return string|nil file_type +---@return string|nil error +function M.read_file_from_buf_or_disk(file_path) + --- Lookup if the file is loaded in a buffer + local bufnr = vim.fn.bufnr(file_path) + if bufnr ~= -1 and vim.api.nvim_buf_is_loaded(bufnr) then + -- If buffer exists and is loaded, get buffer content + local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + local file_type = vim.api.nvim_get_option_value("filetype", { buf = bufnr }) + return lines, file_type, nil + end + + -- Fallback: read file from disk + local file, open_err = io.open(file_path, "r") + if file then + local content = file:read("*all") + file:close() + -- Detect the file type using the specific file's content + local file_type = vim.filetype.match({ filename = file_path, contents = { content } }) or "unknown" + return vim.split(content, "\n"), file_type, nil + else + M.error("failed to open file: " .. file_path .. " with error: " .. open_err) + return nil, nil, open_err + end +end + return M