build: replace luacheck with selene, add nix devshell and pre-commit (#20)
* build: replace luacheck with selene Problem: luacheck is unmaintained (last release 2018) and required suppressing four warning classes to avoid false positives. It also lacks first-class vim/neovim awareness. Solution: switch to selene with std='vim' for vim-aware linting. Replace the luacheck CI job with selene, update the Makefile lint target, and delete .luacheckrc. * build: add nix devshell and pre-commit hooks Problem: oil.nvim had no reproducible dev environment. The .envrc set up a Python venv for the now-removed docgen pipeline, and there were no pre-commit hooks for local formatting checks. Solution: add flake.nix with stylua, selene, and prettier in the devshell. Replace the stale Python .envrc with 'use flake'. Add .pre-commit-config.yaml with stylua and prettier hooks matching other plugins in the repo collection. * fix: format with stylua * build(selene): configure lints and add inline suppressions Problem: selene fails on 5 errors and 3 warnings from upstream code patterns that are intentional (mixed tables in config API, unused callback parameters, identical if branches for readability). Solution: globally allow mixed_table and unused_variable (high volume, inherent to the codebase design). Add inline selene:allow directives for the 8 remaining issues: if_same_then_else (4), mismatched_arg_count (1), empty_if (2), global_usage (1). Remove .envrc from tracking. * build: switch typecheck action to mrcjkb/lua-typecheck-action Problem: oil.nvim used stevearc/nvim-typecheck-action, which required cloning the action repo locally for the Makefile lint target. All other plugins in the collection use mrcjkb/lua-typecheck-action. Solution: swap to mrcjkb/lua-typecheck-action@v0 for consistency. Remove the nvim-typecheck-action git clone from the Makefile and .gitignore. Drop LuaLS from the local lint target since it requires a full language server install — CI handles it.
This commit is contained in:
parent
df53b172a9
commit
86f553cd0a
72 changed files with 2762 additions and 2649 deletions
317
lua/oil/util.lua
317
lua/oil/util.lua
|
|
@ -1,5 +1,5 @@
|
|||
local config = require("oil.config")
|
||||
local constants = require("oil.constants")
|
||||
local config = require('oil.config')
|
||||
local constants = require('oil.constants')
|
||||
|
||||
local M = {}
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ local FIELD_META = constants.FIELD_META
|
|||
---@return nil|string
|
||||
---@return nil|string
|
||||
M.parse_url = function(url)
|
||||
return url:match("^(.*://)(.*)$")
|
||||
return url:match('^(.*://)(.*)$')
|
||||
end
|
||||
|
||||
---Escapes a filename for use in :edit
|
||||
|
|
@ -26,51 +26,51 @@ M.escape_filename = function(filename)
|
|||
end
|
||||
|
||||
local _url_escape_to_char = {
|
||||
["20"] = " ",
|
||||
["22"] = "“",
|
||||
["23"] = "#",
|
||||
["24"] = "$",
|
||||
["25"] = "%",
|
||||
["26"] = "&",
|
||||
["27"] = "‘",
|
||||
["2B"] = "+",
|
||||
["2C"] = ",",
|
||||
["2F"] = "/",
|
||||
["3A"] = ":",
|
||||
["3B"] = ";",
|
||||
["3C"] = "<",
|
||||
["3D"] = "=",
|
||||
["3E"] = ">",
|
||||
["3F"] = "?",
|
||||
["40"] = "@",
|
||||
["5B"] = "[",
|
||||
["5C"] = "\\",
|
||||
["5D"] = "]",
|
||||
["5E"] = "^",
|
||||
["60"] = "`",
|
||||
["7B"] = "{",
|
||||
["7C"] = "|",
|
||||
["7D"] = "}",
|
||||
["7E"] = "~",
|
||||
['20'] = ' ',
|
||||
['22'] = '“',
|
||||
['23'] = '#',
|
||||
['24'] = '$',
|
||||
['25'] = '%',
|
||||
['26'] = '&',
|
||||
['27'] = '‘',
|
||||
['2B'] = '+',
|
||||
['2C'] = ',',
|
||||
['2F'] = '/',
|
||||
['3A'] = ':',
|
||||
['3B'] = ';',
|
||||
['3C'] = '<',
|
||||
['3D'] = '=',
|
||||
['3E'] = '>',
|
||||
['3F'] = '?',
|
||||
['40'] = '@',
|
||||
['5B'] = '[',
|
||||
['5C'] = '\\',
|
||||
['5D'] = ']',
|
||||
['5E'] = '^',
|
||||
['60'] = '`',
|
||||
['7B'] = '{',
|
||||
['7C'] = '|',
|
||||
['7D'] = '}',
|
||||
['7E'] = '~',
|
||||
}
|
||||
local _char_to_url_escape = {}
|
||||
for k, v in pairs(_url_escape_to_char) do
|
||||
_char_to_url_escape[v] = "%" .. k
|
||||
_char_to_url_escape[v] = '%' .. k
|
||||
end
|
||||
-- TODO this uri escape handling is very incomplete
|
||||
|
||||
---@param string string
|
||||
---@return string
|
||||
M.url_escape = function(string)
|
||||
return (string:gsub(".", _char_to_url_escape))
|
||||
return (string:gsub('.', _char_to_url_escape))
|
||||
end
|
||||
|
||||
---@param string string
|
||||
---@return string
|
||||
M.url_unescape = function(string)
|
||||
return (
|
||||
string:gsub("%%([0-9A-Fa-f][0-9A-Fa-f])", function(seq)
|
||||
return _url_escape_to_char[seq:upper()] or ("%" .. seq)
|
||||
string:gsub('%%([0-9A-Fa-f][0-9A-Fa-f])', function(seq)
|
||||
return _url_escape_to_char[seq:upper()] or ('%' .. seq)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
|
@ -105,14 +105,14 @@ M.pad_align = function(text, width, align)
|
|||
return text, 0
|
||||
end
|
||||
|
||||
if align == "right" then
|
||||
return string.rep(" ", total_pad) .. text, total_pad
|
||||
elseif align == "center" then
|
||||
if align == 'right' then
|
||||
return string.rep(' ', total_pad) .. text, total_pad
|
||||
elseif align == 'center' then
|
||||
local left_pad = math.floor(total_pad / 2)
|
||||
local right_pad = total_pad - left_pad
|
||||
return string.rep(" ", left_pad) .. text .. string.rep(" ", right_pad), left_pad
|
||||
return string.rep(' ', left_pad) .. text .. string.rep(' ', right_pad), left_pad
|
||||
else
|
||||
return text .. string.rep(" ", total_pad), 0
|
||||
return text .. string.rep(' ', total_pad), 0
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ end
|
|||
---@param dest_buf_name string
|
||||
---@return boolean True if the buffer was replaced instead of renamed
|
||||
M.rename_buffer = function(src_bufnr, dest_buf_name)
|
||||
if type(src_bufnr) == "string" then
|
||||
if type(src_bufnr) == 'string' then
|
||||
src_bufnr = vim.fn.bufadd(src_bufnr)
|
||||
if not vim.api.nvim_buf_is_loaded(src_bufnr) then
|
||||
vim.api.nvim_buf_delete(src_bufnr, {})
|
||||
|
|
@ -164,7 +164,7 @@ M.rename_buffer = function(src_bufnr, dest_buf_name)
|
|||
-- think that the new buffer conflicts with the file next time it tries to save.
|
||||
if not vim.loop.fs_stat(dest_buf_name) then
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
local altbuf = vim.fn.bufnr("#")
|
||||
local altbuf = vim.fn.bufnr('#')
|
||||
-- This will fail if the dest buf name already exists
|
||||
local ok = pcall(vim.api.nvim_buf_set_name, src_bufnr, dest_buf_name)
|
||||
if ok then
|
||||
|
|
@ -173,7 +173,7 @@ M.rename_buffer = function(src_bufnr, dest_buf_name)
|
|||
-- where Neovim doesn't allow buffer modifications.
|
||||
pcall(vim.api.nvim_buf_delete, vim.fn.bufadd(bufname), {})
|
||||
if altbuf and vim.api.nvim_buf_is_valid(altbuf) then
|
||||
vim.fn.setreg("#", altbuf)
|
||||
vim.fn.setreg('#', altbuf)
|
||||
end
|
||||
|
||||
return false
|
||||
|
|
@ -229,6 +229,7 @@ end
|
|||
M.cb_collect = function(count, cb)
|
||||
return function(err)
|
||||
if err then
|
||||
-- selene: allow(mismatched_arg_count)
|
||||
cb(err)
|
||||
cb = function() end
|
||||
else
|
||||
|
|
@ -243,9 +244,9 @@ end
|
|||
---@param url string
|
||||
---@return string[]
|
||||
local function get_possible_buffer_names_from_url(url)
|
||||
local fs = require("oil.fs")
|
||||
local fs = require('oil.fs')
|
||||
local scheme, path = M.parse_url(url)
|
||||
if config.adapters[scheme] == "files" then
|
||||
if config.adapters[scheme] == 'files' then
|
||||
assert(path)
|
||||
return { fs.posix_to_os_path(path) }
|
||||
end
|
||||
|
|
@ -258,7 +259,7 @@ end
|
|||
M.update_moved_buffers = function(entry_type, src_url, dest_url)
|
||||
local src_buf_names = get_possible_buffer_names_from_url(src_url)
|
||||
local dest_buf_name = get_possible_buffer_names_from_url(dest_url)[1]
|
||||
if entry_type ~= "directory" then
|
||||
if entry_type ~= 'directory' then
|
||||
for _, src_buf_name in ipairs(src_buf_names) do
|
||||
M.rename_buffer(src_buf_name, dest_buf_name)
|
||||
end
|
||||
|
|
@ -272,13 +273,13 @@ M.update_moved_buffers = function(entry_type, src_url, dest_url)
|
|||
if vim.startswith(bufname, src_url) then
|
||||
-- Handle oil directory buffers
|
||||
vim.api.nvim_buf_set_name(bufnr, dest_url .. bufname:sub(src_url:len() + 1))
|
||||
elseif bufname ~= "" and vim.bo[bufnr].buftype == "" then
|
||||
elseif bufname ~= '' and vim.bo[bufnr].buftype == '' then
|
||||
-- Handle regular buffers
|
||||
local scheme = M.parse_url(bufname)
|
||||
|
||||
-- If the buffer is a local file, make sure we're using the absolute path
|
||||
if not scheme then
|
||||
bufname = vim.fn.fnamemodify(bufname, ":p")
|
||||
bufname = vim.fn.fnamemodify(bufname, ':p')
|
||||
end
|
||||
|
||||
for _, src_buf_name in ipairs(src_buf_names) do
|
||||
|
|
@ -296,13 +297,13 @@ end
|
|||
---@return string
|
||||
---@return table|nil
|
||||
M.split_config = function(name_or_config)
|
||||
if type(name_or_config) == "string" then
|
||||
if type(name_or_config) == 'string' then
|
||||
return name_or_config, nil
|
||||
else
|
||||
if not name_or_config[1] and name_or_config["1"] then
|
||||
if not name_or_config[1] and name_or_config['1'] then
|
||||
-- This was likely loaded from json, so the first element got coerced to a string key
|
||||
name_or_config[1] = name_or_config["1"]
|
||||
name_or_config["1"] = nil
|
||||
name_or_config[1] = name_or_config['1']
|
||||
name_or_config['1'] = nil
|
||||
end
|
||||
return name_or_config[1], name_or_config
|
||||
end
|
||||
|
|
@ -324,7 +325,7 @@ M.render_table = function(lines, col_width, col_align)
|
|||
local pieces = {}
|
||||
for i, chunk in ipairs(cols) do
|
||||
local text, hl
|
||||
if type(chunk) == "table" then
|
||||
if type(chunk) == 'table' then
|
||||
text = chunk[1]
|
||||
hl = chunk[2]
|
||||
else
|
||||
|
|
@ -333,11 +334,11 @@ M.render_table = function(lines, col_width, col_align)
|
|||
|
||||
local unpadded_len = text:len()
|
||||
local padding
|
||||
text, padding = M.pad_align(text, col_width[i], col_align[i] or "left")
|
||||
text, padding = M.pad_align(text, col_width[i], col_align[i] or 'left')
|
||||
|
||||
table.insert(pieces, text)
|
||||
if hl then
|
||||
if type(hl) == "table" then
|
||||
if type(hl) == 'table' then
|
||||
-- hl has the form { [1]: hl_name, [2]: col_start, [3]: col_end }[]
|
||||
-- Notice that col_start and col_end are relative position inside
|
||||
-- that col, so we need to add the offset to them
|
||||
|
|
@ -355,7 +356,7 @@ M.render_table = function(lines, col_width, col_align)
|
|||
end
|
||||
col = col + text:len() + 1
|
||||
end
|
||||
table.insert(str_lines, table.concat(pieces, " "))
|
||||
table.insert(str_lines, table.concat(pieces, ' '))
|
||||
end
|
||||
return str_lines, highlights
|
||||
end
|
||||
|
|
@ -363,7 +364,7 @@ end
|
|||
---@param bufnr integer
|
||||
---@param highlights any[][] List of highlights {group, lnum, col_start, col_end}
|
||||
M.set_highlights = function(bufnr, highlights)
|
||||
local ns = vim.api.nvim_create_namespace("Oil")
|
||||
local ns = vim.api.nvim_create_namespace('Oil')
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
|
||||
for _, hl in ipairs(highlights) do
|
||||
local group, line, col_start, col_end = unpack(hl)
|
||||
|
|
@ -379,12 +380,12 @@ end
|
|||
---@param os_slash? boolean use os filesystem slash instead of posix slash
|
||||
---@return string
|
||||
M.addslash = function(path, os_slash)
|
||||
local slash = "/"
|
||||
if os_slash and require("oil.fs").is_windows then
|
||||
slash = "\\"
|
||||
local slash = '/'
|
||||
if os_slash and require('oil.fs').is_windows then
|
||||
slash = '\\'
|
||||
end
|
||||
|
||||
local endslash = path:match(slash .. "$")
|
||||
local endslash = path:match(slash .. '$')
|
||||
if not endslash then
|
||||
return path .. slash
|
||||
else
|
||||
|
|
@ -395,7 +396,7 @@ end
|
|||
---@param winid nil|integer
|
||||
---@return boolean
|
||||
M.is_floating_win = function(winid)
|
||||
return vim.api.nvim_win_get_config(winid or 0).relative ~= ""
|
||||
return vim.api.nvim_win_get_config(winid or 0).relative ~= ''
|
||||
end
|
||||
|
||||
---Recalculate the window title for the current buffer
|
||||
|
|
@ -410,10 +411,10 @@ M.get_title = function(winid)
|
|||
local title = vim.api.nvim_buf_get_name(src_buf)
|
||||
local scheme, path = M.parse_url(title)
|
||||
|
||||
if config.adapters[scheme] == "files" then
|
||||
if config.adapters[scheme] == 'files' then
|
||||
assert(path)
|
||||
local fs = require("oil.fs")
|
||||
title = vim.fn.fnamemodify(fs.posix_to_os_path(path), ":~")
|
||||
local fs = require('oil.fs')
|
||||
title = vim.fn.fnamemodify(fs.posix_to_os_path(path), ':~')
|
||||
end
|
||||
return title
|
||||
end
|
||||
|
|
@ -421,7 +422,7 @@ end
|
|||
local winid_map = {}
|
||||
M.add_title_to_win = function(winid, opts)
|
||||
opts = opts or {}
|
||||
opts.align = opts.align or "left"
|
||||
opts.align = opts.align or 'left'
|
||||
if not vim.api.nvim_win_is_valid(winid) then
|
||||
return
|
||||
end
|
||||
|
|
@ -438,18 +439,18 @@ M.add_title_to_win = function(winid, opts)
|
|||
else
|
||||
bufnr = vim.api.nvim_create_buf(false, true)
|
||||
local col = 1
|
||||
if opts.align == "center" then
|
||||
if opts.align == 'center' then
|
||||
col = math.floor((vim.api.nvim_win_get_width(winid) - width) / 2)
|
||||
elseif opts.align == "right" then
|
||||
elseif opts.align == 'right' then
|
||||
col = vim.api.nvim_win_get_width(winid) - 1 - width
|
||||
elseif opts.align ~= "left" then
|
||||
elseif opts.align ~= 'left' then
|
||||
vim.notify(
|
||||
string.format("Unknown oil window title alignment: '%s'", opts.align),
|
||||
vim.log.levels.ERROR
|
||||
)
|
||||
end
|
||||
title_winid = vim.api.nvim_open_win(bufnr, false, {
|
||||
relative = "win",
|
||||
relative = 'win',
|
||||
win = winid,
|
||||
width = width,
|
||||
height = 1,
|
||||
|
|
@ -457,20 +458,20 @@ M.add_title_to_win = function(winid, opts)
|
|||
col = col,
|
||||
focusable = false,
|
||||
zindex = 151,
|
||||
style = "minimal",
|
||||
style = 'minimal',
|
||||
noautocmd = true,
|
||||
})
|
||||
winid_map[winid] = title_winid
|
||||
vim.api.nvim_set_option_value(
|
||||
"winblend",
|
||||
'winblend',
|
||||
vim.wo[winid].winblend,
|
||||
{ scope = "local", win = title_winid }
|
||||
{ scope = 'local', win = title_winid }
|
||||
)
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].bufhidden = 'wipe'
|
||||
|
||||
local update_autocmd = vim.api.nvim_create_autocmd("BufWinEnter", {
|
||||
desc = "Update oil floating window title when buffer changes",
|
||||
pattern = "*",
|
||||
local update_autocmd = vim.api.nvim_create_autocmd('BufWinEnter', {
|
||||
desc = 'Update oil floating window title when buffer changes',
|
||||
pattern = '*',
|
||||
callback = function(params)
|
||||
local winbuf = params.buf
|
||||
if vim.api.nvim_win_get_buf(winid) ~= winbuf then
|
||||
|
|
@ -479,17 +480,17 @@ M.add_title_to_win = function(winid, opts)
|
|||
local new_title = M.get_title(winid)
|
||||
local new_width =
|
||||
math.min(vim.api.nvim_win_get_width(winid) - 4, 2 + vim.api.nvim_strwidth(new_title))
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { " " .. new_title .. " " })
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { ' ' .. new_title .. ' ' })
|
||||
vim.bo[bufnr].modified = false
|
||||
vim.api.nvim_win_set_width(title_winid, new_width)
|
||||
local new_col = 1
|
||||
if opts.align == "center" then
|
||||
if opts.align == 'center' then
|
||||
new_col = math.floor((vim.api.nvim_win_get_width(winid) - new_width) / 2)
|
||||
elseif opts.align == "right" then
|
||||
elseif opts.align == 'right' then
|
||||
new_col = vim.api.nvim_win_get_width(winid) - 1 - new_width
|
||||
end
|
||||
vim.api.nvim_win_set_config(title_winid, {
|
||||
relative = "win",
|
||||
relative = 'win',
|
||||
win = winid,
|
||||
row = -1,
|
||||
col = new_col,
|
||||
|
|
@ -498,8 +499,8 @@ M.add_title_to_win = function(winid, opts)
|
|||
})
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd("WinClosed", {
|
||||
desc = "Close oil floating window title when floating window closes",
|
||||
vim.api.nvim_create_autocmd('WinClosed', {
|
||||
desc = 'Close oil floating window title when floating window closes',
|
||||
pattern = tostring(winid),
|
||||
callback = function()
|
||||
if title_winid and vim.api.nvim_win_is_valid(title_winid) then
|
||||
|
|
@ -512,12 +513,12 @@ M.add_title_to_win = function(winid, opts)
|
|||
nested = true,
|
||||
})
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { " " .. title .. " " })
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { ' ' .. title .. ' ' })
|
||||
vim.bo[bufnr].modified = false
|
||||
vim.api.nvim_set_option_value(
|
||||
"winhighlight",
|
||||
"Normal:FloatTitle,NormalFloat:FloatTitle",
|
||||
{ scope = "local", win = title_winid }
|
||||
'winhighlight',
|
||||
'Normal:FloatTitle,NormalFloat:FloatTitle',
|
||||
{ scope = 'local', win = title_winid }
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -542,7 +543,7 @@ M.get_adapter_for_action = function(action)
|
|||
else
|
||||
error(
|
||||
string.format(
|
||||
"Cannot copy files from %s -> %s; no cross-adapter transfer method found",
|
||||
'Cannot copy files from %s -> %s; no cross-adapter transfer method found',
|
||||
action.src_url,
|
||||
action.dest_url
|
||||
)
|
||||
|
|
@ -559,12 +560,12 @@ end
|
|||
---@return string
|
||||
---@return integer
|
||||
M.h_align = function(str, align, width)
|
||||
if align == "center" then
|
||||
if align == 'center' then
|
||||
local padding = math.floor((width - vim.api.nvim_strwidth(str)) / 2)
|
||||
return string.rep(" ", padding) .. str, padding
|
||||
elseif align == "right" then
|
||||
return string.rep(' ', padding) .. str, padding
|
||||
elseif align == 'right' then
|
||||
local padding = width - vim.api.nvim_strwidth(str)
|
||||
return string.rep(" ", padding) .. str, padding
|
||||
return string.rep(' ', padding) .. str, padding
|
||||
else
|
||||
return str, 0
|
||||
end
|
||||
|
|
@ -578,15 +579,15 @@ end
|
|||
--- actions nil|string[]
|
||||
--- winid nil|integer
|
||||
M.render_text = function(bufnr, text, opts)
|
||||
opts = vim.tbl_deep_extend("keep", opts or {}, {
|
||||
h_align = "center",
|
||||
v_align = "center",
|
||||
opts = vim.tbl_deep_extend('keep', opts or {}, {
|
||||
h_align = 'center',
|
||||
v_align = 'center',
|
||||
})
|
||||
---@cast opts -nil
|
||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
||||
return
|
||||
end
|
||||
if type(text) == "string" then
|
||||
if type(text) == 'string' then
|
||||
text = { text }
|
||||
end
|
||||
local height = 40
|
||||
|
|
@ -608,17 +609,17 @@ M.render_text = function(bufnr, text, opts)
|
|||
local lines = {}
|
||||
|
||||
-- Add vertical spacing for vertical alignment
|
||||
if opts.v_align == "center" then
|
||||
if opts.v_align == 'center' then
|
||||
for _ = 1, (height / 2) - (#text / 2) do
|
||||
table.insert(lines, "")
|
||||
table.insert(lines, '')
|
||||
end
|
||||
elseif opts.v_align == "bottom" then
|
||||
elseif opts.v_align == 'bottom' then
|
||||
local num_lines = height
|
||||
if opts.actions then
|
||||
num_lines = num_lines - 2
|
||||
end
|
||||
while #lines + #text < num_lines do
|
||||
table.insert(lines, "")
|
||||
table.insert(lines, '')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -632,12 +633,12 @@ M.render_text = function(bufnr, text, opts)
|
|||
local highlights = {}
|
||||
if opts.actions then
|
||||
while #lines < height - 1 do
|
||||
table.insert(lines, "")
|
||||
table.insert(lines, '')
|
||||
end
|
||||
local last_line, padding = M.h_align(table.concat(opts.actions, " "), "center", width)
|
||||
local last_line, padding = M.h_align(table.concat(opts.actions, ' '), 'center', width)
|
||||
local col = padding
|
||||
for _, action in ipairs(opts.actions) do
|
||||
table.insert(highlights, { "Special", #lines, col, col + 3 })
|
||||
table.insert(highlights, { 'Special', #lines, col, col + 3 })
|
||||
col = padding + action:len() + 4
|
||||
end
|
||||
table.insert(lines, last_line)
|
||||
|
|
@ -656,10 +657,10 @@ end
|
|||
M.run_in_fullscreen_win = function(bufnr, callback)
|
||||
if not bufnr then
|
||||
bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].bufhidden = 'wipe'
|
||||
end
|
||||
local winid = vim.api.nvim_open_win(bufnr, false, {
|
||||
relative = "editor",
|
||||
relative = 'editor',
|
||||
width = vim.o.columns,
|
||||
height = vim.o.lines,
|
||||
row = 0,
|
||||
|
|
@ -667,7 +668,7 @@ M.run_in_fullscreen_win = function(bufnr, callback)
|
|||
noautocmd = true,
|
||||
})
|
||||
local winnr = vim.api.nvim_win_get_number(winid)
|
||||
vim.cmd.wincmd({ count = winnr, args = { "w" }, mods = { noautocmd = true } })
|
||||
vim.cmd.wincmd({ count = winnr, args = { 'w' }, mods = { noautocmd = true } })
|
||||
callback()
|
||||
vim.cmd.close({ count = winnr, mods = { noautocmd = true, emsg_silent = true } })
|
||||
end
|
||||
|
|
@ -676,9 +677,9 @@ end
|
|||
---@return boolean
|
||||
M.is_oil_bufnr = function(bufnr)
|
||||
local filetype = vim.bo[bufnr].filetype
|
||||
if filetype == "oil" then
|
||||
if filetype == 'oil' then
|
||||
return true
|
||||
elseif filetype ~= "" then
|
||||
elseif filetype ~= '' then
|
||||
-- If the filetype is set and is NOT "oil", then it's not an oil buffer
|
||||
return false
|
||||
end
|
||||
|
|
@ -693,10 +694,10 @@ M.hack_around_termopen_autocmd = function(prev_mode)
|
|||
vim.defer_fn(function()
|
||||
local new_mode = vim.api.nvim_get_mode().mode
|
||||
if new_mode ~= prev_mode then
|
||||
if string.find(new_mode, "i") == 1 then
|
||||
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<ESC>", true, true, true), "n", false)
|
||||
if string.find(prev_mode, "v") == 1 or string.find(prev_mode, "V") == 1 then
|
||||
vim.cmd.normal({ bang = true, args = { "gv" } })
|
||||
if string.find(new_mode, 'i') == 1 then
|
||||
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<ESC>', true, true, true), 'n', false)
|
||||
if string.find(prev_mode, 'v') == 1 or string.find(prev_mode, 'V') == 1 then
|
||||
vim.cmd.normal({ bang = true, args = { 'gv' } })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -712,7 +713,7 @@ M.get_preview_win = function(opts)
|
|||
if
|
||||
vim.api.nvim_win_is_valid(winid)
|
||||
and vim.wo[winid].previewwindow
|
||||
and (opts.include_not_owned or vim.w[winid]["oil_preview"])
|
||||
and (opts.include_not_owned or vim.w[winid]['oil_preview'])
|
||||
then
|
||||
return winid
|
||||
end
|
||||
|
|
@ -721,13 +722,13 @@ end
|
|||
|
||||
---@return fun() restore Function that restores the cursor
|
||||
M.hide_cursor = function()
|
||||
vim.api.nvim_set_hl(0, "OilPreviewCursor", { nocombine = true, blend = 100 })
|
||||
vim.api.nvim_set_hl(0, 'OilPreviewCursor', { nocombine = true, blend = 100 })
|
||||
local original_guicursor = vim.go.guicursor
|
||||
vim.go.guicursor = "a:OilPreviewCursor/OilPreviewCursor"
|
||||
vim.go.guicursor = 'a:OilPreviewCursor/OilPreviewCursor'
|
||||
|
||||
return function()
|
||||
-- HACK: see https://github.com/neovim/neovim/issues/21018
|
||||
vim.go.guicursor = "a:"
|
||||
vim.go.guicursor = 'a:'
|
||||
vim.cmd.redrawstatus()
|
||||
vim.go.guicursor = original_guicursor
|
||||
end
|
||||
|
|
@ -762,7 +763,7 @@ end
|
|||
---@param opts {columns?: string[], no_cache?: boolean}
|
||||
---@param callback fun(err: nil|string, entries: nil|oil.InternalEntry[])
|
||||
M.adapter_list_all = function(adapter, url, opts, callback)
|
||||
local cache = require("oil.cache")
|
||||
local cache = require('oil.cache')
|
||||
if not opts.no_cache then
|
||||
local entries = cache.list_url(url)
|
||||
if not vim.tbl_isempty(entries) then
|
||||
|
|
@ -790,23 +791,23 @@ end
|
|||
---based on the provided options.
|
||||
---@param opts {target?: "qflist"|"loclist", action?: "r"|"a", only_matching_search?: boolean}
|
||||
M.send_to_quickfix = function(opts)
|
||||
if type(opts) ~= "table" then
|
||||
if type(opts) ~= 'table' then
|
||||
opts = {}
|
||||
end
|
||||
local oil = require("oil")
|
||||
local oil = require('oil')
|
||||
local dir = oil.get_current_dir()
|
||||
if type(dir) ~= "string" then
|
||||
if type(dir) ~= 'string' then
|
||||
return
|
||||
end
|
||||
local range = M.get_visual_range()
|
||||
if not range then
|
||||
range = { start_lnum = 1, end_lnum = vim.fn.line("$") }
|
||||
range = { start_lnum = 1, end_lnum = vim.fn.line('$') }
|
||||
end
|
||||
local match_all = not opts.only_matching_search
|
||||
local qf_entries = {}
|
||||
for i = range.start_lnum, range.end_lnum do
|
||||
local entry = oil.get_entry_on_line(0, i)
|
||||
if entry and entry.type == "file" and (match_all or M.is_matching(entry)) then
|
||||
if entry and entry.type == 'file' and (match_all or M.is_matching(entry)) then
|
||||
local qf_entry = {
|
||||
filename = dir .. entry.name,
|
||||
lnum = 1,
|
||||
|
|
@ -817,26 +818,26 @@ M.send_to_quickfix = function(opts)
|
|||
end
|
||||
end
|
||||
if #qf_entries == 0 then
|
||||
vim.notify("[oil] No entries found to send to quickfix", vim.log.levels.WARN)
|
||||
vim.notify('[oil] No entries found to send to quickfix', vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
vim.api.nvim_exec_autocmds("QuickFixCmdPre", {})
|
||||
local qf_title = "oil files"
|
||||
local action = opts.action == "a" and "a" or "r"
|
||||
if opts.target == "loclist" then
|
||||
vim.api.nvim_exec_autocmds('QuickFixCmdPre', {})
|
||||
local qf_title = 'oil files'
|
||||
local action = opts.action == 'a' and 'a' or 'r'
|
||||
if opts.target == 'loclist' then
|
||||
vim.fn.setloclist(0, {}, action, { title = qf_title, items = qf_entries })
|
||||
vim.cmd.lopen()
|
||||
else
|
||||
vim.fn.setqflist({}, action, { title = qf_title, items = qf_entries })
|
||||
vim.cmd.copen()
|
||||
end
|
||||
vim.api.nvim_exec_autocmds("QuickFixCmdPost", {})
|
||||
vim.api.nvim_exec_autocmds('QuickFixCmdPost', {})
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
M.is_visual_mode = function()
|
||||
local mode = vim.api.nvim_get_mode().mode
|
||||
return mode:match("^[vV]") ~= nil
|
||||
return mode:match('^[vV]') ~= nil
|
||||
end
|
||||
|
||||
---Get the current visual selection range. If not in visual mode, return nil.
|
||||
|
|
@ -847,7 +848,7 @@ M.get_visual_range = function()
|
|||
end
|
||||
-- This is the best way to get the visual selection at the moment
|
||||
-- https://github.com/neovim/neovim/pull/13896
|
||||
local _, start_lnum, _, _ = unpack(vim.fn.getpos("v"))
|
||||
local _, start_lnum, _, _ = unpack(vim.fn.getpos('v'))
|
||||
local _, end_lnum, _, _, _ = unpack(vim.fn.getcurpos())
|
||||
if start_lnum > end_lnum then
|
||||
start_lnum, end_lnum = end_lnum, start_lnum
|
||||
|
|
@ -863,7 +864,7 @@ M.is_matching = function(entry)
|
|||
if search_highlighting_is_off then
|
||||
return true
|
||||
end
|
||||
local pattern = vim.fn.getreg("/")
|
||||
local pattern = vim.fn.getreg('/')
|
||||
local position_of_match = vim.fn.match(entry.name, pattern)
|
||||
return position_of_match ~= -1
|
||||
end
|
||||
|
|
@ -877,8 +878,8 @@ M.run_after_load = function(bufnr, callback)
|
|||
if vim.b[bufnr].oil_ready then
|
||||
callback()
|
||||
else
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "OilEnter",
|
||||
vim.api.nvim_create_autocmd('User', {
|
||||
pattern = 'OilEnter',
|
||||
callback = function(args)
|
||||
if args.data.buf == bufnr then
|
||||
vim.api.nvim_buf_call(bufnr, callback)
|
||||
|
|
@ -892,12 +893,12 @@ end
|
|||
---@param entry oil.Entry
|
||||
---@return boolean
|
||||
M.is_directory = function(entry)
|
||||
local is_directory = entry.type == "directory"
|
||||
local is_directory = entry.type == 'directory'
|
||||
or (
|
||||
entry.type == "link"
|
||||
entry.type == 'link'
|
||||
and entry.meta
|
||||
and entry.meta.link_stat
|
||||
and entry.meta.link_stat.type == "directory"
|
||||
and entry.meta.link_stat.type == 'directory'
|
||||
)
|
||||
return is_directory == true
|
||||
end
|
||||
|
|
@ -907,7 +908,7 @@ end
|
|||
---@param entry oil.Entry
|
||||
---@param callback fun(normalized_url: string)
|
||||
M.get_edit_path = function(bufnr, entry, callback)
|
||||
local pathutil = require("oil.pathutil")
|
||||
local pathutil = require('oil.pathutil')
|
||||
|
||||
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
||||
local scheme, dir = M.parse_url(bufname)
|
||||
|
|
@ -916,10 +917,10 @@ M.get_edit_path = function(bufnr, entry, callback)
|
|||
|
||||
local url = scheme .. dir .. entry.name
|
||||
if M.is_directory(entry) then
|
||||
url = url .. "/"
|
||||
url = url .. '/'
|
||||
end
|
||||
|
||||
if entry.name == ".." then
|
||||
if entry.name == '..' then
|
||||
callback(scheme .. pathutil.parent(dir))
|
||||
elseif adapter.get_entry_path then
|
||||
adapter.get_entry_path(url, entry, callback)
|
||||
|
|
@ -932,33 +933,34 @@ end
|
|||
---@return (oil.IconProvider)?
|
||||
M.get_icon_provider = function()
|
||||
-- prefer mini.icons
|
||||
local _, mini_icons = pcall(require, "mini.icons")
|
||||
local _, mini_icons = pcall(require, 'mini.icons')
|
||||
-- selene: allow(global_usage)
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
if _G.MiniIcons then -- `_G.MiniIcons` is a better check to see if the module is setup
|
||||
if _G.MiniIcons then
|
||||
return function(type, name, conf, ft)
|
||||
if ft then
|
||||
return mini_icons.get("filetype", ft)
|
||||
return mini_icons.get('filetype', ft)
|
||||
end
|
||||
return mini_icons.get(type == "directory" and "directory" or "file", name)
|
||||
return mini_icons.get(type == 'directory' and 'directory' or 'file', name)
|
||||
end
|
||||
end
|
||||
|
||||
-- fallback to `nvim-web-devicons`
|
||||
local has_devicons, devicons = pcall(require, "nvim-web-devicons")
|
||||
local has_devicons, devicons = pcall(require, 'nvim-web-devicons')
|
||||
if has_devicons then
|
||||
return function(type, name, conf, ft)
|
||||
if type == "directory" then
|
||||
return conf and conf.directory or "", "OilDirIcon"
|
||||
if type == 'directory' then
|
||||
return conf and conf.directory or '', 'OilDirIcon'
|
||||
else
|
||||
if ft then
|
||||
local ft_icon, ft_hl = devicons.get_icon_by_filetype(ft)
|
||||
if ft_icon and ft_icon ~= "" then
|
||||
if ft_icon and ft_icon ~= '' then
|
||||
return ft_icon, ft_hl
|
||||
end
|
||||
end
|
||||
local icon, hl = devicons.get_icon(name)
|
||||
hl = hl or "OilFileIcon"
|
||||
icon = icon or (conf and conf.default_file or "")
|
||||
hl = hl or 'OilFileIcon'
|
||||
icon = icon or (conf and conf.default_file or '')
|
||||
return icon, hl
|
||||
end
|
||||
end
|
||||
|
|
@ -975,24 +977,25 @@ M.read_file_to_scratch_buffer = function(path, preview_method)
|
|||
return
|
||||
end
|
||||
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].buftype = "nofile"
|
||||
vim.bo[bufnr].bufhidden = 'wipe'
|
||||
vim.bo[bufnr].buftype = 'nofile'
|
||||
|
||||
local has_lines, read_res
|
||||
if preview_method == "fast_scratch" then
|
||||
has_lines, read_res = pcall(vim.fn.readfile, path, "", vim.o.lines)
|
||||
if preview_method == 'fast_scratch' then
|
||||
has_lines, read_res = pcall(vim.fn.readfile, path, '', vim.o.lines)
|
||||
else
|
||||
has_lines, read_res = pcall(vim.fn.readfile, path)
|
||||
end
|
||||
local lines = has_lines and vim.split(table.concat(read_res, "\n"), "\n") or {}
|
||||
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 ~= "" and vim.treesitter.language.get_lang then
|
||||
if ft and ft ~= '' and vim.treesitter.language.get_lang then
|
||||
local lang = vim.treesitter.language.get_lang(ft)
|
||||
-- selene: allow(empty_if)
|
||||
if not pcall(vim.treesitter.start, bufnr, lang) then
|
||||
vim.bo[bufnr].syntax = ft
|
||||
else
|
||||
|
|
@ -1000,8 +1003,8 @@ M.read_file_to_scratch_buffer = function(path, preview_method)
|
|||
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",
|
||||
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()
|
||||
|
|
@ -1013,7 +1016,7 @@ M.read_file_to_scratch_buffer = function(path, preview_method)
|
|||
-- 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.bo.bufhidden = 'wipe'
|
||||
vim.b.oil_preview_buffer = true
|
||||
end
|
||||
end
|
||||
|
|
@ -1030,7 +1033,7 @@ local _regcache = {}
|
|||
---@return boolean
|
||||
M.file_matches_bufreadcmd = function(filename)
|
||||
local autocmds = vim.api.nvim_get_autocmds({
|
||||
event = "BufReadCmd",
|
||||
event = 'BufReadCmd',
|
||||
})
|
||||
for _, au in ipairs(autocmds) do
|
||||
local pat = _regcache[au.pattern]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue