From 2c4172f567281ea30abb26c0813df050b099e29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Yag=C3=BCe=20L=C3=B3pez?= Date: Fri, 11 Jul 2025 16:59:00 -0600 Subject: [PATCH 1/4] Fixed typo and removed commented-out line --- lua/git-worktree/init.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lua/git-worktree/init.lua b/lua/git-worktree/init.lua index 0fb5295..7bcac4d 100644 --- a/lua/git-worktree/init.lua +++ b/lua/git-worktree/init.lua @@ -150,14 +150,13 @@ local function change_dirs(path) local previous_worktree = current_worktree_path - -- vim.loop.chdir(worktree_path) if Path:new(worktree_path):exists() then local cmd = string.format("%s %s", M._config.change_directory_command, worktree_path) status:log().debug("Changing to directory " .. worktree_path) vim.cmd(cmd) current_worktree_path = worktree_path else - status:error('Could not chang to directory: ' ..worktree_path) + status:error('Could not change to directory: ' ..worktree_path) end if M._config.clearjumps_on_change then From 2bb47a1017290c1029ad236143679bb6888f0aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Yag=C3=BCe=20L=C3=B3pez?= Date: Fri, 11 Jul 2025 17:04:47 -0600 Subject: [PATCH 2/4] Change vim.loop.cwd for vim.uv.cwd --- lua/git-worktree/init.lua | 6 ++-- lua/git-worktree/test.lua | 2 +- tests/worktree_spec.lua | 70 +++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/lua/git-worktree/init.lua b/lua/git-worktree/init.lua index 7bcac4d..4caa104 100644 --- a/lua/git-worktree/init.lua +++ b/lua/git-worktree/init.lua @@ -11,7 +11,7 @@ local current_worktree_path = nil local on_change_callbacks = {} M.setup_git_info = function() - local cwd = vim.loop.cwd() + local cwd = vim.uv.cwd() local is_in_worktree = false @@ -458,7 +458,7 @@ M.delete_worktree = function(path, force, opts) opts.on_failure(e) end - failure(cmd, vim.loop.cwd())(e) + failure(cmd, vim.uv.cwd())(e) end) delete:start() end) @@ -477,7 +477,7 @@ M.update_current_buffer = function(prev_path) return false end - local cwd = vim.loop.cwd() + local cwd = vim.uv.cwd() local current_buf_name = vim.api.nvim_buf_get_name(0) if not current_buf_name or current_buf_name == "" then return false diff --git a/lua/git-worktree/test.lua b/lua/git-worktree/test.lua index 3906c9a..6aeaea6 100644 --- a/lua/git-worktree/test.lua +++ b/lua/git-worktree/test.lua @@ -1,6 +1,6 @@ local Path = require("plenary.path") -local path = Path:new(vim.loop.cwd(), "foo", "..", "..") +local path = Path:new(vim.uv.cwd(), "foo", "..", "..") print(path:absolute()) diff --git a/tests/worktree_spec.lua b/tests/worktree_spec.lua index 4f5e523..c612daf 100644 --- a/tests/worktree_spec.lua +++ b/tests/worktree_spec.lua @@ -66,7 +66,7 @@ describe('git-worktree', function() local expected_path = git_worktree:get_root() .. Path.path.sep .. path -- Check to make sure directory was switched - assert.are.same(expected_path, vim.loop.cwd()) + assert.are.same(expected_path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(expected_path)) @@ -95,7 +95,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path) + assert.are.same(vim.uv.cwd(), path) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(path)) @@ -126,7 +126,7 @@ describe('git-worktree', function() -- Check to make sure directory was switched local expected_path = Path:new(git_worktree:get_root() .. '/' .. path):normalize() - assert.are.same(expected_path, vim.loop.cwd()) + assert.are.same(expected_path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(expected_path)) @@ -157,7 +157,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(path, vim.loop.cwd()) + assert.are.same(path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(path)) @@ -188,7 +188,7 @@ describe('git-worktree', function() local expected_path = git_worktree:get_root() .. '/' .. path -- Check to make sure directory was switched - assert.are.same(expected_path, vim.loop.cwd()) + assert.are.same(expected_path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(expected_path)) @@ -218,7 +218,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(path, vim.loop.cwd()) + assert.are.same(path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(path)) @@ -249,7 +249,7 @@ describe('git-worktree', function() -- Check to make sure directory was switched local expected_path = Path:new(git_worktree:get_root() .. '/' .. path):normalize() - assert.are.same(expected_path, vim.loop.cwd()) + assert.are.same(expected_path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(expected_path)) @@ -280,7 +280,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(path, vim.loop.cwd()) + assert.are.same(path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(path)) @@ -311,7 +311,7 @@ describe('git-worktree', function() -- Check to make sure directory was switched local expected_path = Path:new(git_worktree:get_root() .. '/' .. path):normalize() - assert.are.same(expected_path, vim.loop.cwd()) + assert.are.same(expected_path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(expected_path)) @@ -342,7 +342,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(path, vim.loop.cwd()) + assert.are.same(path, vim.uv.cwd()) -- Check to make sure it is added to git worktree list assert.True(check_git_worktree_exists(path)) @@ -374,7 +374,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root() .. Path.path.sep .. path) + assert.are.same(vim.uv.cwd(), git_worktree:get_root() .. Path.path.sep .. path) end)) @@ -393,7 +393,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path) + assert.are.same(vim.uv.cwd(), path) end)) @@ -415,7 +415,7 @@ describe('git-worktree', function() local expected_path = Path:new(git_worktree:get_root() .. '/'..path):normalize() -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), expected_path) + assert.are.same(vim.uv.cwd(), expected_path) end)) @@ -435,7 +435,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path) + assert.are.same(vim.uv.cwd(), path) end)) @@ -634,12 +634,12 @@ describe('git-worktree', function() reset_variables() -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root() .. Path.path.sep .. path1) + assert.are.same(vim.uv.cwd(), git_worktree:get_root() .. Path.path.sep .. path1) -- open A file vim.cmd("e A.txt") -- make sure it is opensd - assert.True(vim.loop.cwd().."/A.txt" == get_current_file()) + assert.True(vim.uv.cwd().."/A.txt" == get_current_file()) git_worktree.switch_worktree(path2) @@ -653,9 +653,9 @@ describe('git-worktree', function() reset_variables() -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root() .. Path.path.sep .. path2) + assert.are.same(vim.uv.cwd(), git_worktree:get_root() .. Path.path.sep .. path2) -- Make sure file is switched - assert.True(vim.loop.cwd().."/A.txt" == get_current_file()) + assert.True(vim.uv.cwd().."/A.txt" == get_current_file()) git_worktree.switch_worktree(path1) @@ -668,9 +668,9 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root() .. Path.path.sep .. path1) + assert.are.same(vim.uv.cwd(), git_worktree:get_root() .. Path.path.sep .. path1) -- Make sure file is switched - assert.True(vim.loop.cwd().."/A.txt" == get_current_file()) + assert.True(vim.uv.cwd().."/A.txt" == get_current_file()) end)) @@ -692,7 +692,7 @@ describe('git-worktree', function() reset_variables() -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path1) + assert.are.same(vim.uv.cwd(), path1) -- open B file vim.cmd("e A.txt") @@ -711,7 +711,7 @@ describe('git-worktree', function() reset_variables() -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path2) + assert.are.same(vim.uv.cwd(), path2) -- Make sure file is switched assert.True(path2.."/A.txt" == get_current_file()) @@ -726,7 +726,7 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path1) + assert.are.same(vim.uv.cwd(), path1) -- Make sure file is switched assert.True(path1.."/A.txt" == get_current_file()) @@ -754,7 +754,7 @@ describe('git-worktree', function() assert.False(check_git_worktree_exists(git_worktree:get_root() .. Path.path.sep .. path)) -- Check to make sure directory was not switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root()) + assert.are.same(vim.uv.cwd(), git_worktree:get_root()) end)) @@ -776,7 +776,7 @@ describe('git-worktree', function() assert.False(check_git_worktree_exists(path)) -- Check to make sure directory was not switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root()) + assert.are.same(vim.uv.cwd(), git_worktree:get_root()) end)) @@ -800,7 +800,7 @@ describe('git-worktree', function() assert.False(check_git_worktree_exists(absolute_path)) -- Check to make sure directory was not switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root()) + assert.are.same(vim.uv.cwd(), git_worktree:get_root()) end)) @@ -823,7 +823,7 @@ describe('git-worktree', function() assert.False(check_git_worktree_exists(path)) -- Check to make sure directory was not switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root()) + assert.are.same(vim.uv.cwd(), git_worktree:get_root()) end)) @@ -844,8 +844,8 @@ describe('git-worktree', function() in_repo_from_origin_1_worktree(function() git_worktree:setup_git_info() - assert.are.same(vim.loop.cwd(), git_worktree:get_root()) - assert.are.same(vim.loop.cwd(), git_worktree:get_current_worktree_path()) + assert.are.same(vim.uv.cwd(), git_worktree:get_root()) + assert.are.same(vim.uv.cwd(), git_worktree:get_current_worktree_path()) end)) @@ -853,8 +853,8 @@ describe('git-worktree', function() in_bare_repo_from_origin_1_worktree(function() git_worktree:setup_git_info() - assert.are.same(vim.loop.cwd(), git_worktree:get_root()) - assert.are.same(vim.loop.cwd(), git_worktree:get_current_worktree_path()) + assert.are.same(vim.uv.cwd(), git_worktree:get_root()) + assert.are.same(vim.uv.cwd(), git_worktree:get_current_worktree_path()) end)) @@ -876,11 +876,11 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), path) + assert.are.same(vim.uv.cwd(), path) git_worktree:setup_git_info() assert.are.same(expected_git_repo, git_worktree:get_root()) - assert.are.same(vim.loop.cwd(), git_worktree:get_current_worktree_path()) + assert.are.same(vim.uv.cwd(), git_worktree:get_current_worktree_path()) end)) @@ -901,11 +901,11 @@ describe('git-worktree', function() ) -- Check to make sure directory was switched - assert.are.same(vim.loop.cwd(), git_worktree:get_root() .. Path.path.sep .. path) + assert.are.same(vim.uv.cwd(), git_worktree:get_root() .. Path.path.sep .. path) git_worktree:setup_git_info() assert.are.same(expected_git_repo, git_worktree:get_root()) - assert.are.same(vim.loop.cwd(), git_worktree:get_current_worktree_path()) + assert.are.same(vim.uv.cwd(), git_worktree:get_current_worktree_path()) end)) end) From a8bf9ec625a820d957d7102b1946f1320bbc5094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Yag=C3=BCe=20L=C3=B3pez?= Date: Fri, 11 Jul 2025 17:05:05 -0600 Subject: [PATCH 3/4] Added descriptions for the switch_worktree maps --- lua/telescope/_extensions/git_worktree.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lua/telescope/_extensions/git_worktree.lua b/lua/telescope/_extensions/git_worktree.lua index 706cd2b..2f62bfd 100644 --- a/lua/telescope/_extensions/git_worktree.lua +++ b/lua/telescope/_extensions/git_worktree.lua @@ -215,10 +215,8 @@ local telescope_git_worktree = function(opts) attach_mappings = function(_, map) action_set.select:replace(switch_worktree) - map("i", "", delete_worktree) - map("n", "", delete_worktree) - map("i", "", toggle_forced_deletion) - map("n", "", toggle_forced_deletion) + map({"i", "n"}, "", delete_worktree, { desc = "Delete worktree" }) + map({"i", "n"}, "", toggle_forced_deletion, { desc = "Force delete worktree" }) return true end From f503fb9be00342ff8107152781048fb9428d40ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Yag=C3=BCe=20L=C3=B3pez?= Date: Fri, 11 Jul 2025 22:54:42 -0600 Subject: [PATCH 4/4] Now worktree switch tries to update all buffers open in windows That is, for each open window, there will be an attempt to update the buffer, if no buffer is found, then the update_on_change_command is used instead. This will respect the window layout as much as possible when changing workspace. --- lua/git-worktree/init.lua | 54 +++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/lua/git-worktree/init.lua b/lua/git-worktree/init.lua index 4caa104..c2ec363 100644 --- a/lua/git-worktree/init.lua +++ b/lua/git-worktree/init.lua @@ -125,11 +125,43 @@ M.setup_git_info = function() end local function on_tree_change_handler(op, metadata) + -- Do nothing if not really changing + if metadata["path"] == metadata["prev_path"] then + return nil + end + if M._config.update_on_change then if op == Enum.Operations.Switch then - local changed = M.update_current_buffer(metadata["prev_path"]) - if not changed then - status:log().debug("Could not change to the file in the new worktree, running the `update_on_change_command`") + -- Try to change the buffer in each window, if a buffer cannot be + -- changed then close that window. If no buffer is left open, + -- then run update_on_change_command + local keep_open = {} + local is_keep_open_empty = true + + -- Try to load buffers in each window + for _, win in ipairs(vim.api.nvim_list_wins()) do + local buffer_name = vim.api.nvim_win_call(win, function() + return M.update_current_buffer(metadata["prev_path"]) + end) + + if buffer_name then + keep_open[buffer_name] = true + is_keep_open_empty = false + end + end + + -- Close all buffers that are not in keep_open + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + local name = vim.api.nvim_buf_get_name(buf) + if not keep_open[name] then + vim.api.nvim_buf_delete(buf, {}) + end + end + + if is_keep_open_empty then + status + :log() + .debug("Could not change to the file in the new worktree, running the `update_on_change_command`") vim.cmd(M._config.update_on_change_command) end end @@ -474,24 +506,24 @@ end M.update_current_buffer = function(prev_path) if prev_path == nil then - return false + return nil end local cwd = vim.uv.cwd() local current_buf_name = vim.api.nvim_buf_get_name(0) if not current_buf_name or current_buf_name == "" then - return false + return nil end local name = Path:new(current_buf_name):absolute() local start, fin = string.find(name, cwd..Path.path.sep, 1, true) if start ~= nil then - return true + return name end start, fin = string.find(name, prev_path, 1, true) if start == nil then - return false + return nil end local local_name = name:sub(fin + 2) @@ -499,12 +531,12 @@ M.update_current_buffer = function(prev_path) local final_path = Path:new({cwd, local_name}):absolute() if not Path:new(final_path):exists() then - return false + return nil end - local bufnr = vim.fn.bufnr(final_path, true) - vim.api.nvim_set_current_buf(bufnr) - return true + -- Open file with edit so the buffer is loaded also + vim.cmd("edit " .. final_path) + return vim.api.nvim_buf_get_name(0) end M.on_tree_change = function(cb)