Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ https://github.com/user-attachments/assets/9873ec7e-4660-4301-9618-82054af3eb1f
- Create new Git worktrees with branch creation
- Delete worktrees with confirmation
- Switch between worktrees while preserving your place in files
- Lifecycle hooks for create, delete, and switch events
- Customizable commands and keymaps
- Works with any Git worktree structure

Expand Down Expand Up @@ -55,7 +56,12 @@ https://github.com/user-attachments/assets/9873ec7e-4660-4301-9618-82054af3eb1f
create = "<leader>wtc",
delete = "<leader>wtd",
switch = "<leader>wts",
}
},

-- Lifecycle hooks (optional)
on_create = function(path) end,
on_delete = function(path) end,
on_switch = function(from_path, to_path) end,
}
}
```
Expand All @@ -72,6 +78,9 @@ https://github.com/user-attachments/assets/9873ec7e-4660-4301-9618-82054af3eb1f
| `mappings.create` | Key mapping for creating worktrees | `nil` (not set) |
| `mappings.delete` | Key mapping for deleting worktrees | `nil` (not set) |
| `mappings.switch` | Key mapping for switching worktrees | `nil` (not set) |
| `on_create` | Callback `function(path)` called after a worktree is created | `nil` |
| `on_delete` | Callback `function(path)` called after a worktree is deleted | `nil` |
| `on_switch` | Callback `function(from_path, to_path)` called after switching worktrees | `nil` |

### Common Worktree Configurations

Expand Down
47 changes: 47 additions & 0 deletions doc/worktrees.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Features:
- Interactive creation, deletion, and switching of git worktrees
- Configurable base path and path templates for new worktrees
- Automatic file correspondence when switching between worktrees
- Lifecycle hooks for create, delete, and switch events
- Customizable commands and key mappings

==============================================================================
Expand Down Expand Up @@ -79,6 +80,11 @@ Default configuration: >lua
-- Use {branch} as placeholder for branch name
path_template = "{branch}",

-- Lifecycle hooks (optional)
on_create = nil, -- function(path)
on_delete = nil, -- function(path)
on_switch = nil, -- function(from_path, to_path)

-- Command names for interactive functions
commands = {
create = "WorktreeCreate",
Expand Down Expand Up @@ -118,6 +124,33 @@ path_template ~
- "wt-{branch}" - Prefixes worktree directories with "wt-"
- "{branch}-worktree" - Suffixes worktree directories with "-worktree"

*worktrees-config-on_create*
on_create ~
Type: function|nil
Default: nil
Signature: function(path)

Called after a worktree is successfully created. Receives the absolute path
of the new worktree.

*worktrees-config-on_delete*
on_delete ~
Type: function|nil
Default: nil
Signature: function(path)

Called after a worktree is successfully deleted. Receives the absolute path
of the deleted worktree.

*worktrees-config-on_switch*
on_switch ~
Type: function|nil
Default: nil
Signature: function(from_path, to_path)

Called after a successful worktree switch. Receives the absolute paths of
the worktree switched from and the worktree switched to.

*worktrees-config-commands*
commands ~
Type: table
Expand Down Expand Up @@ -261,5 +294,19 @@ Custom configuration: >lua
},
})
<
Using lifecycle hooks: >lua
require("worktrees").setup({
on_create = function(path)
print("Created worktree at: " .. path)
end,
on_delete = function(path)
print("Deleted worktree at: " .. path)
end,
on_switch = function(from_path, to_path)
print("Switched from " .. from_path .. " to " .. to_path)
end,
})
<

==============================================================================
vim:tw=78:ts=8:ft=help:norl:
66 changes: 50 additions & 16 deletions lua/worktrees/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ Worktrees.config = {
-- Use {branch} as placeholder for branch name
path_template = "{branch}",

-- Lifecycle hooks (optional)
-- on_create: called with (path) after a worktree is successfully created
on_create = nil,
-- on_delete: called with (path) after a worktree is successfully deleted
on_delete = nil,
-- on_switch: called with (from_path, to_path) after a successful worktree switch
on_switch = nil,

-- Command names for interactive functions
commands = {
create = "WorktreeCreate",
Expand Down Expand Up @@ -71,6 +79,8 @@ Worktrees.utils = {}
Worktrees.utils.switch_worktree = function(path, change_root)
if change_root == nil then change_root = true end

local worktree_root = git.get_worktree_root()
local from_path = worktree_root and vim.fs.normalize(worktree_root) or nil
local worktrees = git.get_worktrees()
if not worktrees or vim.tbl_count(worktrees) == 0 then
H.notify("No git worktrees found in this repo", vim.log.levels.ERROR)
Expand Down Expand Up @@ -129,6 +139,12 @@ Worktrees.utils.switch_worktree = function(path, change_root)
end
vim.cmd.clearjumps()

if Worktrees.config.on_switch then
vim.schedule(function()
Worktrees.config.on_switch(from_path, normalized_path)
end)
end

return true
end

Expand Down Expand Up @@ -193,22 +209,28 @@ Worktrees.utils.create_worktree = function(path, branch, switch)
vim.log.levels.ERROR
)
return nil
else
H.notify(
"Created worktree: " .. branch .. " at " .. worktree_path,
vim.log.levels.INFO
)
end

-- Check if this is the first worktree, if so switch to it
local worktrees = git.get_worktrees()
if (worktrees and vim.tbl_count(worktrees) == 1) or switch == true then
vim.schedule(function()
Worktrees.utils.switch_worktree(worktree_path,true)
end)
end
H.notify(
"Created worktree: " .. branch .. " at " .. worktree_path,
vim.log.levels.INFO
)

if Worktrees.config.on_create then
vim.schedule(function()
Worktrees.config.on_create(worktree_path)
end)
end

return worktree_path
-- Check if this is the first worktree, if so switch to it
local worktrees = git.get_worktrees()
if (worktrees and vim.tbl_count(worktrees) == 1) or switch == true then
vim.schedule(function()
Worktrees.utils.switch_worktree(worktree_path,true)
end)
end

return worktree_path
end

--- Delete a worktree by path
Expand All @@ -234,10 +256,17 @@ Worktrees.utils.delete_worktree = function(path)
vim.log.levels.ERROR
)
return false
else
H.notify("Deleted worktree at: " .. path, vim.log.levels.INFO)
return true
end

H.notify("Deleted worktree at: " .. path, vim.log.levels.INFO)

if Worktrees.config.on_delete then
vim.schedule(function()
Worktrees.config.on_delete(path)
end)
end

return true
end

-- Interactive UI functions ===================================================
Expand Down Expand Up @@ -390,6 +419,11 @@ H.setup_config = function(config)
H.check_type("mappings.delete", config.mappings.delete, "string", true)
H.check_type("mappings.switch", config.mappings.switch, "string", true)

-- Validate callbacks (callable or nil)
H.check_type("on_create", config.on_create, "callable", true)
H.check_type("on_delete", config.on_delete, "callable", true)
H.check_type("on_switch", config.on_switch, "callable", true)

return config
end

Expand Down