diff --git a/README.md b/README.md index f4ed8c8..6d4f20e 100644 --- a/README.md +++ b/README.md @@ -383,13 +383,13 @@ require'fzf-lua'.setup { file_icons = true, -- show file icons? color_icons = true, -- colorize file|git icons -- executed command priority is 'cmd' (if exists) - -- otherwise auto-detect prioritizes `fd` over `find` - -- default options are controlled by 'fd|find_opts' + -- otherwise auto-detect prioritizes `fd`:`rg`:`find` + -- default options are controlled by 'fd|rg|find|_opts' -- NOTE: 'find -printf' requires GNU find -- cmd = "find . -type f -printf '%P\n'", find_opts = [[-type f -not -path '*/\.git/*' -printf '%P\n']], - fd_opts = [[--color never --type f --hidden --follow ]] .. - [[--exclude .git --exclude node_modules --exclude '*.pyc']], + rg_opts = "--color=never --files --hidden --follow -g '!.git'", + fd_opts = "--color=never --type f --hidden --follow --exclude .git", actions = { -- set bind to 'false' to disable an action -- default action opens a single selection diff --git a/doc/fzf-lua.txt b/doc/fzf-lua.txt index 69d92e7..a5c597a 100644 --- a/doc/fzf-lua.txt +++ b/doc/fzf-lua.txt @@ -417,13 +417,13 @@ Consult the list below for available settings: file_icons = true, -- show file icons? color_icons = true, -- colorize file|git icons -- executed command priority is 'cmd' (if exists) - -- otherwise auto-detect prioritizes `fd` over `find` - -- default options are controlled by 'fd|find_opts' + -- otherwise auto-detect prioritizes `fd`:`rg`:`find` + -- default options are controlled by 'fd|rg|find|_opts' -- NOTE: 'find -printf' requires GNU find -- cmd = "find . -type f -printf '%P\n'", find_opts = [[-type f -not -path '*/\.git/*' -printf '%P\n']], - fd_opts = [[--color never --type f --hidden --follow ]] .. - [[--exclude .git --exclude node_modules --exclude '*.pyc']], + rg_opts = "--color=never --files --hidden --follow -g '!.git'", + fd_opts = "--color=never --type f --hidden --follow --exclude .git", actions = { -- set bind to 'false' to disable an action -- default action opens a single selection diff --git a/lua/fzf-lua/config.lua b/lua/fzf-lua/config.lua index a44f1c4..3a34392 100644 --- a/lua/fzf-lua/config.lua +++ b/lua/fzf-lua/config.lua @@ -1,3 +1,4 @@ +local path = require "fzf-lua.path" local utils = require "fzf-lua.utils" local actions = require "fzf-lua.actions" local previewers = require "fzf-lua.previewer" @@ -165,18 +166,14 @@ M.globals.files = { git_icons = true, git_status_cmd = {"git", "status", "-s"}, find_opts = [[-type f -not -path '*/\.git/*' -printf '%P\n']], - fd_opts = - [[--color never --type f --hidden --follow ]] .. - [[--exclude .git --exclude node_modules --exclude '*.pyc']], + rg_opts = "--color=never --files --hidden --follow -g '!.git'", + fd_opts = "--color=never --type f --hidden --follow --exclude .git", actions = { ["default"] = actions.file_edit_or_qf, ["ctrl-s"] = actions.file_split, ["ctrl-v"] = actions.file_vsplit, ["ctrl-t"] = actions.file_tabedit, ["alt-q"] = actions.file_sel_to_qf, - ["ctrl-q"] = function() - utils.info("'ctrl-q|ctrl-a' has been deprecated in favor of 'alt-q|alt-a'") - end }, } -- Must construct our opts table in stages @@ -649,6 +646,9 @@ function M.normalize_opts(opts, defaults) opts.cwd = nil end end + + -- test for valid git_repo + opts.git_icons = opts.git_icons and path.is_git_repo(opts.cwd, true) local executable = function(binary, fncerr, strerr) if binary and vim.fn.executable(binary) ~= 1 then diff --git a/lua/fzf-lua/core.lua b/lua/fzf-lua/core.lua index 94d6b73..0ba8268 100644 --- a/lua/fzf-lua/core.lua +++ b/lua/fzf-lua/core.lua @@ -251,9 +251,9 @@ M.make_entry_file = function(opts, x) -- fd v8.3 requires adding '--strip-cwd-prefix' to remove -- the './' prefix, will not work with '--color=always' -- https://github.com/sharkdp/fd/blob/master/CHANGELOG.md - -- if not (opts.strip_cwd_prefix == false) and path.starts_with_cwd(x) then - -- x = x:sub(3) - -- end + if not (opts.strip_cwd_prefix == false) and path.starts_with_cwd(x) then + x = x:sub(3) + end if opts.cwd and #opts.cwd > 0 then -- TODO: does this work if there are ANSI escape codes in x? x = path.relative(x, opts.cwd) @@ -309,13 +309,39 @@ M.set_fzf_line_args = function(opts) return opts end -M.fzf_files = function(opts) +M.set_header = function(opts, type) + if not opts then opts = {} end + if opts.no_header then return opts end + if not opts.cwd_header then opts.cwd_header = "cwd:" end + if not opts.search_header then opts.search_header = "Searching for:" end + local header_str + local cwd_str = opts.cwd and opts.cwd ~= vim.loop.cwd() and + ("%s %s"):format(opts.cwd_header, opts.cwd:gsub("^"..vim.env.HOME, "~")) + local search_str = opts.search and #opts.search > 0 and + ("%s %s"):format(opts.search_header, opts.search) + -- 1: only search + -- 2: only cwd + -- otherwise, all + if type == 1 then header_str = search_str or '' + elseif type == 2 then header_str = cwd_str or '' + else + header_str = search_str or '' + if #header_str>0 and cwd_str and #cwd_str>0 then + header_str = header_str .. ", " + end + header_str = header_str .. (cwd_str or '') + end + if not header_str or #header_str==0 then return opts end + opts.fzf_opts['--header'] = vim.fn.shellescape(header_str) + return opts +end + +M.fzf_files = function(opts, contents) if not opts then return end -- reset git tracking opts.diff_files = nil - if opts.git_icons and not path.is_git_repo(opts.cwd, true) then opts.git_icons = false end coroutine.wrap(function () @@ -327,13 +353,7 @@ M.fzf_files = function(opts) opts.diff_files = get_diff_files(opts) end - local has_prefix = opts.file_icons or opts.git_icons or opts.lsp_icons - if not opts.filespec then - opts.filespec = utils._if(has_prefix, "{2}", "{1}") - end - - - local selected = M.fzf(opts, opts.fzf_fn) + local selected = M.fzf(opts, contents or opts.fzf_fn) if opts.post_select_cb then opts.post_select_cb() @@ -342,7 +362,8 @@ M.fzf_files = function(opts) if not selected then return end if #selected > 1 then - for i = 2, #selected do + local idx = utils.tbl_length(opts.actions)>1 and 2 or 1 + for i = idx, #selected do selected[i] = path.entry_to_file(selected[i], opts.cwd).stripped if opts.cb_selected then local cb_ret = opts.cb_selected(opts, selected[i]) diff --git a/lua/fzf-lua/path.lua b/lua/fzf-lua/path.lua index 904f49b..9834c47 100644 --- a/lua/fzf-lua/path.lua +++ b/lua/fzf-lua/path.lua @@ -8,7 +8,7 @@ M.separator = function() end M.starts_with_separator = function(path) - return path:find(M.separator()) == 1 + return path:find("^"..M.separator()) == 1 end M.starts_with_cwd = function(path) diff --git a/lua/fzf-lua/providers/files.lua b/lua/fzf-lua/providers/files.lua index baf9b58..0ee0265 100644 --- a/lua/fzf-lua/providers/files.lua +++ b/lua/fzf-lua/providers/files.lua @@ -26,6 +26,8 @@ local get_files_cmd = function(opts) local command = nil if vim.fn.executable("fd") == 1 then command = string.format('fd %s', opts.fd_opts) + elseif vim.fn.executable("rg") == 1 then + command = string.format('rg %s', opts.rg_opts) else POSIX_find_compat(opts.find_opts) command = string.format('find -L . %s', opts.find_opts) @@ -40,13 +42,16 @@ M.files = function(opts) local command = get_files_cmd(opts) - opts.fzf_fn = libuv.spawn_nvim_fzf_cmd( - { cmd = command, cwd = opts.cwd, pid_cb = opts._pid_cb }, - function(x) - return core.make_entry_file(opts, x) - end) + local contents = (opts.git_icons or opts.file_icons) and + libuv.spawn_nvim_fzf_cmd( + { cmd = command, cwd = opts.cwd, pid_cb = opts._pid_cb }, + function(x) + return core.make_entry_file(opts, x) + end) + or command - return core.fzf_files(opts) + opts = core.set_header(opts, 2) + return core.fzf_files(opts, contents) end local last_query = "" @@ -64,19 +69,11 @@ M.files_resume = function(opts) last_query = args[1] end, "{q}") - local command = get_files_cmd(opts) - opts.fzf_opts['--query'] = vim.fn.shellescape(last_query) opts._fzf_cli_args = ('--bind=change:execute-silent:%s'): format(vim.fn.shellescape(raw_act)) - opts.fzf_fn = libuv.spawn_nvim_fzf_cmd( - {cmd = command, cwd = opts.cwd}, - function(x) - return core.make_entry_file(opts, x) - end) - - return core.fzf_files(opts) + return M.files(opts) end M.args = function(opts) @@ -100,7 +97,7 @@ M.args = function(opts) end entries = nil - opts.fzf_fn = function (cb) + local contents = function (cb) for _, x in ipairs(args) do x = core.make_entry_file(opts, x) if x then @@ -115,7 +112,7 @@ M.args = function(opts) utils.delayed_cb(cb) end - return core.fzf_files(opts) + return core.fzf_files(opts, contents) end return M diff --git a/lua/fzf-lua/providers/git.lua b/lua/fzf-lua/providers/git.lua index 7e6922a..fd66c22 100644 --- a/lua/fzf-lua/providers/git.lua +++ b/lua/fzf-lua/providers/git.lua @@ -12,13 +12,15 @@ M.files = function(opts) if not opts then return end opts.cwd = path.git_root(opts.cwd) if not opts.cwd then return end - local make_entry_file = core.make_entry_file - opts.fzf_fn = libuv.spawn_nvim_fzf_cmd( - { cmd = opts.cmd, cwd = opts.cwd, pid_cb = opts._pid_cb }, - function(x) - return make_entry_file(opts, x) - end) - return core.fzf_files(opts) + local contents = (opts.git_icons or opts.file_icons) and + libuv.spawn_nvim_fzf_cmd( + { cmd = opts.cmd, cwd = opts.cwd, pid_cb = opts._pid_cb }, + function(x) + return core.make_entry_file(opts, x) + end) + or opts.cmd + opts = core.set_header(opts, 2) + return core.fzf_files(opts, contents) end M.status = function(opts) @@ -29,7 +31,7 @@ M.status = function(opts) if opts.preview then opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) end - opts.fzf_fn = libuv.spawn_nvim_fzf_cmd( + local contents = libuv.spawn_nvim_fzf_cmd( { cmd = opts.cmd, cwd = opts.cwd, pid_cb = opts._pid_cb }, function(x) -- greedy match anything after last space @@ -42,16 +44,16 @@ M.status = function(opts) end return core.make_entry_file(opts, f) end) - return core.fzf_files(opts) + opts = core.set_header(opts, 2) + return core.fzf_files(opts, contents) end local function git_cmd(opts) opts.cwd = path.git_root(opts.cwd) if not opts.cwd then return end coroutine.wrap(function () - opts.fzf_fn = libuv.spawn_nvim_fzf_cmd( - { cmd = opts.cmd, cwd = opts.cwd, pid_cb = opts._pid_cb }) - local selected = core.fzf(opts, opts.fzf_fn) + opts = core.set_header(opts, 2) + local selected = core.fzf(opts, opts.cmd) if not selected then return end actions.act(opts.actions, selected, opts) end)() diff --git a/lua/fzf-lua/providers/grep.lua b/lua/fzf-lua/providers/grep.lua index 28d7f15..0584697 100644 --- a/lua/fzf-lua/providers/grep.lua +++ b/lua/fzf-lua/providers/grep.lua @@ -52,32 +52,6 @@ local get_grep_cmd = function(opts, search_query, no_esc) return string.format('%s %s %s', command, search_query, search_path) end -local function set_search_header(opts, type) - if not opts then opts = {} end - if opts.no_header then return opts end - if not opts.cwd_header then opts.cwd_header = "cwd:" end - if not opts.search_header then opts.search_header = "Searching for:" end - local header_str - local cwd_str = opts.cwd and ("%s %s"):format(opts.cwd_header, opts.cwd) - local search_str = opts.search and #opts.search > 0 and - ("%s %s"):format(opts.search_header, opts.search) - -- 1: only search - -- 2: only cwd - -- otherwise, all - if type == 1 then header_str = search_str or '' - elseif type == 2 then header_str = cwd_str or '' - else - header_str = search_str or '' - if #header_str>0 and cwd_str and #cwd_str>0 then - header_str = header_str .. ", " - end - header_str = header_str .. (cwd_str or '') - end - if not header_str or #header_str==0 then return opts end - opts.fzf_opts['--header'] = vim.fn.shellescape(header_str) - return opts -end - M.grep = function(opts) opts = config.normalize_opts(opts, config.globals.grep) @@ -101,7 +75,7 @@ M.grep = function(opts) end ]] -- search query in header line - opts = set_search_header(opts) + opts = core.set_header(opts) -- save the search query so the use can -- call the same search again @@ -111,18 +85,16 @@ M.grep = function(opts) local command = get_grep_cmd(opts, opts.search, no_esc) - opts.fzf_fn = libuv.spawn_nvim_fzf_cmd( - { cmd = command, cwd = opts.cwd, pid_cb = opts._pid_cb }, - function(x) - return core.make_entry_file(opts, x) - end) - - --[[ opts.cb_selected = function(_, x) - return x - end ]] + local contents = (opts.git_icons or opts.file_icons) and + libuv.spawn_nvim_fzf_cmd( + { cmd = command, cwd = opts.cwd, pid_cb = opts._pid_cb }, + function(x) + return core.make_entry_file(opts, x) + end) + or command opts = core.set_fzf_line_args(opts) - core.fzf_files(opts) + core.fzf_files(opts, contents) opts.search = nil end @@ -151,7 +123,7 @@ M.live_grep = function(opts) end -- search query in header line - opts = set_search_header(opts, 2) + opts = core.set_header(opts, 2) opts._reload_command = function(query) if query and not (opts.save_last_search == false) then @@ -204,7 +176,7 @@ M.live_grep_native = function(opts) end -- search query in header line - opts = set_search_header(opts, 2) + opts = core.set_header(opts, 2) -- fzf already adds single quotes around the placeholder when expanding -- for skim we surround it with double quotes or single quote searches fail diff --git a/lua/fzf-lua/providers/oldfiles.lua b/lua/fzf-lua/providers/oldfiles.lua index a47ae2f..c204d00 100644 --- a/lua/fzf-lua/providers/oldfiles.lua +++ b/lua/fzf-lua/providers/oldfiles.lua @@ -30,7 +30,7 @@ M.oldfiles = function(opts) end end - opts.fzf_fn = function (cb) + local contents = function (cb) for _, x in ipairs(results) do x = core.make_entry_file(opts, x) if x then @@ -45,11 +45,7 @@ M.oldfiles = function(opts) utils.delayed_cb(cb) end - --[[ opts.cb_selected = function(_, x) - print("o:", x) - end ]] - - return core.fzf_files(opts) + return core.fzf_files(opts, contents) end return M diff --git a/lua/fzf-lua/providers/quickfix.lua b/lua/fzf-lua/providers/quickfix.lua index 04bd1a6..da82793 100644 --- a/lua/fzf-lua/providers/quickfix.lua +++ b/lua/fzf-lua/providers/quickfix.lua @@ -16,7 +16,7 @@ local quickfix_run = function(opts, cfg, locations) if not opts.cwd then opts.cwd = vim.loop.cwd() end - opts.fzf_fn = function (cb) + local contents = function (cb) for _, x in ipairs(results) do x = core.make_entry_file(opts, x) if x then @@ -36,7 +36,7 @@ local quickfix_run = function(opts, cfg, locations) end ]] opts = core.set_fzf_line_args(opts) - return core.fzf_files(opts) + return core.fzf_files(opts, contents) end M.quickfix = function(opts) diff --git a/lua/fzf-lua/providers/tags.lua b/lua/fzf-lua/providers/tags.lua index e19a652..3d34265 100644 --- a/lua/fzf-lua/providers/tags.lua +++ b/lua/fzf-lua/providers/tags.lua @@ -26,7 +26,7 @@ local fzf_tags = function(opts) local cwd = vim.fn.expand(opts.cwd or vim.fn.getcwd()) local current_file = vim.api.nvim_buf_get_name(0) - local fzf_function = function (cb) + local contents = function (cb) --[[ local read_line = function(file) local line @@ -137,8 +137,7 @@ local fzf_tags = function(opts) end opts = core.set_fzf_line_args(opts) - opts.fzf_fn = fzf_function - return core.fzf_files(opts) + return core.fzf_files(opts, contents) end M.tags = function(opts)