diff --git a/README.md b/README.md index a3f30134..0f4f3fe0 100644 --- a/README.md +++ b/README.md @@ -272,8 +272,8 @@ require("oil").setup({ preview_win = { -- Whether the preview window is automatically updated when the cursor is moved update_on_cursor_moved = true, - -- Maximum file size in megabytes to preview - max_file_size_mb = 100, + -- How to open the preview window "load"|"scratch"|"fast_scratch" + preview_method = "fast_scratch", -- Window-local options to use for preview window buffers win_options = {}, }, diff --git a/doc/oil.txt b/doc/oil.txt index 5bb0953e..48df3a5e 100644 --- a/doc/oil.txt +++ b/doc/oil.txt @@ -157,8 +157,8 @@ CONFIG *oil-confi preview_win = { -- Whether the preview window is automatically updated when the cursor is moved update_on_cursor_moved = true, - -- Maximum file size in megabytes to preview - max_file_size_mb = 100, + -- How to open the preview window "load"|"scratch"|"fast_scratch" + preview_method = "fast_scratch", -- Window-local options to use for preview window buffers win_options = {}, }, diff --git a/lua/oil/config.lua b/lua/oil/config.lua index d3eca474..3b6b57ea 100644 --- a/lua/oil/config.lua +++ b/lua/oil/config.lua @@ -142,8 +142,8 @@ local default_config = { preview_win = { -- Whether the preview window is automatically updated when the cursor is moved update_on_cursor_moved = true, - -- Maximum file size in megabytes to preview - max_file_size_mb = 100, + -- How to open the preview window "load"|"scratch"|"fast_scratch" + preview_method = "fast_scratch", -- Window-local options to use for preview window buffers win_options = {}, }, @@ -326,16 +326,21 @@ local M = {} ---@field border? string|string[] Window border ---@field win_options? table +---@alias oil.PreviewMethod +---| '"load"' # Load the previewed file into a buffer +---| '"scratch"' # Put the text into a scratch buffer to avoid LSP attaching +---| '"fast_scratch"' # Put only the visible text into a scratch buffer + ---@class (exact) oil.PreviewWindowConfig ---@field update_on_cursor_moved boolean ----@field max_file_size_mb number +---@field preview_method oil.PreviewMethod ---@field win_options table ---@class (exact) oil.ConfirmationWindowConfig : oil.WindowConfig ---@class (exact) oil.SetupPreviewWindowConfig ---@field update_on_cursor_moved? boolean Whether the preview window is automatically updated when the cursor is moved ----@field max_file_size_mb? number Maximum file size in megabytes to preview +---@field preview_method? oil.PreviewMethod How to open the preview window ---@field win_options? table Window-local options to use for preview window buffers ---@class (exact) oil.SetupConfirmationWindowConfig : oil.SetupWindowConfig diff --git a/lua/oil/init.lua b/lua/oil/init.lua index 2399d39f..d6734849 100644 --- a/lua/oil/init.lua +++ b/lua/oil/init.lua @@ -452,13 +452,6 @@ M.open_preview = function(opts, callback) if not entry then return finish("Could not find entry under cursor") end - if entry.meta ~= nil and entry.meta.stat ~= nil then - if entry.meta.stat.size >= config.preview_win.max_file_size_mb * 1e6 then - return finish( - "File over " .. config.preview_win.max_file_size_mb .. "MB is too large to preview" - ) - end - end local entry_title = entry.name if entry.type == "directory" then entry_title = entry_title .. "/" @@ -529,14 +522,19 @@ M.open_preview = function(opts, callback) end end - local filebufnr = vim.fn.bufadd(normalized_url) local entry_is_file = not vim.endswith(normalized_url, "/") + local filebufnr + if entry_is_file and config.preview_win.preview_method ~= "load" then + filebufnr = + util.read_file_to_scratch_buffer(normalized_url, config.preview_win.preview_method) + end - -- If we're previewing a file that hasn't been opened yet, make sure it gets deleted after - -- we close the window - if entry_is_file and vim.fn.bufloaded(filebufnr) == 0 then - vim.bo[filebufnr].bufhidden = "wipe" - vim.b[filebufnr].oil_preview_buffer = true + if not filebufnr then + filebufnr = vim.fn.bufadd(normalized_url) + if entry_is_file and vim.fn.bufloaded(filebufnr) == 0 then + vim.bo[filebufnr].bufhidden = "wipe" + vim.b[filebufnr].oil_preview_buffer = true + end end ---@diagnostic disable-next-line: param-type-mismatch diff --git a/lua/oil/util.lua b/lua/oil/util.lua index 947b38a2..24b714b0 100644 --- a/lua/oil/util.lua +++ b/lua/oil/util.lua @@ -897,4 +897,59 @@ M.get_icon_provider = function() end end +---Read a buffer into a scratch buffer and apply syntactic highlighting when possible +---@param path string The path to the file to read +---@param preview_method oil.PreviewMethod +---@return nil|integer +M.read_file_to_scratch_buffer = function(path, preview_method) + local bufnr = vim.api.nvim_create_buf(false, true) + if bufnr == 0 then + return + end + + vim.bo[bufnr].bufhidden = "wipe" + vim.bo[bufnr].buftype = "nofile" + + local max_lines = preview_method == "fast_scratch" and vim.o.lines or nil + local has_lines, read_res = pcall(vim.fn.readfile, path, "", max_lines) + local lines = has_lines and vim.split(table.concat(read_res, "\n"), "\n") or {} + + local ok = pcall(vim.api.nvim_buf_set_lines, bufnr, 0, -1, false, lines) + if not ok then + return + end + local ft = vim.filetype.match({ filename = path, buf = bufnr }) + if ft and ft ~= "" then + local lang = vim.treesitter.language.get_lang(ft) + if not pcall(vim.treesitter.start, bufnr, lang) then + vim.bo[bufnr].syntax = ft + else + end + end + + -- Replace the scratch buffer with a real buffer if we enter it + vim.api.nvim_create_autocmd("BufEnter", { + desc = "oil.nvim replace scratch buffer with real buffer", + buffer = bufnr, + callback = function() + local winid = vim.api.nvim_get_current_win() + -- Have to schedule this so all the FileType, etc autocmds will fire + vim.schedule(function() + if vim.api.nvim_get_current_win() == winid then + vim.cmd.edit({ args = { path } }) + + -- If we're still in a preview window, make sure this buffer still gets treated as a + -- preview + if vim.wo.previewwindow then + vim.bo.bufhidden = "wipe" + vim.b.oil_preview_buffer = true + end + end + end) + end, + }) + + return bufnr +end + return M