@@ -861,6 +861,90 @@ end
return M
]]
+_EMBEDDED_MODULES["wt.cmd.list"] = [[-- SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
+--
+-- SPDX-License-Identifier: GPL-3.0-or-later
+
+local exit = require("wt.exit")
+local shell = require("wt.shell")
+local git = require("wt.git")
+local path_mod = require("wt.path")
+
+---@class wt.cmd.list
+local M = {}
+
+---List all worktrees with status
+function M.cmd_list()
+ local root, err = git.find_project_root()
+ if not root then
+ shell.die(err --[[@as string]])
+ return
+ end
+
+ local git_dir = root .. "/.bare"
+ local output, code = shell.run_cmd("GIT_DIR=" .. git_dir .. " git worktree list --porcelain")
+ if code ~= 0 then
+ shell.die("failed to list worktrees: " .. output, exit.EXIT_SYSTEM_ERROR)
+ end
+
+ ---@type {path: string, head: string, branch: string}[]
+ local worktrees = {}
+ local current = {}
+
+ for line in output:gmatch("[^\n]+") do
+ local key, value = line:match("^(%S+)%s*(.*)$")
+ if key == "worktree" and value then
+ if current.path then
+ table.insert(worktrees, current)
+ end
+ if value:match("/%.bare$") then
+ current = {}
+ else
+ current = { path = value, head = "", branch = "(detached)" }
+ end
+ elseif key == "HEAD" and value then
+ current.head = value:sub(1, 7)
+ elseif key == "branch" and value then
+ current.branch = value:gsub("^refs/heads/", "")
+ elseif key == "bare" then
+ current = {}
+ end
+ end
+ if current.path then
+ table.insert(worktrees, current)
+ end
+
+ if #worktrees == 0 then
+ print("No worktrees found")
+ return
+ end
+
+ local cwd = shell.get_cwd() or ""
+
+ local rows = {}
+ for _, wt in ipairs(worktrees) do
+ local rel_path = path_mod.relative_path(cwd, wt.path)
+
+ local status_out = shell.run_cmd("git -C " .. wt.path .. " status --porcelain")
+ local status = status_out == "" and "clean" or "dirty"
+
+ table.insert(rows, rel_path .. "," .. wt.branch .. "," .. wt.head .. "," .. status)
+ end
+
+ local table_input = "Path,Branch,HEAD,Status\n" .. table.concat(rows, "\n")
+ table_input = table_input:gsub("EOF", "eof")
+ local table_cmd = "gum table --print <<'EOF'\n" .. table_input .. "\nEOF"
+ local table_handle = io.popen(table_cmd, "r")
+ if not table_handle then
+ return
+ end
+ io.write(table_handle:read("*a") or "")
+ table_handle:close()
+end
+
+return M
+]]
+
_EMBEDDED_MODULES["wt.cmd.fetch"] = [[-- SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
--
-- SPDX-License-Identifier: GPL-3.0-or-later
@@ -945,6 +1029,9 @@ local show_command_help = help_mod.show_command_help
local fetch_mod = require("wt.cmd.fetch")
local cmd_fetch = fetch_mod.cmd_fetch
+local list_mod = require("wt.cmd.list")
+local cmd_list = list_mod.cmd_list
+
---@param args string[]
local function cmd_clone(args)
-- Parse arguments: <url> [--remote name]... [--own]
@@ -1598,81 +1685,6 @@ local function cmd_remove(args)
end
end
-local function cmd_list()
- local root, err = find_project_root()
- if not root then
- die(err --[[@as string]])
- return
- end
-
- local git_dir = root .. "/.bare"
- local output, code = run_cmd("GIT_DIR=" .. git_dir .. " git worktree list --porcelain")
- if code ~= 0 then
- die("failed to list worktrees: " .. output, EXIT_SYSTEM_ERROR)
- end
-
- -- Parse porcelain output into worktree entries
- ---@type {path: string, head: string, branch: string}[]
- local worktrees = {}
- local current = {}
-
- for line in output:gmatch("[^\n]+") do
- local key, value = line:match("^(%S+)%s*(.*)$")
- if key == "worktree" and value then
- if current.path then
- table.insert(worktrees, current)
- end
- -- Skip .bare directory
- if value:match("/%.bare$") then
- current = {}
- else
- current = { path = value, head = "", branch = "(detached)" }
- end
- elseif key == "HEAD" and value then
- current.head = value:sub(1, 7)
- elseif key == "branch" and value then
- current.branch = value:gsub("^refs/heads/", "")
- elseif key == "bare" then
- -- Skip bare repo entry
- current = {}
- end
- end
- if current.path then
- table.insert(worktrees, current)
- end
-
- if #worktrees == 0 then
- print("No worktrees found")
- return
- end
-
- -- Get current working directory
- local cwd = get_cwd() or ""
-
- -- Build table rows with status
- local rows = {}
- for _, wt in ipairs(worktrees) do
- local rel_path = relative_path(cwd, wt.path)
-
- -- Check dirty status
- local status_out = run_cmd("git -C " .. wt.path .. " status --porcelain")
- local status = status_out == "" and "clean" or "dirty"
-
- table.insert(rows, rel_path .. "," .. wt.branch .. "," .. wt.head .. "," .. status)
- end
-
- -- Output via gum table
- local table_input = "Path,Branch,HEAD,Status\n" .. table.concat(rows, "\n")
- table_input = table_input:gsub("EOF", "eof")
- local table_cmd = "gum table --print <<'EOF'\n" .. table_input .. "\nEOF"
- local table_handle = io.popen(table_cmd, "r")
- if not table_handle then
- return
- end
- io.write(table_handle:read("*a") or "")
- table_handle:close()
-end
-
---List directory entries (excluding . and ..)
---@param path string
---@return string[]
@@ -57,6 +57,9 @@ local show_command_help = help_mod.show_command_help
local fetch_mod = require("wt.cmd.fetch")
local cmd_fetch = fetch_mod.cmd_fetch
+local list_mod = require("wt.cmd.list")
+local cmd_list = list_mod.cmd_list
+
---@param args string[]
local function cmd_clone(args)
-- Parse arguments: <url> [--remote name]... [--own]
@@ -710,81 +713,6 @@ local function cmd_remove(args)
end
end
-local function cmd_list()
- local root, err = find_project_root()
- if not root then
- die(err --[[@as string]])
- return
- end
-
- local git_dir = root .. "/.bare"
- local output, code = run_cmd("GIT_DIR=" .. git_dir .. " git worktree list --porcelain")
- if code ~= 0 then
- die("failed to list worktrees: " .. output, EXIT_SYSTEM_ERROR)
- end
-
- -- Parse porcelain output into worktree entries
- ---@type {path: string, head: string, branch: string}[]
- local worktrees = {}
- local current = {}
-
- for line in output:gmatch("[^\n]+") do
- local key, value = line:match("^(%S+)%s*(.*)$")
- if key == "worktree" and value then
- if current.path then
- table.insert(worktrees, current)
- end
- -- Skip .bare directory
- if value:match("/%.bare$") then
- current = {}
- else
- current = { path = value, head = "", branch = "(detached)" }
- end
- elseif key == "HEAD" and value then
- current.head = value:sub(1, 7)
- elseif key == "branch" and value then
- current.branch = value:gsub("^refs/heads/", "")
- elseif key == "bare" then
- -- Skip bare repo entry
- current = {}
- end
- end
- if current.path then
- table.insert(worktrees, current)
- end
-
- if #worktrees == 0 then
- print("No worktrees found")
- return
- end
-
- -- Get current working directory
- local cwd = get_cwd() or ""
-
- -- Build table rows with status
- local rows = {}
- for _, wt in ipairs(worktrees) do
- local rel_path = relative_path(cwd, wt.path)
-
- -- Check dirty status
- local status_out = run_cmd("git -C " .. wt.path .. " status --porcelain")
- local status = status_out == "" and "clean" or "dirty"
-
- table.insert(rows, rel_path .. "," .. wt.branch .. "," .. wt.head .. "," .. status)
- end
-
- -- Output via gum table
- local table_input = "Path,Branch,HEAD,Status\n" .. table.concat(rows, "\n")
- table_input = table_input:gsub("EOF", "eof")
- local table_cmd = "gum table --print <<'EOF'\n" .. table_input .. "\nEOF"
- local table_handle = io.popen(table_cmd, "r")
- if not table_handle then
- return
- end
- io.write(table_handle:read("*a") or "")
- table_handle:close()
-end
-
---List directory entries (excluding . and ..)
---@param path string
---@return string[]
@@ -0,0 +1,82 @@
+-- SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
+--
+-- SPDX-License-Identifier: GPL-3.0-or-later
+
+local exit = require("wt.exit")
+local shell = require("wt.shell")
+local git = require("wt.git")
+local path_mod = require("wt.path")
+
+---@class wt.cmd.list
+local M = {}
+
+---List all worktrees with status
+function M.cmd_list()
+ local root, err = git.find_project_root()
+ if not root then
+ shell.die(err --[[@as string]])
+ return
+ end
+
+ local git_dir = root .. "/.bare"
+ local output, code = shell.run_cmd("GIT_DIR=" .. git_dir .. " git worktree list --porcelain")
+ if code ~= 0 then
+ shell.die("failed to list worktrees: " .. output, exit.EXIT_SYSTEM_ERROR)
+ end
+
+ ---@type {path: string, head: string, branch: string}[]
+ local worktrees = {}
+ local current = {}
+
+ for line in output:gmatch("[^\n]+") do
+ local key, value = line:match("^(%S+)%s*(.*)$")
+ if key == "worktree" and value then
+ if current.path then
+ table.insert(worktrees, current)
+ end
+ if value:match("/%.bare$") then
+ current = {}
+ else
+ current = { path = value, head = "", branch = "(detached)" }
+ end
+ elseif key == "HEAD" and value then
+ current.head = value:sub(1, 7)
+ elseif key == "branch" and value then
+ current.branch = value:gsub("^refs/heads/", "")
+ elseif key == "bare" then
+ current = {}
+ end
+ end
+ if current.path then
+ table.insert(worktrees, current)
+ end
+
+ if #worktrees == 0 then
+ print("No worktrees found")
+ return
+ end
+
+ local cwd = shell.get_cwd() or ""
+
+ local rows = {}
+ for _, wt in ipairs(worktrees) do
+ local rel_path = path_mod.relative_path(cwd, wt.path)
+
+ local status_out = shell.run_cmd("git -C " .. wt.path .. " status --porcelain")
+ local status = status_out == "" and "clean" or "dirty"
+
+ table.insert(rows, rel_path .. "," .. wt.branch .. "," .. wt.head .. "," .. status)
+ end
+
+ local table_input = "Path,Branch,HEAD,Status\n" .. table.concat(rows, "\n")
+ table_input = table_input:gsub("EOF", "eof")
+ local table_cmd = "gum table --print <<'EOF'\n" .. table_input .. "\nEOF"
+ local table_handle = io.popen(table_cmd, "r")
+ if not table_handle then
+ return
+ end
+ io.write(table_handle:read("*a") or "")
+ table_handle:close()
+end
+
+return M