Skip to content

Commit

Permalink
feat: custom glob parsing function via 'grep.rg_glob_fn' (#373)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibhagwan committed Mar 26, 2022
1 parent 97a63e6 commit f3d0789
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 13 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,14 @@ require'fzf-lua'.setup {
rg_glob = false, -- default to glob parsing?
glob_flag = "--iglob", -- for case sensitive globs use '--glob'
glob_separator = "%s%-%-", -- query separator pattern (lua): ' --'
-- advanced usage: for custom argument parsing define
-- 'rg_glob_fn' to return a pair:
-- first returned argument is the new search query
-- second returned argument are addtional rg flags
-- rg_glob_fn = function(opts, query)
-- ...
-- return flags, new_query
-- end,
actions = {
-- actions inherit from 'actions.files' and merge
-- this action toggles between 'grep' and 'live_grep'
Expand Down
10 changes: 10 additions & 0 deletions doc/fzf-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,14 @@ Consult the list below for available settings:
rg_glob = false, -- default to glob parsing?
glob_flag = "--iglob", -- for case sensitive globs use '--glob'
glob_separator = "%s%-%-", -- query separator pattern (lua): ' --'
-- advanced usage: for custom argument parsing define
-- 'rg_glob_fn' to return a pair:
-- first returned argument is the new search query
-- second returned argument are addtional rg flags
-- rg_glob_fn = function(opts, query)
-- ...
-- return flags, new_query
-- end,
actions = {
-- actions inherit from 'actions.files' and merge
-- this action toggles between 'grep' and 'live_grep'
Expand Down Expand Up @@ -723,6 +731,8 @@ Consult the list below for available settings:
file_icons = true,
git_icons = true,
color_icons = true,
rg_opts = "--no-heading --color=always",
grep_opts = "--color=auto --perl-regexp",
fzf_opts = {
['--delimiter'] = "'[\\]:]'",
["--with-nth"] = '2..',
Expand Down
15 changes: 15 additions & 0 deletions lua/fzf-lua/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,21 @@ function M.normalize_opts(opts, defaults)
return opts
end

M.bytecode = function(s, datatype)
local keys = utils.strsplit(s, '.')
local iter = M
for i=1,#keys do
iter = iter[keys[i]]
if not iter then break end
if i == #keys and type(iter) == datatype then
-- Not sure if second argument 'true' is needed
-- can't find any references for it other than
-- it being used in packer.nvim
return string.dump(iter, true)
end
end
end

M.set_action_helpstr = function(fn, helpstr)
assert(type(fn) == 'function')
M._action_to_helpstr[fn] = helpstr
Expand Down
1 change: 1 addition & 0 deletions lua/fzf-lua/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ M.fzf_resume = function(opts)
if opts.__FNCREF__ then
-- HACK for 'live_grep' and 'lsp_live_workspace_symbols'
opts.cmd = nil
opts.search = nil
opts.continue_last_search = true
opts.__FNCREF__(opts)
else
Expand Down
38 changes: 27 additions & 11 deletions lua/fzf-lua/make_entry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ M._devicons_path = _G._devicons_path
---@diagnostic disable-next-line: undefined-field
M._devicons_setup = _G._devicons_setup

local function load_config_section(s, datatype)
local function load_config_section(s, datatype, optional)
if config then
local keys = utils.strsplit(s, '.')
local iter, sect = config, nil
Expand All @@ -34,17 +34,28 @@ local function load_config_section(s, datatype)
elseif M._fzf_lua_server then
-- load config from our running instance
local res = nil
local is_bytecode = false
local exec_str, exec_opts = nil, nil
if datatype == 'function' then
is_bytecode = true
exec_opts = { s, datatype }
exec_str = ("return require'fzf-lua'.config.bytecode(...)"):format(s)
else
exec_opts = {}
exec_str = ("return require'fzf-lua'.config.%s"):format(s)
end
local ok, errmsg = pcall(function()
local chan_id = vim.fn.sockconnect("pipe", M._fzf_lua_server, { rpc = true })
res = vim.rpcrequest(chan_id, "nvim_exec_lua", ([[
return require'fzf-lua'.config.%s
]]):format(s), {})
res = vim.rpcrequest(chan_id, "nvim_exec_lua", exec_str, exec_opts)
vim.fn.chanclose(chan_id)
end)
if not ok then
if ok and is_bytecode then
ok, res = pcall(loadstring, res)
end
if not ok and not optional then
io.stderr:write(("Error loading remote config section '%s': %s\n")
:format(s, errmsg))
elseif type(res) == datatype then
elseif ok and type(res) == datatype then
return res
end
end
Expand Down Expand Up @@ -141,11 +152,12 @@ end
pcall(load_devicons)

if not config then
local _config = { globals = { git = {}, files = {} } }
local _config = { globals = { git = {}, files = {}, grep = {} } }
_config.globals.git.icons = load_config_section('globals.git.icons', 'table') or {}
_config.globals.file_icon_colors = load_config_section('globals.file_icon_colors', 'table') or {}
_config.globals.file_icon_padding = load_config_section('globals.file_icon_padding', 'string')
_config.globals.files.git_status_cmd = load_config_section('globals.files.git_status_cmd', 'table')
_config.globals.grep.rg_glob_fn = load_config_section('globals.grep.rg_glob_fn', 'function', true)

_config.globals.nbsp = load_config_section('globals.nbsp', 'string')
if _config.globals.nbsp then utils.nbsp = _config.globals.nbsp end
Expand Down Expand Up @@ -198,10 +210,13 @@ M.glob_parse = function(opts, query)
if not query or not query:find(opts.glob_separator) then
return query, nil
end
local glob_args = ""
if config.globals.grep.rg_glob_fn then
return config.globals.grep.rg_glob_fn(opts, query)
end
local glob_args = nil
local search_query, glob_str = query:match("(.*)"..opts.glob_separator.."(.*)")
for _, s in ipairs(utils.strsplit(glob_str, "%s")) do
glob_args = glob_args .. ("%s %s ")
glob_args = (glob_args or "") .. ("%s %s ")
:format(opts.glob_flag, vim.fn.shellescape(s))
end
return search_query, glob_args
Expand Down Expand Up @@ -230,9 +245,10 @@ M.preprocess = function(opts)

-- live_grep replace pattern with last argument
local argvz = "{argvz}"
local has_argvz = opts.cmd:match(argvz)

-- save our last search argument for resume
if opts.argv_expr and opts.cmd:match(argvz) then
if opts.argv_expr and has_argvz then
local query = argv(nil, opts.debug)
set_config_section('__resume_data.last_query', query)
if opts.__module__ then
Expand All @@ -243,7 +259,7 @@ M.preprocess = function(opts)

-- did the caller request rg with glob support?
-- mannipulation needs to be done before the argv hack
if opts.rg_glob then
if opts.rg_glob and has_argvz then
local query = argv()
local search_query, glob_args = M.glob_parse(opts, query)
if glob_args then
Expand Down
15 changes: 13 additions & 2 deletions lua/fzf-lua/providers/grep.lua
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ M.grep = function(opts)
-- can call the same search again
set_last_search(opts, opts.search, no_esc or opts.no_esc)

local contents = core.mt_cmd_wrapper(opts)
local contents = core.mt_cmd_wrapper(vim.tbl_deep_extend("force", opts,
-- query was already parsed for globs inside 'get_grep_cmd'
-- no need for our external headless instance to parse again
{ rg_glob = false }))

-- by redirecting the error stream to stdout
-- we make sure a clear error message is displayed
-- when the user enters bad regex expressions
Expand Down Expand Up @@ -247,6 +251,14 @@ M.live_grep_mt = function(opts)
opts.__module__ = opts.__module__ or 'grep'
opts.prompt = set_live_grep_prompt(opts.prompt)

-- when using glob parsing we must use the external
-- headless instance for processing the query, this
-- prevents 'file|git_icons=false' from overriding
-- processing inside 'core.mt_cmd_wrapper'
if opts.rg_glob then
opts.requires_processing = true
end

assert(opts.multiprocess)

local no_esc = false
Expand Down Expand Up @@ -381,7 +393,6 @@ M.live_grep_glob_mt = function(opts)
-- 'make_entry.preprocess', only supported with multiprocess
opts = opts or {}
opts.rg_glob = true
opts.requires_processing = true
return M.live_grep_mt(opts)
end

Expand Down

0 comments on commit f3d0789

Please sign in to comment.