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,7 +1,7 @@
|
|||
local columns = require("oil.columns")
|
||||
local config = require("oil.config")
|
||||
local layout = require("oil.layout")
|
||||
local util = require("oil.util")
|
||||
local columns = require('oil.columns')
|
||||
local config = require('oil.config')
|
||||
local layout = require('oil.layout')
|
||||
local util = require('oil.util')
|
||||
local M = {}
|
||||
|
||||
---@param actions oil.Action[]
|
||||
|
|
@ -12,17 +12,17 @@ local function is_simple_edit(actions)
|
|||
local num_move = 0
|
||||
for _, action in ipairs(actions) do
|
||||
-- If there are any deletes, it is not a simple edit
|
||||
if action.type == "delete" then
|
||||
if action.type == 'delete' then
|
||||
return false
|
||||
elseif action.type == "create" then
|
||||
elseif action.type == 'create' then
|
||||
num_create = num_create + 1
|
||||
elseif action.type == "copy" then
|
||||
elseif action.type == 'copy' then
|
||||
num_copy = num_copy + 1
|
||||
-- Cross-adapter copies are not simple
|
||||
if util.parse_url(action.src_url) ~= util.parse_url(action.dest_url) then
|
||||
return false
|
||||
end
|
||||
elseif action.type == "move" then
|
||||
elseif action.type == 'move' then
|
||||
num_move = num_move + 1
|
||||
-- Cross-adapter moves are not simple
|
||||
if util.parse_url(action.src_url) ~= util.parse_url(action.dest_url) then
|
||||
|
|
@ -46,10 +46,10 @@ end
|
|||
---@param lines string[]
|
||||
local function render_lines(winid, bufnr, lines)
|
||||
util.render_text(bufnr, lines, {
|
||||
v_align = "top",
|
||||
h_align = "left",
|
||||
v_align = 'top',
|
||||
h_align = 'left',
|
||||
winid = winid,
|
||||
actions = { "[Y]es", "[N]o" },
|
||||
actions = { '[Y]es', '[N]o' },
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -70,48 +70,48 @@ M.show = vim.schedule_wrap(function(actions, should_confirm, cb)
|
|||
|
||||
-- Create the buffer
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].bufhidden = 'wipe'
|
||||
local lines = {}
|
||||
local max_line_width = 0
|
||||
for _, action in ipairs(actions) do
|
||||
local adapter = util.get_adapter_for_action(action)
|
||||
local line
|
||||
if action.type == "change" then
|
||||
if action.type == 'change' then
|
||||
---@cast action oil.ChangeAction
|
||||
line = columns.render_change_action(adapter, action)
|
||||
else
|
||||
line = adapter.render_action(action)
|
||||
end
|
||||
-- We can't handle lines with newlines in them
|
||||
line = line:gsub("\n", "")
|
||||
line = line:gsub('\n', '')
|
||||
table.insert(lines, line)
|
||||
local line_width = vim.api.nvim_strwidth(line)
|
||||
if line_width > max_line_width then
|
||||
max_line_width = line_width
|
||||
end
|
||||
end
|
||||
table.insert(lines, "")
|
||||
table.insert(lines, '')
|
||||
|
||||
-- Create the floating window
|
||||
local width, height = layout.calculate_dims(max_line_width, #lines + 1, config.confirmation)
|
||||
local ok, winid = pcall(vim.api.nvim_open_win, bufnr, true, {
|
||||
relative = "editor",
|
||||
relative = 'editor',
|
||||
width = width,
|
||||
height = height,
|
||||
row = math.floor((layout.get_editor_height() - height) / 2),
|
||||
col = math.floor((layout.get_editor_width() - width) / 2),
|
||||
zindex = 152, -- render on top of the floating window title
|
||||
style = "minimal",
|
||||
style = 'minimal',
|
||||
border = config.confirmation.border,
|
||||
})
|
||||
if not ok then
|
||||
vim.notify(string.format("Error showing oil preview window: %s", winid), vim.log.levels.ERROR)
|
||||
vim.notify(string.format('Error showing oil preview window: %s', winid), vim.log.levels.ERROR)
|
||||
cb(false)
|
||||
end
|
||||
vim.bo[bufnr].filetype = "oil_preview"
|
||||
vim.bo[bufnr].syntax = "oil_preview"
|
||||
vim.bo[bufnr].filetype = 'oil_preview'
|
||||
vim.bo[bufnr].syntax = 'oil_preview'
|
||||
for k, v in pairs(config.confirmation.win_options) do
|
||||
vim.api.nvim_set_option_value(k, v, { scope = "local", win = winid })
|
||||
vim.api.nvim_set_option_value(k, v, { scope = 'local', win = winid })
|
||||
end
|
||||
|
||||
render_lines(winid, bufnr, lines)
|
||||
|
|
@ -137,7 +137,7 @@ M.show = vim.schedule_wrap(function(actions, should_confirm, cb)
|
|||
end
|
||||
cancel = make_callback(false)
|
||||
confirm = make_callback(true)
|
||||
vim.api.nvim_create_autocmd("BufLeave", {
|
||||
vim.api.nvim_create_autocmd('BufLeave', {
|
||||
callback = function()
|
||||
cancel()
|
||||
end,
|
||||
|
|
@ -145,7 +145,7 @@ M.show = vim.schedule_wrap(function(actions, should_confirm, cb)
|
|||
nested = true,
|
||||
buffer = bufnr,
|
||||
})
|
||||
vim.api.nvim_create_autocmd("WinLeave", {
|
||||
vim.api.nvim_create_autocmd('WinLeave', {
|
||||
callback = function()
|
||||
cancel()
|
||||
end,
|
||||
|
|
@ -154,12 +154,12 @@ M.show = vim.schedule_wrap(function(actions, should_confirm, cb)
|
|||
})
|
||||
table.insert(
|
||||
autocmds,
|
||||
vim.api.nvim_create_autocmd("VimResized", {
|
||||
vim.api.nvim_create_autocmd('VimResized', {
|
||||
callback = function()
|
||||
if vim.api.nvim_win_is_valid(winid) then
|
||||
width, height = layout.calculate_dims(max_line_width, #lines, config.confirmation)
|
||||
vim.api.nvim_win_set_config(winid, {
|
||||
relative = "editor",
|
||||
relative = 'editor',
|
||||
width = width,
|
||||
height = height,
|
||||
row = math.floor((layout.get_editor_height() - height) / 2),
|
||||
|
|
@ -173,17 +173,17 @@ M.show = vim.schedule_wrap(function(actions, should_confirm, cb)
|
|||
)
|
||||
|
||||
-- We used to use [C]ancel to cancel, so preserve the old keymap
|
||||
local cancel_keys = { "n", "N", "c", "C", "q", "<C-c>", "<Esc>" }
|
||||
local cancel_keys = { 'n', 'N', 'c', 'C', 'q', '<C-c>', '<Esc>' }
|
||||
for _, cancel_key in ipairs(cancel_keys) do
|
||||
vim.keymap.set("n", cancel_key, function()
|
||||
vim.keymap.set('n', cancel_key, function()
|
||||
cancel()
|
||||
end, { buffer = bufnr, nowait = true })
|
||||
end
|
||||
|
||||
-- We used to use [O]k to confirm, so preserve the old keymap
|
||||
local confirm_keys = { "y", "Y", "o", "O" }
|
||||
local confirm_keys = { 'y', 'Y', 'o', 'O' }
|
||||
for _, confirm_key in ipairs(confirm_keys) do
|
||||
vim.keymap.set("n", confirm_key, function()
|
||||
vim.keymap.set('n', confirm_key, function()
|
||||
confirm()
|
||||
end, { buffer = bufnr, nowait = true })
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
local Progress = require("oil.mutator.progress")
|
||||
local Trie = require("oil.mutator.trie")
|
||||
local cache = require("oil.cache")
|
||||
local columns = require("oil.columns")
|
||||
local config = require("oil.config")
|
||||
local confirmation = require("oil.mutator.confirmation")
|
||||
local constants = require("oil.constants")
|
||||
local fs = require("oil.fs")
|
||||
local lsp_helpers = require("oil.lsp.helpers")
|
||||
local oil = require("oil")
|
||||
local parser = require("oil.mutator.parser")
|
||||
local util = require("oil.util")
|
||||
local view = require("oil.view")
|
||||
local Progress = require('oil.mutator.progress')
|
||||
local Trie = require('oil.mutator.trie')
|
||||
local cache = require('oil.cache')
|
||||
local columns = require('oil.columns')
|
||||
local config = require('oil.config')
|
||||
local confirmation = require('oil.mutator.confirmation')
|
||||
local constants = require('oil.constants')
|
||||
local fs = require('oil.fs')
|
||||
local lsp_helpers = require('oil.lsp.helpers')
|
||||
local oil = require('oil')
|
||||
local parser = require('oil.mutator.parser')
|
||||
local util = require('oil.util')
|
||||
local view = require('oil.view')
|
||||
local M = {}
|
||||
|
||||
local FIELD_NAME = constants.FIELD_NAME
|
||||
|
|
@ -73,7 +73,7 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
local function add_action(action)
|
||||
local adapter = assert(config.get_adapter_by_scheme(action.dest_url or action.url))
|
||||
if not adapter.filter_action or adapter.filter_action(action) then
|
||||
if action.type == "create" then
|
||||
if action.type == 'create' then
|
||||
if seen_creates[action.url] then
|
||||
return
|
||||
else
|
||||
|
|
@ -87,11 +87,11 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
for bufnr, diffs in pairs(all_diffs) do
|
||||
local adapter = util.get_adapter(bufnr, true)
|
||||
if not adapter then
|
||||
error("Missing adapter")
|
||||
error('Missing adapter')
|
||||
end
|
||||
local parent_url = vim.api.nvim_buf_get_name(bufnr)
|
||||
for _, diff in ipairs(diffs) do
|
||||
if diff.type == "new" then
|
||||
if diff.type == 'new' then
|
||||
if diff.id then
|
||||
local by_id = diff_by_id[diff.id]
|
||||
---HACK: set the destination on this diff for use later
|
||||
|
|
@ -100,28 +100,28 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
table.insert(by_id, diff)
|
||||
else
|
||||
-- Parse nested files like foo/bar/baz
|
||||
local path_sep = fs.is_windows and "[/\\]" or "/"
|
||||
local path_sep = fs.is_windows and '[/\\]' or '/'
|
||||
local pieces = vim.split(diff.name, path_sep)
|
||||
local url = parent_url:gsub("/$", "")
|
||||
local url = parent_url:gsub('/$', '')
|
||||
for i, v in ipairs(pieces) do
|
||||
local is_last = i == #pieces
|
||||
local entry_type = is_last and diff.entry_type or "directory"
|
||||
local alternation = v:match("{([^}]+)}")
|
||||
local entry_type = is_last and diff.entry_type or 'directory'
|
||||
local alternation = v:match('{([^}]+)}')
|
||||
if is_last and alternation then
|
||||
-- Parse alternations like foo.{js,test.js}
|
||||
for _, alt in ipairs(vim.split(alternation, ",")) do
|
||||
local alt_url = url .. "/" .. v:gsub("{[^}]+}", alt)
|
||||
for _, alt in ipairs(vim.split(alternation, ',')) do
|
||||
local alt_url = url .. '/' .. v:gsub('{[^}]+}', alt)
|
||||
add_action({
|
||||
type = "create",
|
||||
type = 'create',
|
||||
url = alt_url,
|
||||
entry_type = entry_type,
|
||||
link = diff.link,
|
||||
})
|
||||
end
|
||||
else
|
||||
url = url .. "/" .. v
|
||||
url = url .. '/' .. v
|
||||
add_action({
|
||||
type = "create",
|
||||
type = 'create',
|
||||
url = url,
|
||||
entry_type = entry_type,
|
||||
link = diff.link,
|
||||
|
|
@ -129,9 +129,9 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
end
|
||||
end
|
||||
end
|
||||
elseif diff.type == "change" then
|
||||
elseif diff.type == 'change' then
|
||||
add_action({
|
||||
type = "change",
|
||||
type = 'change',
|
||||
url = parent_url .. diff.name,
|
||||
entry_type = diff.entry_type,
|
||||
column = diff.column,
|
||||
|
|
@ -151,7 +151,7 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
for id, diffs in pairs(diff_by_id) do
|
||||
local entry = cache.get_entry_by_id(id)
|
||||
if not entry then
|
||||
error(string.format("Could not find entry %d", id))
|
||||
error(string.format('Could not find entry %d', id))
|
||||
end
|
||||
---HACK: access the has_delete field on the list-like table of diffs
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
|
|
@ -161,7 +161,7 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
-- MOVE (+ optional copies) when has both creates and delete
|
||||
for i, diff in ipairs(diffs) do
|
||||
add_action({
|
||||
type = i == #diffs and "move" or "copy",
|
||||
type = i == #diffs and 'move' or 'copy',
|
||||
entry_type = entry[FIELD_TYPE],
|
||||
---HACK: access the dest field we set above
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
|
|
@ -172,7 +172,7 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
else
|
||||
-- DELETE when no create
|
||||
add_action({
|
||||
type = "delete",
|
||||
type = 'delete',
|
||||
entry_type = entry[FIELD_TYPE],
|
||||
url = cache.get_parent_url(id) .. entry[FIELD_NAME],
|
||||
})
|
||||
|
|
@ -181,7 +181,7 @@ M.create_actions_from_diffs = function(all_diffs)
|
|||
-- COPY when create but no delete
|
||||
for _, diff in ipairs(diffs) do
|
||||
add_action({
|
||||
type = "copy",
|
||||
type = 'copy',
|
||||
entry_type = entry[FIELD_TYPE],
|
||||
src_url = cache.get_parent_url(id) .. entry[FIELD_NAME],
|
||||
---HACK: access the dest field we set above
|
||||
|
|
@ -201,9 +201,9 @@ M.enforce_action_order = function(actions)
|
|||
local src_trie = Trie.new()
|
||||
local dest_trie = Trie.new()
|
||||
for _, action in ipairs(actions) do
|
||||
if action.type == "delete" or action.type == "change" then
|
||||
if action.type == 'delete' or action.type == 'change' then
|
||||
src_trie:insert_action(action.url, action)
|
||||
elseif action.type == "create" then
|
||||
elseif action.type == 'create' then
|
||||
dest_trie:insert_action(action.url, action)
|
||||
else
|
||||
dest_trie:insert_action(action.dest_url, action)
|
||||
|
|
@ -223,18 +223,18 @@ M.enforce_action_order = function(actions)
|
|||
---@param action oil.Action
|
||||
local function get_deps(action)
|
||||
local ret = {}
|
||||
if action.type == "delete" then
|
||||
if action.type == 'delete' then
|
||||
src_trie:accum_children_of(action.url, ret)
|
||||
elseif action.type == "create" then
|
||||
elseif action.type == 'create' then
|
||||
-- Finish operating on parents first
|
||||
-- e.g. NEW /a BEFORE NEW /a/b
|
||||
dest_trie:accum_first_parents_of(action.url, ret)
|
||||
-- Process remove path before creating new path
|
||||
-- e.g. DELETE /a BEFORE NEW /a
|
||||
src_trie:accum_actions_at(action.url, ret, function(a)
|
||||
return a.type == "move" or a.type == "delete"
|
||||
return a.type == 'move' or a.type == 'delete'
|
||||
end)
|
||||
elseif action.type == "change" then
|
||||
elseif action.type == 'change' then
|
||||
-- Finish operating on parents first
|
||||
-- e.g. NEW /a BEFORE CHANGE /a/b
|
||||
dest_trie:accum_first_parents_of(action.url, ret)
|
||||
|
|
@ -244,9 +244,9 @@ M.enforce_action_order = function(actions)
|
|||
-- Finish copy from operations first
|
||||
-- e.g. COPY /a -> /b BEFORE CHANGE /a
|
||||
src_trie:accum_actions_at(action.url, ret, function(entry)
|
||||
return entry.type == "copy"
|
||||
return entry.type == 'copy'
|
||||
end)
|
||||
elseif action.type == "move" then
|
||||
elseif action.type == 'move' then
|
||||
-- Finish operating on parents first
|
||||
-- e.g. NEW /a BEFORE MOVE /z -> /a/b
|
||||
dest_trie:accum_first_parents_of(action.dest_url, ret)
|
||||
|
|
@ -260,9 +260,9 @@ M.enforce_action_order = function(actions)
|
|||
-- Process remove path before moving to new path
|
||||
-- e.g. MOVE /a -> /b BEFORE MOVE /c -> /a
|
||||
src_trie:accum_actions_at(action.dest_url, ret, function(a)
|
||||
return a.type == "move" or a.type == "delete"
|
||||
return a.type == 'move' or a.type == 'delete'
|
||||
end)
|
||||
elseif action.type == "copy" then
|
||||
elseif action.type == 'copy' then
|
||||
-- Finish operating on parents first
|
||||
-- e.g. NEW /a BEFORE COPY /z -> /a/b
|
||||
dest_trie:accum_first_parents_of(action.dest_url, ret)
|
||||
|
|
@ -272,7 +272,7 @@ M.enforce_action_order = function(actions)
|
|||
-- Process remove path before copying to new path
|
||||
-- e.g. MOVE /a -> /b BEFORE COPY /c -> /a
|
||||
src_trie:accum_actions_at(action.dest_url, ret, function(a)
|
||||
return a.type == "move" or a.type == "delete"
|
||||
return a.type == 'move' or a.type == 'delete'
|
||||
end)
|
||||
end
|
||||
return ret
|
||||
|
|
@ -312,24 +312,24 @@ M.enforce_action_order = function(actions)
|
|||
if selected then
|
||||
to_remove = selected
|
||||
else
|
||||
if loop_action and loop_action.type == "move" then
|
||||
if loop_action and loop_action.type == 'move' then
|
||||
-- If this is moving a parent into itself, that's an error
|
||||
if vim.startswith(loop_action.dest_url, loop_action.src_url) then
|
||||
error("Detected cycle in desired paths")
|
||||
error('Detected cycle in desired paths')
|
||||
end
|
||||
|
||||
-- We've detected a move cycle (e.g. MOVE /a -> /b + MOVE /b -> /a)
|
||||
-- Split one of the moves and retry
|
||||
local intermediate_url =
|
||||
string.format("%s__oil_tmp_%05d", loop_action.src_url, math.random(999999))
|
||||
string.format('%s__oil_tmp_%05d', loop_action.src_url, math.random(999999))
|
||||
local move_1 = {
|
||||
type = "move",
|
||||
type = 'move',
|
||||
entry_type = loop_action.entry_type,
|
||||
src_url = loop_action.src_url,
|
||||
dest_url = intermediate_url,
|
||||
}
|
||||
local move_2 = {
|
||||
type = "move",
|
||||
type = 'move',
|
||||
entry_type = loop_action.entry_type,
|
||||
src_url = intermediate_url,
|
||||
dest_url = loop_action.dest_url,
|
||||
|
|
@ -340,16 +340,16 @@ M.enforce_action_order = function(actions)
|
|||
dest_trie:insert_action(move_1.dest_url, move_1)
|
||||
src_trie:insert_action(move_1.src_url, move_1)
|
||||
else
|
||||
error("Detected cycle in desired paths")
|
||||
error('Detected cycle in desired paths')
|
||||
end
|
||||
end
|
||||
|
||||
if selected then
|
||||
if selected.type == "move" or selected.type == "copy" then
|
||||
if vim.startswith(selected.dest_url, selected.src_url .. "/") then
|
||||
if selected.type == 'move' or selected.type == 'copy' then
|
||||
if vim.startswith(selected.dest_url, selected.src_url .. '/') then
|
||||
error(
|
||||
string.format(
|
||||
"Cannot move or copy parent into itself: %s -> %s",
|
||||
'Cannot move or copy parent into itself: %s -> %s',
|
||||
selected.src_url,
|
||||
selected.dest_url
|
||||
)
|
||||
|
|
@ -360,9 +360,9 @@ M.enforce_action_order = function(actions)
|
|||
end
|
||||
|
||||
if to_remove then
|
||||
if to_remove.type == "delete" or to_remove.type == "change" then
|
||||
if to_remove.type == 'delete' or to_remove.type == 'change' then
|
||||
src_trie:remove_action(to_remove.url, to_remove)
|
||||
elseif to_remove.type == "create" then
|
||||
elseif to_remove.type == 'create' then
|
||||
dest_trie:remove_action(to_remove.url, to_remove)
|
||||
else
|
||||
dest_trie:remove_action(to_remove.dest_url, to_remove)
|
||||
|
|
@ -387,8 +387,8 @@ local progress
|
|||
---@param cb fun(err: nil|string)
|
||||
M.process_actions = function(actions, cb)
|
||||
vim.api.nvim_exec_autocmds(
|
||||
"User",
|
||||
{ pattern = "OilActionsPre", modeline = false, data = { actions = actions } }
|
||||
'User',
|
||||
{ pattern = 'OilActionsPre', modeline = false, data = { actions = actions } }
|
||||
)
|
||||
|
||||
local did_complete = nil
|
||||
|
|
@ -398,14 +398,14 @@ M.process_actions = function(actions, cb)
|
|||
|
||||
-- Convert some cross-adapter moves to a copy + delete
|
||||
for _, action in ipairs(actions) do
|
||||
if action.type == "move" then
|
||||
if action.type == 'move' then
|
||||
local _, cross_action = util.get_adapter_for_action(action)
|
||||
-- Only do the conversion if the cross-adapter support is "copy"
|
||||
if cross_action == "copy" then
|
||||
if cross_action == 'copy' then
|
||||
---@diagnostic disable-next-line: assign-type-mismatch
|
||||
action.type = "copy"
|
||||
action.type = 'copy'
|
||||
table.insert(actions, {
|
||||
type = "delete",
|
||||
type = 'delete',
|
||||
url = action.src_url,
|
||||
entry_type = action.entry_type,
|
||||
})
|
||||
|
|
@ -421,8 +421,8 @@ M.process_actions = function(actions, cb)
|
|||
progress:close()
|
||||
progress = nil
|
||||
vim.api.nvim_exec_autocmds(
|
||||
"User",
|
||||
{ pattern = "OilActionsPost", modeline = false, data = { err = err, actions = actions } }
|
||||
'User',
|
||||
{ pattern = 'OilActionsPost', modeline = false, data = { err = err, actions = actions } }
|
||||
)
|
||||
cb(err)
|
||||
end
|
||||
|
|
@ -435,7 +435,7 @@ M.process_actions = function(actions, cb)
|
|||
-- TODO some actions are actually cancelable.
|
||||
-- We should stop them instead of stopping after the current action
|
||||
cancel = function()
|
||||
finish("Canceled")
|
||||
finish('Canceled')
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
|
@ -472,7 +472,7 @@ M.process_actions = function(actions, cb)
|
|||
next_action()
|
||||
end
|
||||
end)
|
||||
if action.type == "change" then
|
||||
if action.type == 'change' then
|
||||
---@cast action oil.ChangeAction
|
||||
columns.perform_change_action(adapter, action, callback)
|
||||
else
|
||||
|
|
@ -502,7 +502,7 @@ M.try_write_changes = function(confirm, cb)
|
|||
cb = function(_err) end
|
||||
end
|
||||
if mutation_in_progress then
|
||||
cb("Cannot perform mutation when already in progress")
|
||||
cb('Cannot perform mutation when already in progress')
|
||||
return
|
||||
end
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
|
|
@ -537,7 +537,7 @@ M.try_write_changes = function(confirm, cb)
|
|||
mutation_in_progress = false
|
||||
end
|
||||
|
||||
local ns = vim.api.nvim_create_namespace("Oil")
|
||||
local ns = vim.api.nvim_create_namespace('Oil')
|
||||
vim.diagnostic.reset(ns)
|
||||
if not vim.tbl_isempty(all_errors) then
|
||||
for bufnr, errors in pairs(all_errors) do
|
||||
|
|
@ -564,7 +564,7 @@ M.try_write_changes = function(confirm, cb)
|
|||
end)
|
||||
end
|
||||
unlock()
|
||||
cb("Error parsing oil buffers")
|
||||
cb('Error parsing oil buffers')
|
||||
return
|
||||
end
|
||||
|
||||
|
|
@ -572,7 +572,7 @@ M.try_write_changes = function(confirm, cb)
|
|||
confirmation.show(actions, confirm, function(proceed)
|
||||
if not proceed then
|
||||
unlock()
|
||||
cb("Canceled")
|
||||
cb('Canceled')
|
||||
return
|
||||
end
|
||||
|
||||
|
|
@ -581,7 +581,7 @@ M.try_write_changes = function(confirm, cb)
|
|||
vim.schedule_wrap(function(err)
|
||||
view.unlock_buffers()
|
||||
if err then
|
||||
err = string.format("[oil] Error applying actions: %s", err)
|
||||
err = string.format('[oil] Error applying actions: %s', err)
|
||||
view.rerender_all_oil_buffers(nil, function()
|
||||
cb(err)
|
||||
end)
|
||||
|
|
@ -591,13 +591,13 @@ M.try_write_changes = function(confirm, cb)
|
|||
-- get the entry under the cursor and make sure the cursor stays on it
|
||||
view.set_last_cursor(
|
||||
vim.api.nvim_buf_get_name(0),
|
||||
vim.split(current_entry.parsed_name or current_entry.name, "/")[1]
|
||||
vim.split(current_entry.parsed_name or current_entry.name, '/')[1]
|
||||
)
|
||||
end
|
||||
view.rerender_all_oil_buffers(nil, function(render_err)
|
||||
vim.api.nvim_exec_autocmds(
|
||||
"User",
|
||||
{ pattern = "OilMutationComplete", modeline = false }
|
||||
'User',
|
||||
{ pattern = 'OilMutationComplete', modeline = false }
|
||||
)
|
||||
cb(render_err)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
local cache = require("oil.cache")
|
||||
local columns = require("oil.columns")
|
||||
local config = require("oil.config")
|
||||
local constants = require("oil.constants")
|
||||
local fs = require("oil.fs")
|
||||
local util = require("oil.util")
|
||||
local view = require("oil.view")
|
||||
local cache = require('oil.cache')
|
||||
local columns = require('oil.columns')
|
||||
local config = require('oil.config')
|
||||
local constants = require('oil.constants')
|
||||
local fs = require('oil.fs')
|
||||
local util = require('oil.util')
|
||||
local view = require('oil.view')
|
||||
local M = {}
|
||||
|
||||
local FIELD_ID = constants.FIELD_ID
|
||||
|
|
@ -37,7 +37,7 @@ local FIELD_META = constants.FIELD_META
|
|||
---@return string
|
||||
---@return boolean
|
||||
local function parsedir(name)
|
||||
local isdir = vim.endswith(name, "/") or (fs.is_windows and vim.endswith(name, "\\"))
|
||||
local isdir = vim.endswith(name, '/') or (fs.is_windows and vim.endswith(name, '\\'))
|
||||
if isdir then
|
||||
name = name:sub(1, name:len() - 1)
|
||||
end
|
||||
|
|
@ -52,8 +52,8 @@ local function compare_link_target(meta, parsed_entry)
|
|||
return false
|
||||
end
|
||||
-- Make sure we trim off any trailing path slashes from both sources
|
||||
local meta_name = meta.link:gsub("[/\\]$", "")
|
||||
local parsed_name = parsed_entry.link_target:gsub("[/\\]$", "")
|
||||
local meta_name = meta.link:gsub('[/\\]$', '')
|
||||
local parsed_name = parsed_entry.link_target:gsub('[/\\]$', '')
|
||||
return meta_name == parsed_name
|
||||
end
|
||||
|
||||
|
|
@ -72,9 +72,9 @@ M.parse_line = function(adapter, line, column_defs)
|
|||
local ret = {}
|
||||
local ranges = {}
|
||||
local start = 1
|
||||
local value, rem = line:match("^/(%d+) (.+)$")
|
||||
local value, rem = line:match('^/(%d+) (.+)$')
|
||||
if not value then
|
||||
return nil, "Malformed ID at start of line"
|
||||
return nil, 'Malformed ID at start of line'
|
||||
end
|
||||
ranges.id = { start, value:len() + 1 }
|
||||
start = ranges.id[2] + 1
|
||||
|
|
@ -97,7 +97,7 @@ M.parse_line = function(adapter, line, column_defs)
|
|||
local start_len = string.len(rem)
|
||||
value, rem = columns.parse_col(adapter, assert(rem), def)
|
||||
if not rem then
|
||||
return nil, string.format("Parsing %s failed", name)
|
||||
return nil, string.format('Parsing %s failed', name)
|
||||
end
|
||||
ret[name] = value
|
||||
range[2] = range[1] + start_len - string.len(rem) - 1
|
||||
|
|
@ -108,10 +108,10 @@ M.parse_line = function(adapter, line, column_defs)
|
|||
if name then
|
||||
local isdir
|
||||
name, isdir = parsedir(vim.trim(name))
|
||||
if name ~= "" then
|
||||
if name ~= '' then
|
||||
ret.name = name
|
||||
end
|
||||
ret._type = isdir and "directory" or "file"
|
||||
ret._type = isdir and 'directory' or 'file'
|
||||
end
|
||||
local entry = cache.get_entry_by_id(ret.id)
|
||||
ranges.name = { start, start + string.len(rem) - 1 }
|
||||
|
|
@ -122,20 +122,20 @@ M.parse_line = function(adapter, line, column_defs)
|
|||
-- Parse the symlink syntax
|
||||
local meta = entry[FIELD_META]
|
||||
local entry_type = entry[FIELD_TYPE]
|
||||
if entry_type == "link" and meta and meta.link then
|
||||
local name_pieces = vim.split(ret.name, " -> ", { plain = true })
|
||||
if entry_type == 'link' and meta and meta.link then
|
||||
local name_pieces = vim.split(ret.name, ' -> ', { plain = true })
|
||||
if #name_pieces ~= 2 then
|
||||
ret.name = ""
|
||||
ret.name = ''
|
||||
return { data = ret, ranges = ranges }
|
||||
end
|
||||
ranges.name = { start, start + string.len(name_pieces[1]) - 1 }
|
||||
ret.name = parsedir(vim.trim(name_pieces[1]))
|
||||
ret.link_target = name_pieces[2]
|
||||
ret._type = "link"
|
||||
ret._type = 'link'
|
||||
end
|
||||
|
||||
-- Try to keep the same file type
|
||||
if entry_type ~= "directory" and entry_type ~= "file" and ret._type ~= "directory" then
|
||||
if entry_type ~= 'directory' and entry_type ~= 'file' and ret._type ~= 'directory' then
|
||||
ret._type = entry[FIELD_TYPE]
|
||||
end
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ M.parse = function(bufnr)
|
|||
name = name:lower()
|
||||
end
|
||||
if seen_names[name] then
|
||||
table.insert(errors, { message = "Duplicate filename", lnum = i - 1, end_lnum = i, col = 0 })
|
||||
table.insert(errors, { message = 'Duplicate filename', lnum = i - 1, end_lnum = i, col = 0 })
|
||||
else
|
||||
seen_names[name] = true
|
||||
end
|
||||
|
|
@ -197,7 +197,7 @@ M.parse = function(bufnr)
|
|||
-- hack to be compatible with Lua 5.1
|
||||
-- use return instead of goto
|
||||
(function()
|
||||
if line:match("^/%d+") then
|
||||
if line:match('^/%d+') then
|
||||
-- Parse the line for an existing entry
|
||||
local result, err = M.parse_line(adapter, line, column_defs)
|
||||
if not result or err then
|
||||
|
|
@ -217,11 +217,11 @@ M.parse = function(bufnr)
|
|||
|
||||
local err_message
|
||||
if not parsed_entry.name then
|
||||
err_message = "No filename found"
|
||||
err_message = 'No filename found'
|
||||
elseif not entry then
|
||||
err_message = "Could not find existing entry (was the ID changed?)"
|
||||
elseif parsed_entry.name:match("/") or parsed_entry.name:match(fs.sep) then
|
||||
err_message = "Filename cannot contain path separator"
|
||||
err_message = 'Could not find existing entry (was the ID changed?)'
|
||||
elseif parsed_entry.name:match('/') or parsed_entry.name:match(fs.sep) then
|
||||
err_message = 'Filename cannot contain path separator'
|
||||
end
|
||||
if err_message then
|
||||
table.insert(errors, {
|
||||
|
|
@ -237,16 +237,16 @@ M.parse = function(bufnr)
|
|||
check_dupe(parsed_entry.name, i)
|
||||
local meta = entry[FIELD_META]
|
||||
if original_entries[parsed_entry.name] == parsed_entry.id then
|
||||
if entry[FIELD_TYPE] == "link" and not compare_link_target(meta, parsed_entry) then
|
||||
if entry[FIELD_TYPE] == 'link' and not compare_link_target(meta, parsed_entry) then
|
||||
table.insert(diffs, {
|
||||
type = "new",
|
||||
type = 'new',
|
||||
name = parsed_entry.name,
|
||||
entry_type = "link",
|
||||
entry_type = 'link',
|
||||
link = parsed_entry.link_target,
|
||||
})
|
||||
elseif entry[FIELD_TYPE] ~= parsed_entry._type then
|
||||
table.insert(diffs, {
|
||||
type = "new",
|
||||
type = 'new',
|
||||
name = parsed_entry.name,
|
||||
entry_type = parsed_entry._type,
|
||||
})
|
||||
|
|
@ -255,7 +255,7 @@ M.parse = function(bufnr)
|
|||
end
|
||||
else
|
||||
table.insert(diffs, {
|
||||
type = "new",
|
||||
type = 'new',
|
||||
name = parsed_entry.name,
|
||||
entry_type = parsed_entry._type,
|
||||
id = parsed_entry.id,
|
||||
|
|
@ -267,7 +267,7 @@ M.parse = function(bufnr)
|
|||
local col_name = util.split_config(col_def)
|
||||
if columns.compare(adapter, col_name, entry, parsed_entry[col_name]) then
|
||||
table.insert(diffs, {
|
||||
type = "change",
|
||||
type = 'change',
|
||||
name = parsed_entry.name,
|
||||
entry_type = entry[FIELD_TYPE],
|
||||
column = col_name,
|
||||
|
|
@ -278,7 +278,7 @@ M.parse = function(bufnr)
|
|||
else
|
||||
-- Parse a new entry
|
||||
local name, isdir = parsedir(vim.trim(line))
|
||||
if vim.startswith(name, "/") then
|
||||
if vim.startswith(name, '/') then
|
||||
table.insert(errors, {
|
||||
message = "Paths cannot start with '/'",
|
||||
lnum = i - 1,
|
||||
|
|
@ -287,17 +287,17 @@ M.parse = function(bufnr)
|
|||
})
|
||||
return
|
||||
end
|
||||
if name ~= "" then
|
||||
local link_pieces = vim.split(name, " -> ", { plain = true })
|
||||
local entry_type = isdir and "directory" or "file"
|
||||
if name ~= '' then
|
||||
local link_pieces = vim.split(name, ' -> ', { plain = true })
|
||||
local entry_type = isdir and 'directory' or 'file'
|
||||
local link
|
||||
if #link_pieces == 2 then
|
||||
entry_type = "link"
|
||||
entry_type = 'link'
|
||||
name, link = unpack(link_pieces)
|
||||
end
|
||||
check_dupe(name, i)
|
||||
table.insert(diffs, {
|
||||
type = "new",
|
||||
type = 'new',
|
||||
name = name,
|
||||
entry_type = entry_type,
|
||||
link = link,
|
||||
|
|
@ -309,7 +309,7 @@ M.parse = function(bufnr)
|
|||
|
||||
for name, child_id in pairs(original_entries) do
|
||||
table.insert(diffs, {
|
||||
type = "delete",
|
||||
type = 'delete',
|
||||
name = name,
|
||||
id = child_id,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
local columns = require("oil.columns")
|
||||
local config = require("oil.config")
|
||||
local layout = require("oil.layout")
|
||||
local loading = require("oil.loading")
|
||||
local util = require("oil.util")
|
||||
local columns = require('oil.columns')
|
||||
local config = require('oil.config')
|
||||
local layout = require('oil.layout')
|
||||
local loading = require('oil.loading')
|
||||
local util = require('oil.util')
|
||||
local Progress = {}
|
||||
|
||||
local FPS = 20
|
||||
|
||||
function Progress.new()
|
||||
return setmetatable({
|
||||
lines = { "", "" },
|
||||
count = "",
|
||||
spinner = "",
|
||||
lines = { '', '' },
|
||||
count = '',
|
||||
spinner = '',
|
||||
bufnr = nil,
|
||||
winid = nil,
|
||||
min_bufnr = nil,
|
||||
|
|
@ -40,18 +40,18 @@ function Progress:show(opts)
|
|||
return
|
||||
end
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].bufhidden = 'wipe'
|
||||
self.bufnr = bufnr
|
||||
self.cancel = opts.cancel or self.cancel
|
||||
local loading_iter = loading.get_bar_iter()
|
||||
local spinner = loading.get_iter("dots")
|
||||
local spinner = loading.get_iter('dots')
|
||||
if not self.timer then
|
||||
self.timer = vim.loop.new_timer()
|
||||
self.timer:start(
|
||||
0,
|
||||
math.floor(1000 / FPS),
|
||||
vim.schedule_wrap(function()
|
||||
self.lines[2] = string.format("%s %s", self.count, loading_iter())
|
||||
self.lines[2] = string.format('%s %s', self.count, loading_iter())
|
||||
self.spinner = spinner()
|
||||
self:_render()
|
||||
end)
|
||||
|
|
@ -59,22 +59,22 @@ function Progress:show(opts)
|
|||
end
|
||||
local width, height = layout.calculate_dims(120, 10, config.progress)
|
||||
self.winid = vim.api.nvim_open_win(self.bufnr, true, {
|
||||
relative = "editor",
|
||||
relative = 'editor',
|
||||
width = width,
|
||||
height = height,
|
||||
row = math.floor((layout.get_editor_height() - height) / 2),
|
||||
col = math.floor((layout.get_editor_width() - width) / 2),
|
||||
zindex = 152, -- render on top of the floating window title
|
||||
style = "minimal",
|
||||
style = 'minimal',
|
||||
border = config.progress.border,
|
||||
})
|
||||
vim.bo[self.bufnr].filetype = "oil_progress"
|
||||
vim.bo[self.bufnr].filetype = 'oil_progress'
|
||||
for k, v in pairs(config.progress.win_options) do
|
||||
vim.api.nvim_set_option_value(k, v, { scope = "local", win = self.winid })
|
||||
vim.api.nvim_set_option_value(k, v, { scope = 'local', win = self.winid })
|
||||
end
|
||||
table.insert(
|
||||
self.autocmds,
|
||||
vim.api.nvim_create_autocmd("VimResized", {
|
||||
vim.api.nvim_create_autocmd('VimResized', {
|
||||
callback = function()
|
||||
self:_reposition()
|
||||
end,
|
||||
|
|
@ -82,7 +82,7 @@ function Progress:show(opts)
|
|||
)
|
||||
table.insert(
|
||||
self.autocmds,
|
||||
vim.api.nvim_create_autocmd("WinLeave", {
|
||||
vim.api.nvim_create_autocmd('WinLeave', {
|
||||
callback = function()
|
||||
self:minimize()
|
||||
end,
|
||||
|
|
@ -94,17 +94,17 @@ function Progress:show(opts)
|
|||
vim.api.nvim_win_close(self.winid, true)
|
||||
end
|
||||
end
|
||||
vim.keymap.set("n", "c", cancel, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set("n", "C", cancel, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set("n", "m", minimize, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set("n", "M", minimize, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set('n', 'c', cancel, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set('n', 'C', cancel, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set('n', 'm', minimize, { buffer = self.bufnr, nowait = true })
|
||||
vim.keymap.set('n', 'M', minimize, { buffer = self.bufnr, nowait = true })
|
||||
end
|
||||
|
||||
function Progress:restore()
|
||||
if self.closing then
|
||||
return
|
||||
elseif not self:is_minimized() then
|
||||
error("Cannot restore progress window: not minimized")
|
||||
error('Cannot restore progress window: not minimized')
|
||||
end
|
||||
self:_cleanup_minimized_win()
|
||||
self:show()
|
||||
|
|
@ -115,14 +115,14 @@ function Progress:_render()
|
|||
util.render_text(
|
||||
self.bufnr,
|
||||
self.lines,
|
||||
{ winid = self.winid, actions = { "[M]inimize", "[C]ancel" } }
|
||||
{ winid = self.winid, actions = { '[M]inimize', '[C]ancel' } }
|
||||
)
|
||||
end
|
||||
if self.min_bufnr and vim.api.nvim_buf_is_valid(self.min_bufnr) then
|
||||
util.render_text(
|
||||
self.min_bufnr,
|
||||
{ string.format("%sOil: %s", self.spinner, self.count) },
|
||||
{ winid = self.min_winid, h_align = "left" }
|
||||
{ string.format('%sOil: %s', self.spinner, self.count) },
|
||||
{ winid = self.min_winid, h_align = 'left' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -136,7 +136,7 @@ function Progress:_reposition()
|
|||
end
|
||||
local width, height = layout.calculate_dims(min_width, 10, config.progress)
|
||||
vim.api.nvim_win_set_config(self.winid, {
|
||||
relative = "editor",
|
||||
relative = 'editor',
|
||||
width = width,
|
||||
height = height,
|
||||
row = math.floor((layout.get_editor_height() - height) / 2),
|
||||
|
|
@ -174,22 +174,22 @@ function Progress:minimize()
|
|||
end
|
||||
self:_cleanup_main_win()
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].bufhidden = 'wipe'
|
||||
local winid = vim.api.nvim_open_win(bufnr, false, {
|
||||
relative = "editor",
|
||||
relative = 'editor',
|
||||
width = 16,
|
||||
height = 1,
|
||||
anchor = "SE",
|
||||
anchor = 'SE',
|
||||
row = layout.get_editor_height(),
|
||||
col = layout.get_editor_width(),
|
||||
zindex = 152, -- render on top of the floating window title
|
||||
style = "minimal",
|
||||
style = 'minimal',
|
||||
border = config.progress.minimized_border,
|
||||
})
|
||||
self.min_bufnr = bufnr
|
||||
self.min_winid = winid
|
||||
self:_render()
|
||||
vim.notify_once("Restore progress window with :Oil --progress")
|
||||
vim.notify_once('Restore progress window with :Oil --progress')
|
||||
end
|
||||
|
||||
---@param action oil.Action
|
||||
|
|
@ -198,14 +198,14 @@ end
|
|||
function Progress:set_action(action, idx, total)
|
||||
local adapter = util.get_adapter_for_action(action)
|
||||
local change_line
|
||||
if action.type == "change" then
|
||||
if action.type == 'change' then
|
||||
---@cast action oil.ChangeAction
|
||||
change_line = columns.render_change_action(adapter, action)
|
||||
else
|
||||
change_line = adapter.render_action(action)
|
||||
end
|
||||
self.lines[1] = change_line
|
||||
self.count = string.format("%d/%d", idx, total)
|
||||
self.count = string.format('%d/%d', idx, total)
|
||||
self:_reposition()
|
||||
self:_render()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local util = require("oil.util")
|
||||
local util = require('oil.util')
|
||||
|
||||
---@class (exact) oil.Trie
|
||||
---@field new fun(): oil.Trie
|
||||
|
|
@ -20,7 +20,7 @@ end
|
|||
function Trie:_url_to_path_pieces(url)
|
||||
local scheme, path = util.parse_url(url)
|
||||
assert(path)
|
||||
local pieces = vim.split(path, "/")
|
||||
local pieces = vim.split(path, '/')
|
||||
table.insert(pieces, 1, scheme)
|
||||
return pieces
|
||||
end
|
||||
|
|
@ -75,7 +75,7 @@ function Trie:remove(path_pieces, value)
|
|||
return
|
||||
end
|
||||
end
|
||||
error("Value not present in trie: " .. vim.inspect(value))
|
||||
error('Value not present in trie: ' .. vim.inspect(value))
|
||||
end
|
||||
|
||||
---Add the first action that affects a parent path of the url
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue