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
|
|
@ -1,11 +1,11 @@
|
|||
local config = require("oil.config")
|
||||
local constants = require("oil.constants")
|
||||
local files = require("oil.adapters.files")
|
||||
local fs = require("oil.fs")
|
||||
local loading = require("oil.loading")
|
||||
local pathutil = require("oil.pathutil")
|
||||
local s3fs = require("oil.adapters.s3.s3fs")
|
||||
local util = require("oil.util")
|
||||
local config = require('oil.config')
|
||||
local constants = require('oil.constants')
|
||||
local files = require('oil.adapters.files')
|
||||
local fs = require('oil.fs')
|
||||
local loading = require('oil.loading')
|
||||
local pathutil = require('oil.pathutil')
|
||||
local s3fs = require('oil.adapters.s3.s3fs')
|
||||
local util = require('oil.util')
|
||||
local M = {}
|
||||
|
||||
local FIELD_META = constants.FIELD_META
|
||||
|
|
@ -21,11 +21,11 @@ M.parse_url = function(oil_url)
|
|||
local scheme, url = util.parse_url(oil_url)
|
||||
assert(scheme and url, string.format("Malformed input url '%s'", oil_url))
|
||||
local ret = { scheme = scheme }
|
||||
local bucket, path = url:match("^([^/]+)/?(.*)$")
|
||||
local bucket, path = url:match('^([^/]+)/?(.*)$')
|
||||
ret.bucket = bucket
|
||||
ret.path = path ~= "" and path or nil
|
||||
ret.path = path ~= '' and path or nil
|
||||
if not ret.bucket and ret.path then
|
||||
error(string.format("Parsing error for s3 url: %s", oil_url))
|
||||
error(string.format('Parsing error for s3 url: %s', oil_url))
|
||||
end
|
||||
---@cast ret oil.s3Url
|
||||
return ret
|
||||
|
|
@ -36,43 +36,43 @@ end
|
|||
local function url_to_str(url)
|
||||
local pieces = { url.scheme }
|
||||
if url.bucket then
|
||||
assert(url.bucket ~= "")
|
||||
assert(url.bucket ~= '')
|
||||
table.insert(pieces, url.bucket)
|
||||
table.insert(pieces, "/")
|
||||
table.insert(pieces, '/')
|
||||
end
|
||||
if url.path then
|
||||
assert(url.path ~= "")
|
||||
assert(url.path ~= '')
|
||||
table.insert(pieces, url.path)
|
||||
end
|
||||
return table.concat(pieces, "")
|
||||
return table.concat(pieces, '')
|
||||
end
|
||||
|
||||
---@param url oil.s3Url
|
||||
---@param is_folder boolean
|
||||
---@return string
|
||||
local function url_to_s3(url, is_folder)
|
||||
local pieces = { "s3://" }
|
||||
local pieces = { 's3://' }
|
||||
if url.bucket then
|
||||
assert(url.bucket ~= "")
|
||||
assert(url.bucket ~= '')
|
||||
table.insert(pieces, url.bucket)
|
||||
table.insert(pieces, "/")
|
||||
table.insert(pieces, '/')
|
||||
end
|
||||
if url.path then
|
||||
assert(url.path ~= "")
|
||||
assert(url.path ~= '')
|
||||
table.insert(pieces, url.path)
|
||||
if is_folder and not vim.endswith(url.path, "/") then
|
||||
table.insert(pieces, "/")
|
||||
if is_folder and not vim.endswith(url.path, '/') then
|
||||
table.insert(pieces, '/')
|
||||
end
|
||||
end
|
||||
return table.concat(pieces, "")
|
||||
return table.concat(pieces, '')
|
||||
end
|
||||
|
||||
---@param url oil.s3Url
|
||||
---@return boolean
|
||||
local function is_bucket(url)
|
||||
assert(url.bucket and url.bucket ~= "")
|
||||
assert(url.bucket and url.bucket ~= '')
|
||||
if url.path then
|
||||
assert(url.path ~= "")
|
||||
assert(url.path ~= '')
|
||||
return false
|
||||
end
|
||||
return true
|
||||
|
|
@ -83,20 +83,20 @@ s3_columns.size = {
|
|||
render = function(entry, conf)
|
||||
local meta = entry[FIELD_META]
|
||||
if not meta or not meta.size then
|
||||
return ""
|
||||
return ''
|
||||
elseif meta.size >= 1e9 then
|
||||
return string.format("%.1fG", meta.size / 1e9)
|
||||
return string.format('%.1fG', meta.size / 1e9)
|
||||
elseif meta.size >= 1e6 then
|
||||
return string.format("%.1fM", meta.size / 1e6)
|
||||
return string.format('%.1fM', meta.size / 1e6)
|
||||
elseif meta.size >= 1e3 then
|
||||
return string.format("%.1fk", meta.size / 1e3)
|
||||
return string.format('%.1fk', meta.size / 1e3)
|
||||
else
|
||||
return string.format("%d", meta.size)
|
||||
return string.format('%d', meta.size)
|
||||
end
|
||||
end,
|
||||
|
||||
parse = function(line, conf)
|
||||
return line:match("^(%d+%S*)%s+(.*)$")
|
||||
return line:match('^(%d+%S*)%s+(.*)$')
|
||||
end,
|
||||
|
||||
get_sort_value = function(entry)
|
||||
|
|
@ -113,21 +113,21 @@ s3_columns.birthtime = {
|
|||
render = function(entry, conf)
|
||||
local meta = entry[FIELD_META]
|
||||
if not meta or not meta.date then
|
||||
return ""
|
||||
return ''
|
||||
else
|
||||
return meta.date
|
||||
end
|
||||
end,
|
||||
|
||||
parse = function(line, conf)
|
||||
return line:match("^(%d+%-%d+%-%d+%s%d+:%d+:%d+)%s+(.*)$")
|
||||
return line:match('^(%d+%-%d+%-%d+%s%d+:%d+:%d+)%s+(.*)$')
|
||||
end,
|
||||
|
||||
get_sort_value = function(entry)
|
||||
local meta = entry[FIELD_META]
|
||||
if meta and meta.date then
|
||||
local year, month, day, hour, min, sec =
|
||||
meta.date:match("^(%d+)%-(%d+)%-(%d+)%s(%d+):(%d+):(%d+)$")
|
||||
meta.date:match('^(%d+)%-(%d+)%-(%d+)%s(%d+):(%d+):(%d+)$')
|
||||
local time =
|
||||
os.time({ year = year, month = month, day = day, hour = hour, min = min, sec = sec })
|
||||
return time
|
||||
|
|
@ -148,9 +148,9 @@ end
|
|||
M.get_parent = function(bufname)
|
||||
local res = M.parse_url(bufname)
|
||||
if res.path then
|
||||
assert(res.path ~= "")
|
||||
assert(res.path ~= '')
|
||||
local path = pathutil.parent(res.path)
|
||||
res.path = path ~= "" and path or nil
|
||||
res.path = path ~= '' and path or nil
|
||||
else
|
||||
res.bucket = nil
|
||||
end
|
||||
|
|
@ -168,8 +168,8 @@ end
|
|||
---@param column_defs string[]
|
||||
---@param callback fun(err?: string, entries?: oil.InternalEntry[], fetch_more?: fun())
|
||||
M.list = function(url, column_defs, callback)
|
||||
if vim.fn.executable("aws") ~= 1 then
|
||||
callback("`aws` is not executable. Can you run `aws s3 ls`?")
|
||||
if vim.fn.executable('aws') ~= 1 then
|
||||
callback('`aws` is not executable. Can you run `aws s3 ls`?')
|
||||
return
|
||||
end
|
||||
|
||||
|
|
@ -187,16 +187,16 @@ end
|
|||
---@param action oil.Action
|
||||
---@return string
|
||||
M.render_action = function(action)
|
||||
local is_folder = action.entry_type == "directory"
|
||||
if action.type == "create" then
|
||||
local is_folder = action.entry_type == 'directory'
|
||||
if action.type == 'create' then
|
||||
local res = M.parse_url(action.url)
|
||||
local extra = is_bucket(res) and "BUCKET " or ""
|
||||
return string.format("CREATE %s%s", extra, url_to_s3(res, is_folder))
|
||||
elseif action.type == "delete" then
|
||||
local extra = is_bucket(res) and 'BUCKET ' or ''
|
||||
return string.format('CREATE %s%s', extra, url_to_s3(res, is_folder))
|
||||
elseif action.type == 'delete' then
|
||||
local res = M.parse_url(action.url)
|
||||
local extra = is_bucket(res) and "BUCKET " or ""
|
||||
return string.format("DELETE %s%s", extra, url_to_s3(res, is_folder))
|
||||
elseif action.type == "move" or action.type == "copy" then
|
||||
local extra = is_bucket(res) and 'BUCKET ' or ''
|
||||
return string.format('DELETE %s%s', extra, url_to_s3(res, is_folder))
|
||||
elseif action.type == 'move' or action.type == 'copy' then
|
||||
local src = action.src_url
|
||||
local dest = action.dest_url
|
||||
if config.get_adapter_by_scheme(src) ~= M then
|
||||
|
|
@ -210,7 +210,7 @@ M.render_action = function(action)
|
|||
dest = files.to_short_os_path(path, action.entry_type)
|
||||
src = url_to_s3(M.parse_url(src), is_folder)
|
||||
end
|
||||
return string.format(" %s %s -> %s", action.type:upper(), src, dest)
|
||||
return string.format(' %s %s -> %s', action.type:upper(), src, dest)
|
||||
else
|
||||
error(string.format("Bad action type: '%s'", action.type))
|
||||
end
|
||||
|
|
@ -219,30 +219,30 @@ end
|
|||
---@param action oil.Action
|
||||
---@param cb fun(err: nil|string)
|
||||
M.perform_action = function(action, cb)
|
||||
local is_folder = action.entry_type == "directory"
|
||||
if action.type == "create" then
|
||||
local is_folder = action.entry_type == 'directory'
|
||||
if action.type == 'create' then
|
||||
local res = M.parse_url(action.url)
|
||||
local bucket = is_bucket(res)
|
||||
|
||||
if action.entry_type == "directory" and bucket then
|
||||
if action.entry_type == 'directory' and bucket then
|
||||
s3fs.mb(url_to_s3(res, true), cb)
|
||||
elseif action.entry_type == "directory" or action.entry_type == "file" then
|
||||
elseif action.entry_type == 'directory' or action.entry_type == 'file' then
|
||||
s3fs.touch(url_to_s3(res, is_folder), cb)
|
||||
else
|
||||
cb(string.format("Bad entry type on s3 create action: %s", action.entry_type))
|
||||
cb(string.format('Bad entry type on s3 create action: %s', action.entry_type))
|
||||
end
|
||||
elseif action.type == "delete" then
|
||||
elseif action.type == 'delete' then
|
||||
local res = M.parse_url(action.url)
|
||||
local bucket = is_bucket(res)
|
||||
|
||||
if action.entry_type == "directory" and bucket then
|
||||
if action.entry_type == 'directory' and bucket then
|
||||
s3fs.rb(url_to_s3(res, true), cb)
|
||||
elseif action.entry_type == "directory" or action.entry_type == "file" then
|
||||
elseif action.entry_type == 'directory' or action.entry_type == 'file' then
|
||||
s3fs.rm(url_to_s3(res, is_folder), is_folder, cb)
|
||||
else
|
||||
cb(string.format("Bad entry type on s3 delete action: %s", action.entry_type))
|
||||
cb(string.format('Bad entry type on s3 delete action: %s', action.entry_type))
|
||||
end
|
||||
elseif action.type == "move" then
|
||||
elseif action.type == 'move' then
|
||||
local src_adapter = assert(config.get_adapter_by_scheme(action.src_url))
|
||||
local dest_adapter = assert(config.get_adapter_by_scheme(action.dest_url))
|
||||
if
|
||||
|
|
@ -250,7 +250,7 @@ M.perform_action = function(action, cb)
|
|||
then
|
||||
cb(
|
||||
string.format(
|
||||
"We should never attempt to move from the %s adapter to the %s adapter.",
|
||||
'We should never attempt to move from the %s adapter to the %s adapter.',
|
||||
src_adapter.name,
|
||||
dest_adapter.name
|
||||
)
|
||||
|
|
@ -276,7 +276,7 @@ M.perform_action = function(action, cb)
|
|||
assert(dest)
|
||||
|
||||
s3fs.mv(src, dest, is_folder, cb)
|
||||
elseif action.type == "copy" then
|
||||
elseif action.type == 'copy' then
|
||||
local src_adapter = assert(config.get_adapter_by_scheme(action.src_url))
|
||||
local dest_adapter = assert(config.get_adapter_by_scheme(action.dest_url))
|
||||
if
|
||||
|
|
@ -284,7 +284,7 @@ M.perform_action = function(action, cb)
|
|||
then
|
||||
cb(
|
||||
string.format(
|
||||
"We should never attempt to copy from the %s adapter to the %s adapter.",
|
||||
'We should never attempt to copy from the %s adapter to the %s adapter.',
|
||||
src_adapter.name,
|
||||
dest_adapter.name
|
||||
)
|
||||
|
|
@ -311,11 +311,11 @@ M.perform_action = function(action, cb)
|
|||
|
||||
s3fs.cp(src, dest, is_folder, cb)
|
||||
else
|
||||
cb(string.format("Bad action type: %s", action.type))
|
||||
cb(string.format('Bad action type: %s', action.type))
|
||||
end
|
||||
end
|
||||
|
||||
M.supported_cross_adapter_actions = { files = "move" }
|
||||
M.supported_cross_adapter_actions = { files = 'move' }
|
||||
|
||||
---@param bufnr integer
|
||||
M.read_file = function(bufnr)
|
||||
|
|
@ -323,11 +323,11 @@ M.read_file = function(bufnr)
|
|||
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
||||
local url = M.parse_url(bufname)
|
||||
local basename = pathutil.basename(bufname)
|
||||
local cache_dir = vim.fn.stdpath("cache")
|
||||
assert(type(cache_dir) == "string")
|
||||
local tmpdir = fs.join(cache_dir, "oil")
|
||||
local cache_dir = vim.fn.stdpath('cache')
|
||||
assert(type(cache_dir) == 'string')
|
||||
local tmpdir = fs.join(cache_dir, 'oil')
|
||||
fs.mkdirp(tmpdir)
|
||||
local fd, tmpfile = vim.loop.fs_mkstemp(fs.join(tmpdir, "s3_XXXXXX"))
|
||||
local fd, tmpfile = vim.loop.fs_mkstemp(fs.join(tmpdir, 's3_XXXXXX'))
|
||||
if fd then
|
||||
vim.loop.fs_close(fd)
|
||||
end
|
||||
|
|
@ -336,9 +336,9 @@ M.read_file = function(bufnr)
|
|||
s3fs.cp(url_to_s3(url, false), tmpfile, false, function(err)
|
||||
loading.set_loading(bufnr, false)
|
||||
vim.bo[bufnr].modifiable = true
|
||||
vim.cmd.doautocmd({ args = { "BufReadPre", bufname }, mods = { silent = true } })
|
||||
vim.cmd.doautocmd({ args = { 'BufReadPre', bufname }, mods = { silent = true } })
|
||||
if err then
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, vim.split(err, "\n"))
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, vim.split(err, '\n'))
|
||||
else
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, {})
|
||||
vim.api.nvim_buf_call(bufnr, function()
|
||||
|
|
@ -352,7 +352,7 @@ M.read_file = function(bufnr)
|
|||
if filetype then
|
||||
vim.bo[bufnr].filetype = filetype
|
||||
end
|
||||
vim.cmd.doautocmd({ args = { "BufReadPost", bufname }, mods = { silent = true } })
|
||||
vim.cmd.doautocmd({ args = { 'BufReadPost', bufname }, mods = { silent = true } })
|
||||
vim.api.nvim_buf_delete(tmp_bufnr, { force = true })
|
||||
end)
|
||||
end
|
||||
|
|
@ -361,14 +361,14 @@ end
|
|||
M.write_file = function(bufnr)
|
||||
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
||||
local url = M.parse_url(bufname)
|
||||
local cache_dir = vim.fn.stdpath("cache")
|
||||
assert(type(cache_dir) == "string")
|
||||
local tmpdir = fs.join(cache_dir, "oil")
|
||||
local fd, tmpfile = vim.loop.fs_mkstemp(fs.join(tmpdir, "s3_XXXXXXXX"))
|
||||
local cache_dir = vim.fn.stdpath('cache')
|
||||
assert(type(cache_dir) == 'string')
|
||||
local tmpdir = fs.join(cache_dir, 'oil')
|
||||
local fd, tmpfile = vim.loop.fs_mkstemp(fs.join(tmpdir, 's3_XXXXXXXX'))
|
||||
if fd then
|
||||
vim.loop.fs_close(fd)
|
||||
end
|
||||
vim.cmd.doautocmd({ args = { "BufWritePre", bufname }, mods = { silent = true } })
|
||||
vim.cmd.doautocmd({ args = { 'BufWritePre', bufname }, mods = { silent = true } })
|
||||
vim.bo[bufnr].modifiable = false
|
||||
vim.cmd.write({ args = { tmpfile }, bang = true, mods = { silent = true, noautocmd = true } })
|
||||
local tmp_bufnr = vim.fn.bufadd(tmpfile)
|
||||
|
|
@ -376,10 +376,10 @@ M.write_file = function(bufnr)
|
|||
s3fs.cp(tmpfile, url_to_s3(url, false), false, function(err)
|
||||
vim.bo[bufnr].modifiable = true
|
||||
if err then
|
||||
vim.notify(string.format("Error writing file: %s", err), vim.log.levels.ERROR)
|
||||
vim.notify(string.format('Error writing file: %s', err), vim.log.levels.ERROR)
|
||||
else
|
||||
vim.bo[bufnr].modified = false
|
||||
vim.cmd.doautocmd({ args = { "BufWritePost", bufname }, mods = { silent = true } })
|
||||
vim.cmd.doautocmd({ args = { 'BufWritePost', bufname }, mods = { silent = true } })
|
||||
end
|
||||
vim.loop.fs_unlink(tmpfile)
|
||||
vim.api.nvim_buf_delete(tmp_bufnr, { force = true })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue