fix(git/cmd): parse :G args with shell-style quoting
This commit is contained in:
+1
-1
@@ -248,7 +248,7 @@ vim.keymap.set("n", "<leader>gc", function()
|
||||
require("git.commit").commit()
|
||||
end)
|
||||
vim.keymap.set("n", "<leader>ga", function()
|
||||
require("git.commit").commit({ amend = true })
|
||||
require("git.commit").commit({ args = { "--amend" } })
|
||||
end)
|
||||
vim.keymap.set("n", "<leader>gl", function()
|
||||
require('git.log_view').open({ max_count = 1000 })
|
||||
|
||||
+95
-22
@@ -42,6 +42,95 @@ local function git_cmds()
|
||||
return cached_cmds
|
||||
end
|
||||
|
||||
---@param tok string
|
||||
---@return boolean
|
||||
local function is_expansion_target(tok)
|
||||
local first = tok:sub(1, 1)
|
||||
if first == "%" or first == "#" then
|
||||
return true
|
||||
end
|
||||
if tok:match("^<%w+>") then
|
||||
return true
|
||||
end
|
||||
if tok == "~" or tok:sub(1, 2) == "~/" then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@param line string
|
||||
---@param i integer
|
||||
---@param buf string[]
|
||||
---@param escapes string?
|
||||
---@return integer
|
||||
local function parse_quoted(line, i, buf, escapes)
|
||||
local quote = line:sub(i, i)
|
||||
local n = #line
|
||||
i = i + 1
|
||||
while i <= n do
|
||||
local c = line:sub(i, i)
|
||||
if c == quote then
|
||||
return i + 1
|
||||
elseif escapes and c == "\\" and i < n then
|
||||
local nxt = line:sub(i + 1, i + 1)
|
||||
if escapes:find(nxt, 1, true) then
|
||||
table.insert(buf, nxt)
|
||||
i = i + 2
|
||||
else
|
||||
table.insert(buf, c)
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
table.insert(buf, c)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
---@param line string
|
||||
---@return string[]
|
||||
function M.parse_args(line)
|
||||
local args = {}
|
||||
local i, n = 1, #line
|
||||
while i <= n do
|
||||
local c = line:sub(i, i)
|
||||
if c == " " or c == "\t" then
|
||||
i = i + 1
|
||||
else
|
||||
local buf = {}
|
||||
local quoted = false
|
||||
while i <= n do
|
||||
c = line:sub(i, i)
|
||||
if c == " " or c == "\t" then
|
||||
break
|
||||
elseif c == "\\" and i < n then
|
||||
table.insert(buf, line:sub(i + 1, i + 1))
|
||||
i = i + 2
|
||||
elseif c == '"' then
|
||||
quoted = true
|
||||
i = parse_quoted(line, i, buf, '"\\$`')
|
||||
elseif c == "'" then
|
||||
quoted = true
|
||||
i = parse_quoted(line, i, buf, nil)
|
||||
else
|
||||
table.insert(buf, c)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
local tok = table.concat(buf)
|
||||
if not quoted and is_expansion_target(tok) then
|
||||
local expanded = vim.fn.expand(tok) --[[@as string]]
|
||||
if expanded ~= "" then
|
||||
tok = expanded
|
||||
end
|
||||
end
|
||||
table.insert(args, tok)
|
||||
end
|
||||
end
|
||||
return args
|
||||
end
|
||||
|
||||
---@param args string[]
|
||||
---@param start integer
|
||||
---@return string?
|
||||
@@ -139,18 +228,6 @@ local function run_to_messages(r, args)
|
||||
)
|
||||
end
|
||||
|
||||
---@param args string[]
|
||||
---@param flag string
|
||||
---@return boolean
|
||||
local function has_flag(args, flag)
|
||||
for _, a in ipairs(args) do
|
||||
if a == flag then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@param args string[]
|
||||
---@return boolean
|
||||
local function has_message(args)
|
||||
@@ -177,14 +254,13 @@ function M.run(args)
|
||||
|
||||
local sub = args[1]
|
||||
if sub == "commit" and not has_message(args) then
|
||||
commit.commit({ amend = has_flag(args, "--amend") })
|
||||
commit.commit({ args = vim.list_slice(args, 2) })
|
||||
return
|
||||
end
|
||||
|
||||
if sub == "show" then
|
||||
local arg = first_positional(args, 2)
|
||||
if arg and arg:find(":", 1, true) then
|
||||
object.open(r, arg)
|
||||
if #args == 2 and args[2]:find(":", 1, true) then
|
||||
object.open(r, args[2])
|
||||
return
|
||||
end
|
||||
run_in_split(r, args, { ft = "git", needs_rev = true })
|
||||
@@ -192,12 +268,9 @@ function M.run(args)
|
||||
end
|
||||
|
||||
if sub == "cat-file" then
|
||||
if vim.list_contains(args, "-p") then
|
||||
local rev = first_positional(args, 2)
|
||||
if rev then
|
||||
object.open(r, rev)
|
||||
return
|
||||
end
|
||||
if #args == 3 and args[2] == "-p" then
|
||||
object.open(r, args[3])
|
||||
return
|
||||
end
|
||||
run_in_split(r, args, { ft = "git", needs_rev = true })
|
||||
return
|
||||
|
||||
+3
-4
@@ -4,9 +4,8 @@ local util = require("git.util")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param opts { amend: boolean? }?
|
||||
---@param opts { args: string[]? }?
|
||||
function M.commit(opts)
|
||||
local amend = opts and opts.amend or false
|
||||
local r = repo.resolve()
|
||||
if not r then
|
||||
util.error("not in a git repository")
|
||||
@@ -14,8 +13,8 @@ function M.commit(opts)
|
||||
end
|
||||
|
||||
local cmd = { "git", "commit" }
|
||||
if amend then
|
||||
table.insert(cmd, "--amend")
|
||||
if opts and opts.args then
|
||||
vim.list_extend(cmd, opts.args)
|
||||
end
|
||||
|
||||
local proxy_buf, proxy_win
|
||||
|
||||
+2
-1
@@ -137,7 +137,8 @@ function M.init()
|
||||
})
|
||||
|
||||
vim.api.nvim_create_user_command("G", function(opts)
|
||||
require("git.cmd").run(opts.fargs)
|
||||
local cmd = require("git.cmd")
|
||||
cmd.run(cmd.parse_args(opts.args))
|
||||
end, {
|
||||
nargs = "*",
|
||||
complete = function(...)
|
||||
|
||||
Reference in New Issue
Block a user