Refactored argument parsing in add, clone, and new commands to use a
for-loop pattern that collects flags and positional args separately.
This allows POSIX-style flexible flag positioning (e.g., `wt a -b
branch` works the same as `wt a branch -b`).
Also adds @cast annotations after validation to satisfy the type
checker.
Assisted-by: Claude Opus 4.5 via Amp
@@ -960,12 +960,15 @@ local M = {}
---@param args string[]
function M.cmd_clone(args)
-- Parse arguments: <url> [--remote name]... [--own]
- local url = nil
+ ---@type string|nil
+ local url
---@type string[]
local remote_flags = {}
local own = false
local i = 1
+ -- Flags can appear anywhere in the argument list
+ local positional = {}
while i <= #args do
local a = args[i]
if a == "--remote" then
@@ -976,18 +979,21 @@ function M.cmd_clone(args)
i = i + 1
elseif a == "--own" then
own = true
- elseif not url then- url = a
+ elseif a:match("^%-") then
+ shell.die("unknown flag: " .. a)
else
- shell.die("unexpected argument: " .. a)
+ table.insert(positional, a)
end
i = i + 1
end
- if not url then
+ if #positional == 0 then
shell.die("usage: wt c <url> [--remote name]... [--own]")
return
+ elseif #positional > 1 then
+ shell.die("unexpected argument: " .. positional[2])
end
+ url = positional[1]
-- Extract project name from URL
local project_name = config.extract_project_name(url)
@@ -1248,11 +1254,14 @@ local M = {}
---@param args string[]
function M.cmd_new(args)
-- Parse arguments: <project-name> [--remote name]...
- local project_name = nil
+ ---@type string|nil
+ local project_name
---@type string[]
local remote_flags = {}
local i = 1
+ -- Flags can appear anywhere in the argument list
+ local positional = {}
while i <= #args do
local a = args[i]
if a == "--remote" then
@@ -1261,18 +1270,21 @@ function M.cmd_new(args)
end
table.insert(remote_flags, args[i + 1])
i = i + 1
- elseif not project_name then- project_name = a
+ elseif a:match("^%-") then
+ shell.die("unknown flag: " .. a)
else
- shell.die("unexpected argument: " .. a)
+ table.insert(positional, a)
end
i = i + 1
end
- if not project_name then
+ if #positional == 0 then
shell.die("usage: wt n <project-name> [--remote name]...")
return
+ elseif #positional > 1 then
+ shell.die("unexpected argument: " .. positional[2])
end
+ project_name = positional[1]
-- Check if project directory already exists
local cwd = shell.get_cwd()
@@ -1444,27 +1456,29 @@ function M.cmd_add(args)
---@type string|nil
local start_point = nil
- local i = 1- while i <= #args do- local a = args[i]
+ -- Collect flags and positional args (flags can appear anywhere)
+ local positional = {}
+ for _, a in ipairs(args) do
if a == "-b" then
create_branch = true
- -- Check if next arg is start-point (not another flag)- if args[i + 1] and not args[i + 1]:match("^%-") then- start_point = args[i + 1]- i = i + 1- end- elseif not branch then- branch = a
+ elseif a:match("^%-") then
+ shell.die("unknown flag: " .. a)
else
- shell.die("unexpected argument: " .. a)
+ table.insert(positional, a)
end
- i = i + 1
end
- if not branch then
+ -- Assign positional args: <branch> [<start-point>]
+ if #positional == 0 then
shell.die("usage: wt a <branch> [-b [<start-point>]]")
return
+ elseif #positional == 1 then
+ branch = positional[1]
+ elseif #positional == 2 then
+ branch = positional[1]
+ start_point = positional[2]
+ else
+ shell.die("unexpected argument: " .. positional[3])
end
local root, err = git.find_project_root()
@@ -22,28 +22,31 @@ function M.cmd_add(args)
---@type string|nil
local start_point = nil
- local i = 1- while i <= #args do- local a = args[i]
+ -- Collect flags and positional args (flags can appear anywhere)
+ local positional = {}
+ for _, a in ipairs(args) do
if a == "-b" then
create_branch = true
- -- Check if next arg is start-point (not another flag)- if args[i + 1] and not args[i + 1]:match("^%-") then- start_point = args[i + 1]- i = i + 1- end- elseif not branch then- branch = a
+ elseif a:match("^%-") then
+ shell.die("unknown flag: " .. a)
else
- shell.die("unexpected argument: " .. a)
+ table.insert(positional, a)
end
- i = i + 1
end
- if not branch then
+ -- Assign positional args: <branch> [<start-point>]
+ if #positional == 0 then
shell.die("usage: wt a <branch> [-b [<start-point>]]")
return
+ elseif #positional == 1 then
+ branch = positional[1]
+ elseif #positional == 2 then
+ branch = positional[1]
+ start_point = positional[2]
+ else
+ shell.die("unexpected argument: " .. positional[3])
end
+ ---@cast branch string
local root, err = git.find_project_root()
if not root then
@@ -15,12 +15,15 @@ local M = {}
---@param args string[]
function M.cmd_clone(args)
-- Parse arguments: <url> [--remote name]... [--own]
- local url = nil
+ ---@type string|nil
+ local url
---@type string[]
local remote_flags = {}
local own = false
local i = 1
+ -- Flags can appear anywhere in the argument list
+ local positional = {}
while i <= #args do
local a = args[i]
if a == "--remote" then
@@ -31,18 +34,22 @@ function M.cmd_clone(args)
i = i + 1
elseif a == "--own" then
own = true
- elseif not url then- url = a
+ elseif a:match("^%-") then
+ shell.die("unknown flag: " .. a)
else
- shell.die("unexpected argument: " .. a)
+ table.insert(positional, a)
end
i = i + 1
end
- if not url then
+ if #positional == 0 then
shell.die("usage: wt c <url> [--remote name]... [--own]")
return
+ elseif #positional > 1 then
+ shell.die("unexpected argument: " .. positional[2])
end
+ url = positional[1]
+ ---@cast url string
-- Extract project name from URL
local project_name = config.extract_project_name(url)
@@ -15,11 +15,14 @@ local M = {}
---@param args string[]
function M.cmd_new(args)
-- Parse arguments: <project-name> [--remote name]...
- local project_name = nil
+ ---@type string|nil
+ local project_name
---@type string[]
local remote_flags = {}
local i = 1
+ -- Flags can appear anywhere in the argument list
+ local positional = {}
while i <= #args do
local a = args[i]
if a == "--remote" then
@@ -28,18 +31,22 @@ function M.cmd_new(args)
end
table.insert(remote_flags, args[i + 1])
i = i + 1
- elseif not project_name then- project_name = a
+ elseif a:match("^%-") then
+ shell.die("unknown flag: " .. a)
else
- shell.die("unexpected argument: " .. a)
+ table.insert(positional, a)
end
i = i + 1
end
- if not project_name then
+ if #positional == 0 then
shell.die("usage: wt n <project-name> [--remote name]...")
return
+ elseif #positional > 1 then
+ shell.die("unexpected argument: " .. positional[2])
end
+ project_name = positional[1]
+ ---@cast project_name string
-- Check if project directory already exists
local cwd = shell.get_cwd()