feat(nvim): add file intercepts to open files in external programs

This commit is contained in:
Price Hiller 2023-09-05 16:22:59 -05:00
parent 281bd2d390
commit a598276379
Signed by: Price
SSH Key Fingerprint: SHA256:Y4S9ZzYphRn1W1kbJerJFO6GGsfu9O70VaBSxJO7dF8

View File

@ -27,6 +27,103 @@ M.setup = function()
vim.cmd.startinsert()
end,
})
-- NOTE: Launches a different program for a given filetype instead of opening it in Neovim
local intercept_file_open = true
vim.api.nvim_create_user_command("InterceptToggle", function()
intercept_file_open = not intercept_file_open
local intercept_state = "`Enabled`"
if not intercept_file_open then
intercept_state = "`Disabled`"
end
vim.notify("Intercept file open set to " .. intercept_state, vim.log.levels.INFO,
{
title = "Intercept File Open",
---@param win integer The window handle
on_open = function(win)
vim.api.nvim_buf_set_option(
vim.api.nvim_win_get_buf(win),
"filetype",
"markdown"
)
end
})
end, { desc = "Toggles intercepting BufNew to open files in custom programs" })
-- NOTE: Add "BufReadPre" to the autocmd events to also intercept files given on the command line, e.g.
-- `nvim myfile.txt`
vim.api.nvim_create_autocmd({ "BufNew" }, {
group = augroup,
callback = function(args)
---@type string
local path = args.match
---@type integer
local bufnr = args.buf
---@type string? The file extension if detected
local extension = vim.fn.fnamemodify(path, ":e")
---@type string? The filename if detected
local filename = vim.fn.fnamemodify(path, ":t")
---Open a given file path in a given program and remove the buffer for the file.
---@param buf integer The buffer handle for the opening buffer
---@param fpath string The file path given to the program
---@param fname string The file name used in notifications
---@param prog string The program to execute against the file path
local function open_in_prog(buf, fpath, fname, prog)
vim.notify(
string.format("Opening `%s` in `%s`", fname, prog),
vim.log.levels.INFO,
{
title = "Open File in External Program",
---@param win integer The window handle
on_open = function(win)
vim.api.nvim_buf_set_option(
vim.api.nvim_win_get_buf(win),
"filetype",
"markdown"
)
end
}
)
vim.system({ prog, fpath }, { detach = true })
vim.api.nvim_buf_delete(buf, { force = true })
end
local extension_callbacks = {
["pdf"] = function(buf, fpath, fname)
open_in_prog(buf, fpath, fname, "zathura")
end,
["png"] = function(buf, fpath, fname)
open_in_prog(buf, fpath, fname, "feh")
end,
["jpg"] = "png",
["mp4"] = function(buf, fpath, fname)
open_in_prog(buf, fpath, fname, "mpv")
end,
["gif"] = "mp4"
}
---Get the extension callback for a given extension. Will do a recursive lookup if an extension callback is actually
---of type string to get the correct extension
---@param ext string A file extension. Example: `png`.
---@return fun(bufnr: integer, path: string, filename: string?) extension_callback The extension callback to invoke, expects a buffer handle, file path, and filename.
local function extension_lookup(ext)
local callback = extension_callbacks[ext]
if type(callback) == "string" then
callback = extension_lookup(callback)
end
return callback
end
if extension ~= nil and not extension:match("^%s*$") and intercept_file_open then
local callback = extension_lookup(extension)
if type(callback) == "function" then
callback(bufnr, path, filename)
end
end
end
})
end
return M