From 6b05c2e91378960be7f7e73867112cee0b4a408a Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Sat, 6 May 2023 22:48:37 -0700 Subject: [PATCH] feat: prompt user to save changes before editing moved file/dir (#93) --- README.md | 2 ++ doc/oil.txt | 2 ++ lua/oil/config.lua | 2 ++ lua/oil/init.lua | 32 ++++++++++++++++++++++++++++++-- lua/oil/mutator/init.lua | 2 +- tests/minimal_init.lua | 8 +------- tests/test_util.lua | 1 + 7 files changed, 39 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9a7fd2a..8dc858d 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,8 @@ require("oil").setup({ skip_confirm_for_simple_edits = false, -- Deleted files will be removed with the `trash-put` command. 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 -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) -- Additionally, if it is a string that matches "actions.", diff --git a/doc/oil.txt b/doc/oil.txt index 3b828f0..44ec411 100644 --- a/doc/oil.txt +++ b/doc/oil.txt @@ -45,6 +45,8 @@ OPTIONS *oil-option skip_confirm_for_simple_edits = false, -- Deleted files will be removed with the `trash-put` command. 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 -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) -- Additionally, if it is a string that matches "actions.", diff --git a/lua/oil/config.lua b/lua/oil/config.lua index b54d3bc..8e3a1f2 100644 --- a/lua/oil/config.lua +++ b/lua/oil/config.lua @@ -30,6 +30,8 @@ local default_config = { skip_confirm_for_simple_edits = false, -- Deleted files will be removed with the `trash-put` command. 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 -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) -- Additionally, if it is a string that matches "actions.", diff --git a/lua/oil/init.lua b/lua/oil/init.lua index dd7fddc..558d657 100644 --- a/lua/oil/init.lua +++ b/lua/oil/init.lua @@ -6,6 +6,7 @@ local M = {} ---@field name string ---@field type oil.EntryType ---@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.TextChunk string|string[] @@ -47,11 +48,14 @@ M.get_entry_on_line = function(bufnr, lnum) local result = parser.parse_line(adapter, line, column_defs) if result 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 return { name = result.data.name, type = result.data._type, + parsed_name = result.data.name, } end end @@ -70,6 +74,7 @@ M.get_entry_on_line = function(bufnr, lnum) return { name = name, type = entry_type, + parsed_name = name, } end end @@ -399,6 +404,7 @@ end --- tab boolean Open the buffer in a new tab M.select = function(opts) local cache = require("oil.cache") + local config = require("oil.config") opts = vim.tbl_extend("keep", opts or {}, {}) if opts.horizontal or opts.vertical or opts.preview then opts.split = opts.split or "belowright" @@ -451,12 +457,34 @@ M.select = function(opts) vim.notify("Cannot preview multiple entries", vim.log.levels.WARN) entries = { entries[1] } 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 local preview_win = util.get_preview_win() if not opts.preview and preview_win then vim.api.nvim_win_close(preview_win, true) end - local bufname = vim.api.nvim_buf_get_name(0) local prev_win = vim.api.nvim_get_current_win() for _, entry in ipairs(entries) do local scheme, dir = util.parse_url(bufname) diff --git a/lua/oil/mutator/init.lua b/lua/oil/mutator/init.lua index 1142699..466a430 100644 --- a/lua/oil/mutator/init.lua +++ b/lua/oil/mutator/init.lua @@ -528,7 +528,7 @@ M.try_write_changes = function(confirm) -- 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.name, "/")[1] + vim.split(current_entry.parsed_name or current_entry.name, "/")[1] ) end view.rerender_all_oil_buffers({ preserve_undo = M.trash }) diff --git a/tests/minimal_init.lua b/tests/minimal_init.lua index 3c7c0ec..262d9ec 100644 --- a/tests/minimal_init.lua +++ b/tests/minimal_init.lua @@ -2,10 +2,4 @@ vim.cmd([[set runtimepath+=.]]) vim.o.swapfile = false vim.bo.swapfile = false -require("oil").setup({ - columms = {}, - adapters = { - ["oil-test://"] = "test", - }, - silence_disclaimer = true, -}) +require("tests.test_util").reset_editor() diff --git a/tests/test_util.lua b/tests/test_util.lua index 44110eb..2a83743 100644 --- a/tests/test_util.lua +++ b/tests/test_util.lua @@ -9,6 +9,7 @@ M.reset_editor = function() ["oil-test://"] = "test", }, silence_disclaimer = true, + prompt_save_on_select_new_entry = false, }) vim.cmd.tabonly({ mods = { silent = true } }) for i, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do