feat: prompt user to save changes before editing moved file/dir (#93)

This commit is contained in:
Steven Arcangeli 2023-05-06 22:48:37 -07:00
parent 3cbebc2b0c
commit 6b05c2e913
7 changed files with 39 additions and 10 deletions

View file

@ -154,6 +154,8 @@ require("oil").setup({
skip_confirm_for_simple_edits = false, skip_confirm_for_simple_edits = false,
-- Deleted files will be removed with the `trash-put` command. -- Deleted files will be removed with the `trash-put` command.
delete_to_trash = false, delete_to_trash = false,
-- Selecting a new/moved/renamed file or directory will prompt you to save changes first
prompt_save_on_select_new_entry = true,
-- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap
-- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true })
-- Additionally, if it is a string that matches "actions.<name>", -- Additionally, if it is a string that matches "actions.<name>",

View file

@ -45,6 +45,8 @@ OPTIONS *oil-option
skip_confirm_for_simple_edits = false, skip_confirm_for_simple_edits = false,
-- Deleted files will be removed with the `trash-put` command. -- Deleted files will be removed with the `trash-put` command.
delete_to_trash = false, delete_to_trash = false,
-- Selecting a new/moved/renamed file or directory will prompt you to save changes first
prompt_save_on_select_new_entry = true,
-- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap
-- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true })
-- Additionally, if it is a string that matches "actions.<name>", -- Additionally, if it is a string that matches "actions.<name>",

View file

@ -30,6 +30,8 @@ local default_config = {
skip_confirm_for_simple_edits = false, skip_confirm_for_simple_edits = false,
-- Deleted files will be removed with the `trash-put` command. -- Deleted files will be removed with the `trash-put` command.
delete_to_trash = false, delete_to_trash = false,
-- Selecting a new/moved/renamed file or directory will prompt you to save changes first
prompt_save_on_select_new_entry = true,
-- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap
-- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true })
-- Additionally, if it is a string that matches "actions.<name>", -- Additionally, if it is a string that matches "actions.<name>",

View file

@ -6,6 +6,7 @@ local M = {}
---@field name string ---@field name string
---@field type oil.EntryType ---@field type oil.EntryType
---@field id nil|integer Will be nil if it hasn't been persisted to disk yet ---@field id nil|integer Will be nil if it hasn't been persisted to disk yet
---@field parsed_name nil|string
---@alias oil.EntryType "file"|"directory"|"socket"|"link" ---@alias oil.EntryType "file"|"directory"|"socket"|"link"
---@alias oil.TextChunk string|string[] ---@alias oil.TextChunk string|string[]
@ -47,11 +48,14 @@ M.get_entry_on_line = function(bufnr, lnum)
local result = parser.parse_line(adapter, line, column_defs) local result = parser.parse_line(adapter, line, column_defs)
if result then if result then
if result.entry then if result.entry then
return util.export_entry(result.entry) local entry = util.export_entry(result.entry)
entry.parsed_name = result.data.name
return entry
else else
return { return {
name = result.data.name, name = result.data.name,
type = result.data._type, type = result.data._type,
parsed_name = result.data.name,
} }
end end
end end
@ -70,6 +74,7 @@ M.get_entry_on_line = function(bufnr, lnum)
return { return {
name = name, name = name,
type = entry_type, type = entry_type,
parsed_name = name,
} }
end end
end end
@ -399,6 +404,7 @@ end
--- tab boolean Open the buffer in a new tab --- tab boolean Open the buffer in a new tab
M.select = function(opts) M.select = function(opts)
local cache = require("oil.cache") local cache = require("oil.cache")
local config = require("oil.config")
opts = vim.tbl_extend("keep", opts or {}, {}) opts = vim.tbl_extend("keep", opts or {}, {})
if opts.horizontal or opts.vertical or opts.preview then if opts.horizontal or opts.vertical or opts.preview then
opts.split = opts.split or "belowright" opts.split = opts.split or "belowright"
@ -451,12 +457,34 @@ M.select = function(opts)
vim.notify("Cannot preview multiple entries", vim.log.levels.WARN) vim.notify("Cannot preview multiple entries", vim.log.levels.WARN)
entries = { entries[1] } entries = { entries[1] }
end end
-- Check if any of these entries are moved from their original location
local bufname = vim.api.nvim_buf_get_name(0)
local any_moved = false
for _, entry in ipairs(entries) do
local is_new_entry = entry.id == nil
local is_moved_from_dir = entry.id and cache.get_parent_url(entry.id) ~= bufname
local is_renamed = entry.parsed_name ~= entry.name
if is_new_entry or is_moved_from_dir or is_renamed then
any_moved = true
break
end
end
if any_moved and not opts.preview and config.prompt_save_on_select_new_entry then
local ok, choice = pcall(vim.fn.confirm, "Save changes?", "Yes\nNo", 1)
if not ok then
return
elseif choice == 1 then
M.save()
return
end
end
-- Close the preview window if we're not previewing the selection -- Close the preview window if we're not previewing the selection
local preview_win = util.get_preview_win() local preview_win = util.get_preview_win()
if not opts.preview and preview_win then if not opts.preview and preview_win then
vim.api.nvim_win_close(preview_win, true) vim.api.nvim_win_close(preview_win, true)
end end
local bufname = vim.api.nvim_buf_get_name(0)
local prev_win = vim.api.nvim_get_current_win() local prev_win = vim.api.nvim_get_current_win()
for _, entry in ipairs(entries) do for _, entry in ipairs(entries) do
local scheme, dir = util.parse_url(bufname) local scheme, dir = util.parse_url(bufname)

View file

@ -528,7 +528,7 @@ M.try_write_changes = function(confirm)
-- get the entry under the cursor and make sure the cursor stays on it -- get the entry under the cursor and make sure the cursor stays on it
view.set_last_cursor( view.set_last_cursor(
vim.api.nvim_buf_get_name(0), vim.api.nvim_buf_get_name(0),
vim.split(current_entry.name, "/")[1] vim.split(current_entry.parsed_name or current_entry.name, "/")[1]
) )
end end
view.rerender_all_oil_buffers({ preserve_undo = M.trash }) view.rerender_all_oil_buffers({ preserve_undo = M.trash })

View file

@ -2,10 +2,4 @@ vim.cmd([[set runtimepath+=.]])
vim.o.swapfile = false vim.o.swapfile = false
vim.bo.swapfile = false vim.bo.swapfile = false
require("oil").setup({ require("tests.test_util").reset_editor()
columms = {},
adapters = {
["oil-test://"] = "test",
},
silence_disclaimer = true,
})

View file

@ -9,6 +9,7 @@ M.reset_editor = function()
["oil-test://"] = "test", ["oil-test://"] = "test",
}, },
silence_disclaimer = true, silence_disclaimer = true,
prompt_save_on_select_new_entry = false,
}) })
vim.cmd.tabonly({ mods = { silent = true } }) vim.cmd.tabonly({ mods = { silent = true } })
for i, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do for i, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do