From 23881568d3f7e8c15c48e25dce24af671da278fa Mon Sep 17 00:00:00 2001 From: bhagwan Date: Tue, 30 Jan 2024 00:25:58 -0500 Subject: [PATCH] fix(tags): ctags adjustments for windows --- lua/fzf-lua/core.lua | 10 +++++----- lua/fzf-lua/make_entry.lua | 22 +++++++++++++++------- lua/fzf-lua/path.lua | 4 ++-- lua/fzf-lua/providers/grep.lua | 10 ++++++++++ lua/fzf-lua/providers/tags.lua | 3 ++- lua/fzf-lua/utils.lua | 13 +++++++++++-- 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/lua/fzf-lua/core.lua b/lua/fzf-lua/core.lua index 6584363e..02a6fa1b 100644 --- a/lua/fzf-lua/core.lua +++ b/lua/fzf-lua/core.lua @@ -534,17 +534,17 @@ M.build_fzf_cli = function(opts) for k, v in pairs(opts.fzf_opts) do -- flag can be set to `false` to negate a default if v then - if utils.__IS_WINDOWS and type(v) == "string" and v:match([[^'.*'$]]) then - -- replace single quote shellescape - -- TODO: replace all so we never get here - v = [["]] .. v:sub(2, #v - 1) .. [["]] - end table.insert(cli_args, k) if type(v) == "string" or type(v) == "number" then v = tostring(v) -- convert number type to string if k == "--query" then table.insert(cli_args, libuv.shellescape(v)) else + if utils.__IS_WINDOWS and type(v) == "string" and v:match([[^'.*'$]]) then + -- replace single quote shellescape + -- TODO: replace all so we never get here + v = [["]] .. v:sub(2, #v - 1) .. [["]] + end if libuv.is_escaped(v) then utils.warn(string.format("`fzf_opts` are automatically shellescaped." .. " Please remove surrounding quotes from %s=%s", k, v)) diff --git a/lua/fzf-lua/make_entry.lua b/lua/fzf-lua/make_entry.lua index 8c1be3e4..c3b8ca9a 100644 --- a/lua/fzf-lua/make_entry.lua +++ b/lua/fzf-lua/make_entry.lua @@ -384,13 +384,21 @@ M.preprocess = function(opts) -- This changes slightly if you are running with DelayedExpansion of variables: -- if any part of the command line includes an '!' then CMD will escape a second -- time, so ^^^^ will become ^ - opts.cmd = opts.cmd:gsub('[%(%)%%!%^<>&|"]', function(x) - return "^" .. x - end) - -- make sure all ! are escaped at least twice - opts.cmd = opts.cmd:gsub("[^%^]%^!", function(x) - return x:sub(1, 1) .. "^" .. x:sub(2) - end) + -- replace in sections, only double the relevant pipe sections with ! + local escaped_cmd = {} + for _, str in ipairs(utils.strsplit(opts.cmd, "%s+|")) do + if str:match("!") then + str = str:gsub('[%(%)%%!%^<>&|"]', function(x) + return "^" .. x + end) + -- make sure all ! are escaped at least twice + str = str:gsub("[^%^]%^!", function(x) + return x:sub(1, 1) .. "^" .. x:sub(2) + end) + end + table.insert(escaped_cmd, str) + end + opts.cmd = table.concat(escaped_cmd, " |") end return opts diff --git a/lua/fzf-lua/path.lua b/lua/fzf-lua/path.lua index b58f6af3..7be7d4a2 100644 --- a/lua/fzf-lua/path.lua +++ b/lua/fzf-lua/path.lua @@ -331,11 +331,11 @@ local function stripBeforeLastOccurrenceOf(str, sep) end function M.entry_to_ctag(entry, noesc) - local ctag = entry:match("%:.-/^?\t?(.*)/") + local ctag = entry:match("%:.-[/\\]^?\t?(.*)[/\\]") -- if tag name contains a slash we could -- have the wrong match, most tags start -- with ^ so try to match based on that - ctag = ctag and ctag:match("/^(.*)") or ctag + ctag = ctag and ctag:match("[/\\]^(.*)") or ctag if ctag and not noesc then -- required escapes for vim.fn.search() -- \ ] ~ * diff --git a/lua/fzf-lua/providers/grep.lua b/lua/fzf-lua/providers/grep.lua index 758b02a2..ce9cccc9 100644 --- a/lua/fzf-lua/providers/grep.lua +++ b/lua/fzf-lua/providers/grep.lua @@ -113,6 +113,11 @@ M.grep = function(opts) end end + if utils.__IS_WINDOWS and opts.search and opts.search:match("[;,]") then + -- TODO: having [;,] in the search errs the NEQ exec_empty_query condition + opts.exec_empty_query = true + end + -- get the grep command before saving the last search -- in case the search string is overwritten by 'rg_glob' opts.cmd = get_grep_cmd(opts, opts.search, opts.no_esc) @@ -196,6 +201,11 @@ local function normalize_live_grep_opts(opts) end end + if utils.__IS_WINDOWS and opts.query:match("[;,]") then + -- TODO: having [;,] in the search errs the NEQ exec_empty_query condition + opts.exec_empty_query = true + end + return opts end diff --git a/lua/fzf-lua/providers/tags.lua b/lua/fzf-lua/providers/tags.lua index 96991f05..444f1f65 100644 --- a/lua/fzf-lua/providers/tags.lua +++ b/lua/fzf-lua/providers/tags.lua @@ -19,7 +19,8 @@ local function get_tags_cmd(opts) if opts.filename and #opts.filename > 0 then -- tags use relative paths, by now we should -- have the correct cwd from `get_ctags_cwd` - query = libuv.shellescape(path.relative_to(opts.filename, opts.cwd or vim.loop.cwd())) + query = libuv.shellescape( + utils.rg_escape(path.relative_to(opts.filename, opts.cwd or vim.loop.cwd()))) elseif opts.search and #opts.search > 0 then filter = ([[%s -v "^!"]]):format(bin) query = libuv.shellescape(opts.no_esc and opts.search or diff --git a/lua/fzf-lua/utils.lua b/lua/fzf-lua/utils.lua index 10588573..6f87c351 100644 --- a/lua/fzf-lua/utils.lua +++ b/lua/fzf-lua/utils.lua @@ -110,8 +110,17 @@ end ---@return string[] M.strsplit = function(inputstr, sep) local t = {} - for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do - table.insert(t, str) + if #sep == 1 then + for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do + table.insert(t, str) + end + else + local s, m, r = inputstr, nil, nil + repeat + m, r = s:match("^(.-)" .. sep .. "(.*)$") + s = r and r or s + table.insert(t, m or s) + until not m end return t end