refactor(previewer): clean up file_maker (#2585)

- split apart functions
- replace magic numbers with named constants
- reorganize functions for better grouping
This commit is contained in:
James Trew
2023-07-01 13:57:00 -04:00
committed by GitHub
parent c5b11f4fe7
commit b14de80d1c

View File

@@ -155,6 +155,131 @@ local handle_directory_preview = function(filepath, bufnr, opts)
}) })
end end
local handle_file_preview = function(filepath, bufnr, stat, opts)
vim.schedule(function()
opts.ft = opts.use_ft_detect and putils.filetype_detect(filepath)
local possible_binary = false
if type(opts.preview.filetype_hook) == "function" and opts.ft ~= nil and opts.ft ~= "" then
if not opts.preview.filetype_hook(filepath, bufnr, opts) then
return
end
end
if opts.preview.check_mime_type == true and has_file and (opts.ft == nil or opts.ft == "") then
-- avoid SIGABRT in buffer previewer happening with utils.get_os_command_output
local output = capture(string.format([[file --mime-type -b "%s"]], filepath))
local mime_type = vim.split(output, "/")
if mime_type[1] ~= "text" and mime_type[1] ~= "inode" and mime_type[2] ~= "json" then
if type(opts.preview.mime_hook) == "function" then
opts.preview.mime_hook(filepath, bufnr, opts)
return
else
possible_binary = true
end
end
if mime_type[2] == "json" then
opts.ft = "json"
end
end
if opts.preview.filesize_limit then
local mb_filesize = math.floor(stat.size / bytes_to_megabytes)
if mb_filesize > opts.preview.filesize_limit then
if type(opts.preview.filesize_hook) == "function" then
opts.preview.filesize_hook(filepath, bufnr, opts)
else
putils.set_preview_message(bufnr, opts.winid, "File exceeds preview size limit", opts.preview.msg_bg_fillchar)
end
return
end
end
opts.start_time = vim.loop.hrtime()
Path:new(filepath):_read_async(vim.schedule_wrap(function(data)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
local processed_data = split(data, "[\r]?\n", nil, opts)
if processed_data then
local ok = pcall(vim.api.nvim_buf_set_lines, bufnr, 0, -1, false, processed_data)
if not ok then
return
end
-- last resort, if ft is still empty at this point in time,
-- we need to determine the filetype using the buffer contents
if opts.ft == nil or opts.ft == "" then
opts.ft = vim.filetype.match { filename = filepath, buf = bufnr }
end
-- we need to attempt to call filetype hook at this point "again"
-- previously only if we had a valid filetype, now every time
-- also if there will never be a filetype
if type(opts.preview.filetype_hook) == "function" then
if not opts.preview.filetype_hook(filepath, bufnr, opts) then
return
end
end
-- if we still dont have a ft we need to display the binary message
if (opts.ft == nil or opts.ft == "") and possible_binary then
putils.set_preview_message(bufnr, opts.winid, "Binary cannot be previewed", opts.preview.msg_bg_fillchar)
return
end
if opts.callback then
opts.callback(bufnr)
end
putils.highlighter(bufnr, opts.ft, opts)
else
if type(opts.preview.timeout_hook) == "function" then
opts.preview.timeout_hook(filepath, bufnr, opts)
else
putils.set_preview_message(bufnr, opts.winid, "Previewer timed out", opts.preview.msg_bg_fillchar)
end
return
end
end))
end)
end
local PREVIEW_TIMEOUT_MS = 250
local PREVIEW_FILESIZE_MB = 25
previewers.file_maker = function(filepath, bufnr, opts)
opts = vim.F.if_nil(opts, {})
opts.preview = vim.F.if_nil(opts.preview, {})
opts.preview.timeout = vim.F.if_nil(opts.preview.timeout, PREVIEW_TIMEOUT_MS)
opts.preview.filesize_limit = vim.F.if_nil(opts.preview.filesize_limit, PREVIEW_FILESIZE_MB)
opts.preview.msg_bg_fillchar = vim.F.if_nil(opts.preview.msg_bg_fillchar, "")
opts.preview.treesitter = vim.F.if_nil(opts.preview.treesitter, true)
if opts.use_ft_detect == nil then
opts.use_ft_detect = true
end
if opts.bufname ~= filepath then
if not vim.in_fast_event() then
filepath = vim.fn.expand(filepath)
end
vim.loop.fs_stat(filepath, function(_, stat)
if not stat then
return
end
if stat.type == "directory" then
handle_directory_preview(filepath, bufnr, opts)
else
handle_file_preview(filepath, bufnr, stat, opts)
end
end)
else
if opts.callback then
if vim.in_fast_event() then
vim.schedule(function()
opts.callback(bufnr)
end)
else
opts.callback(bufnr)
end
end
end
end
local search_cb_jump = function(self, bufnr, query) local search_cb_jump = function(self, bufnr, query)
if not query then if not query then
return return
@@ -202,135 +327,6 @@ local scroll_horizontal_fn = function(self, direction)
end) end)
end end
previewers.file_maker = function(filepath, bufnr, opts)
opts = vim.F.if_nil(opts, {})
-- TODO(conni2461): here shouldn't be any hardcoded magic numbers ...
opts.preview = vim.F.if_nil(opts.preview, {})
opts.preview.timeout = vim.F.if_nil(opts.preview.timeout, 250) -- in ms
opts.preview.filesize_limit = vim.F.if_nil(opts.preview.filesize_limit, 25) -- in mb
opts.preview.msg_bg_fillchar = vim.F.if_nil(opts.preview.msg_bg_fillchar, "") -- in mb
opts.preview.treesitter = vim.F.if_nil(opts.preview.treesitter, true)
if opts.use_ft_detect == nil then
opts.use_ft_detect = true
end
if opts.bufname ~= filepath then
if not vim.in_fast_event() then
filepath = vim.fn.expand(filepath)
end
vim.loop.fs_stat(filepath, function(_, stat)
if not stat then
return
end
if stat.type == "directory" then
handle_directory_preview(filepath, bufnr, opts)
else
vim.schedule(function()
opts.ft = opts.use_ft_detect and putils.filetype_detect(filepath)
local possible_binary = false
if type(opts.preview.filetype_hook) == "function" and opts.ft ~= nil and opts.ft ~= "" then
if not opts.preview.filetype_hook(filepath, bufnr, opts) then
return
end
end
if opts.preview.check_mime_type == true and has_file and (opts.ft == nil or opts.ft == "") then
-- avoid SIGABRT in buffer previewer happening with utils.get_os_command_output
local output = capture(string.format([[file --mime-type -b "%s"]], filepath))
local mime_type = vim.split(output, "/")
if mime_type[1] ~= "text" and mime_type[1] ~= "inode" and mime_type[2] ~= "json" then
if type(opts.preview.mime_hook) == "function" then
opts.preview.mime_hook(filepath, bufnr, opts)
return
else
possible_binary = true
end
end
if mime_type[2] == "json" then
opts.ft = "json"
end
end
if opts.preview.filesize_limit then
local mb_filesize = math.floor(stat.size / bytes_to_megabytes)
if mb_filesize > opts.preview.filesize_limit then
if type(opts.preview.filesize_hook) == "function" then
opts.preview.filesize_hook(filepath, bufnr, opts)
else
putils.set_preview_message(
bufnr,
opts.winid,
"File exceeds preview size limit",
opts.preview.msg_bg_fillchar
)
end
return
end
end
opts.start_time = vim.loop.hrtime()
Path:new(filepath):_read_async(vim.schedule_wrap(function(data)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
local processed_data = split(data, "[\r]?\n", _, opts)
if processed_data then
local ok = pcall(vim.api.nvim_buf_set_lines, bufnr, 0, -1, false, processed_data)
if not ok then
return
end
-- last resort, if ft is still empty at this point in time,
-- we need to determine the filetype using the buffer contents
if opts.ft == nil or opts.ft == "" then
opts.ft = vim.filetype.match { filename = filepath, buf = bufnr }
end
-- we need to attempt to call filetype hook at this point "again"
-- previously only if we had a valid filetype, now every time
-- also if there will never be a filetype
if type(opts.preview.filetype_hook) == "function" then
if not opts.preview.filetype_hook(filepath, bufnr, opts) then
return
end
end
-- if we still dont have a ft we need to display the binary message
if (opts.ft == nil or opts.ft == "") and possible_binary then
putils.set_preview_message(
bufnr,
opts.winid,
"Binary cannot be previewed",
opts.preview.msg_bg_fillchar
)
return
end
if opts.callback then
opts.callback(bufnr)
end
putils.highlighter(bufnr, opts.ft, opts)
else
if type(opts.preview.timeout_hook) == "function" then
opts.preview.timeout_hook(filepath, bufnr, opts)
else
putils.set_preview_message(bufnr, opts.winid, "Previewer timed out", opts.preview.msg_bg_fillchar)
end
return
end
end))
end)
end
end)
else
if opts.callback then
if vim.in_fast_event() then
vim.schedule(function()
opts.callback(bufnr)
end)
else
opts.callback(bufnr)
end
end
end
end
previewers.new_buffer_previewer = function(opts) previewers.new_buffer_previewer = function(opts)
opts = opts or {} opts = opts or {}