From 7b9fe4495e5777ea4f506778fab39dd6b304a0d4 Mon Sep 17 00:00:00 2001 From: bhagwan Date: Wed, 1 Sep 2021 15:37:11 -0700 Subject: [PATCH] 'git_xxx' now supports 'cwd' option (closes issue #82) --- README.md | 1 + lua/fzf-lua/actions.lua | 34 +++++++++++++++++++--------------- lua/fzf-lua/config.lua | 3 +-- lua/fzf-lua/core.lua | 19 +++++++++++-------- lua/fzf-lua/path.lua | 19 +++++++++++++++++++ lua/fzf-lua/previewer/init.lua | 10 ++++++++++ lua/fzf-lua/providers/git.lua | 32 +++++++++++++------------------- lua/fzf-lua/utils.lua | 6 ------ 8 files changed, 74 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index e926ba3..fb36a0b 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ nnoremap lua require('fzf-lua').files() |`lsp_implementations`|Implementations| |`lsp_document_symbols`|Document Symbols| |`lsp_workspace_symbols`|Workspace Symbols| +|`lsp_live_workspace_symbols`|Workspace Symbols (live query)| |`lsp_code_actions`|Code Actions| |`lsp_document_diagnostics`|Document Diagnostics| |`lsp_workspace_diagnostics`|Workspace Diagnostics| diff --git a/lua/fzf-lua/actions.lua b/lua/fzf-lua/actions.lua index 6ebf66f..f104da1 100644 --- a/lua/fzf-lua/actions.lua +++ b/lua/fzf-lua/actions.lua @@ -18,7 +18,7 @@ M.expect = function(actions) return nil end -M.act = function(actions, selected) +M.act = function(actions, selected, opts) if not actions or not selected then return end local action = "default" -- if there are no actions besides default @@ -28,7 +28,7 @@ M.act = function(actions, selected) if actions and utils.tbl_length(actions) > 1 and #selected>1 and #selected[1]>0 then action = selected[1] end if actions[action] then - actions[action](selected) + actions[action](selected, opts) end end @@ -216,14 +216,15 @@ M.man_tab = function(selected) end -M.git_switch = function(selected) +M.git_switch = function(selected, opts) + local cmd = path.git_cwd("git switch ", opts.cwd) -- remove anything past space local branch = selected[1]:match("[^ ]+") -- do nothing for active branch if branch:find("%*") ~= nil then return end local args = "" if branch:find("/") ~= nil then args = "--detach " end - local output = vim.fn.systemlist("git switch " .. args .. branch) + local output = vim.fn.systemlist(cmd .. args .. branch) if utils.shell_error() then utils.err(unpack(output)) else @@ -232,12 +233,14 @@ M.git_switch = function(selected) end end -M.git_checkout = function(selected) +M.git_checkout = function(selected, opts) + local cmd_checkout = path.git_cwd("git checkout ", opts.cwd) + local cmd_cur_commit = path.git_cwd("git rev-parse --short HEAD", opts.cwd) local commit_hash = selected[1]:match("[^ ]+") if vim.fn.input("Checkout commit " .. commit_hash .. "? [y/n] ") == "y" then - local current_commit = vim.fn.systemlist("git rev-parse --short HEAD") + local current_commit = vim.fn.systemlist(cmd_cur_commit) if(commit_hash == current_commit) then return end - local output = vim.fn.systemlist("git checkout " .. commit_hash) + local output = vim.fn.systemlist(cmd_checkout .. commit_hash) if utils.shell_error() then utils.err(unpack(output)) else @@ -247,14 +250,15 @@ M.git_checkout = function(selected) end end -M.git_buf_edit = function(selected) +M.git_buf_edit = function(selected, opts) + local cmd = path.git_cwd("git show ", opts.cwd) -- there's an empty string in position 1 for some reason? table.remove(selected,1) local win = vim.api.nvim_get_current_win() local buffer_filetype = vim.bo.filetype local file = path.relative(vim.fn.expand("%"), vim.loop.cwd()) local commit_hash = selected[1]:match("[^ ]+") - local git_file_contents = vim.fn.systemlist("git show " .. commit_hash .. ":" .. file) + local git_file_contents = vim.fn.systemlist(cmd .. commit_hash .. ":" .. file) local buf = vim.api.nvim_create_buf(true, false) local file_name = string.gsub(file,"%.","[" .. commit_hash .. "]%.") vim.api.nvim_buf_set_lines(buf,0,0,true,git_file_contents) @@ -265,19 +269,19 @@ M.git_buf_edit = function(selected) vim.api.nvim_win_set_buf(win, buf) end -M.git_buf_tabedit = function(selected) +M.git_buf_tabedit = function(selected, opts) vim.cmd('tab split') - M.git_buf_edit(selected) + M.git_buf_edit(selected, opts) end -M.git_buf_split = function(selected) +M.git_buf_split = function(selected, opts) vim.cmd('split') - M.git_buf_edit(selected) + M.git_buf_edit(selected, opts) end -M.git_buf_vsplit = function(selected) +M.git_buf_vsplit = function(selected, opts) vim.cmd('vsplit') - M.git_buf_edit(selected) + M.git_buf_edit(selected, opts) end return M diff --git a/lua/fzf-lua/config.lua b/lua/fzf-lua/config.lua index 4ad2c19..155b212 100644 --- a/lua/fzf-lua/config.lua +++ b/lua/fzf-lua/config.lua @@ -1,4 +1,3 @@ -local utils = require "fzf-lua.utils" local actions = require "fzf-lua.actions" -- Clear the default command or it would interfere with our options @@ -100,7 +99,7 @@ M.globals = { git_diff = { cmd = "git diff", args = "--color", - _new = function() return require 'fzf-lua.previewer'.cmd_async end, + _new = function() return require 'fzf-lua.previewer'.git_diff end, }, builtin = { title = true, diff --git a/lua/fzf-lua/core.lua b/lua/fzf-lua/core.lua index 88a1502..e6cc956 100644 --- a/lua/fzf-lua/core.lua +++ b/lua/fzf-lua/core.lua @@ -97,9 +97,10 @@ M.build_fzf_cli = function(opts, debug_print) return cli end -local get_diff_files = function() +local get_diff_files = function(opts) local diff_files = {} - local status = vim.fn.systemlist(config.globals.files.git_diff_cmd) + local status = vim.fn.systemlist(path.git_cwd( + config.globals.files.git_diff_cmd, opts.cwd)) if not utils.shell_error() then for i = 1, #status do local icon, file = status[i]:match("^([MUDAR])%s+(.*)") @@ -110,12 +111,14 @@ local get_diff_files = function() return diff_files end -local get_untracked_files = function() +local get_untracked_files = function(opts) local untracked_files = {} - local status = vim.fn.systemlist(config.globals.files.git_untracked_cmd) + local status = vim.fn.systemlist(path.git_cwd( + config.globals.files.git_untracked_cmd, opts.cwd)) if vim.v.shell_error == 0 then for i = 1, #status do - untracked_files[status[i]] = "?" + local file = status[i] + untracked_files[file] = "?" end end @@ -207,7 +210,7 @@ M.fzf_files = function(opts) -- reset git tracking opts.diff_files, opts.untracked_files = nil, nil - if opts.git_icons and not utils.is_git_repo() then opts.git_icons = false end + if opts.git_icons and not path.is_git_repo(opts.cwd, true) then opts.git_icons = false end if opts.cwd and #opts.cwd > 0 then opts.cwd = vim.fn.expand(opts.cwd) @@ -220,8 +223,8 @@ M.fzf_files = function(opts) end if opts.git_icons then - opts.diff_files = get_diff_files() - opts.untracked_files = get_untracked_files() + opts.diff_files = get_diff_files(opts) + opts.untracked_files = get_untracked_files(opts) end local has_prefix = opts.file_icons or opts.git_icons or opts.lsp_icons diff --git a/lua/fzf-lua/path.lua b/lua/fzf-lua/path.lua index 19c204b..95e9925 100644 --- a/lua/fzf-lua/path.lua +++ b/lua/fzf-lua/path.lua @@ -153,4 +153,23 @@ function M.entry_to_file(entry, cwd) } end +function M.git_cwd(cmd, cwd) + if not cwd then return cmd end + cwd = vim.fn.expand(cwd) + local arg_cwd = (" --git-dir=%s --work-tree=%s "):format( + vim.fn.shellescape(M.join({cwd, ".git"})), + vim.fn.shellescape(cwd)) + return cmd:gsub("^git ", "git " .. arg_cwd) +end + +function M.is_git_repo(cwd, noerr) + local cmd = M.git_cwd("git rev-parse --is-inside-work-tree", cwd) + local output = vim.fn.systemlist(cmd) + if utils.shell_error() then + if not noerr then utils.info(unpack(output)) end + return false + end + return true +end + return M diff --git a/lua/fzf-lua/previewer/init.lua b/lua/fzf-lua/previewer/init.lua index dc52768..e8536bd 100644 --- a/lua/fzf-lua/previewer/init.lua +++ b/lua/fzf-lua/previewer/init.lua @@ -10,6 +10,7 @@ Previewer.cmd = {} Previewer.bat = {} Previewer.cmd_async = {} Previewer.bat_async = {} +Previewer.git_diff = {} Previewer.buffer = {} -- Constructors call on Previewer.() @@ -154,4 +155,13 @@ function Previewer.bat_async:cmdline(o) return act end +function Previewer.git_diff:new(o, opts) + self = setmetatable(Previewer.cmd(o, opts), { + __index = vim.tbl_deep_extend("keep", + self, Previewer.cmd_async, Previewer.base + )}) + self.cmd = path.git_cwd(self.cmd, opts.cwd) + return self +end + return Previewer diff --git a/lua/fzf-lua/providers/git.lua b/lua/fzf-lua/providers/git.lua index b495560..f2fef35 100644 --- a/lua/fzf-lua/providers/git.lua +++ b/lua/fzf-lua/providers/git.lua @@ -11,25 +11,15 @@ local actions = require "fzf-lua.actions" local M = {} --- code duplication, we don't use the utils version of this --- as it doesn't print the "not in a git repo" error -local function is_git_repo() - local output = vim.fn.systemlist("git rev-parse --is-inside-work-tree") - if utils.shell_error() then - utils.info(unpack(output)) - return false - end - return true -end - local function git_version() local out = vim.fn.system("git --version") return out:match("(%d+.%d+).") end M.files = function(opts) - if not is_git_repo() then return end opts = config.normalize_opts(opts, config.globals.git.files) + if not path.is_git_repo(opts.cwd) then return end + opts.cmd = path.git_cwd(opts.cmd, opts.cwd) opts.fzf_fn = fzf_helpers.cmd_line_transformer(opts.cmd, function(x) return core.make_entry_file(opts, x) @@ -38,9 +28,12 @@ M.files = function(opts) end M.status = function(opts) - if not is_git_repo() then return end opts = config.normalize_opts(opts, config.globals.git.status) - if opts.preview then opts.preview = vim.fn.shellescape(opts.preview) end + if not path.is_git_repo(opts.cwd) then return end + if opts.preview then + opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) + end + opts.cmd = path.git_cwd(opts.cmd, opts.cwd) opts.fzf_fn = fzf_helpers.cmd_line_transformer(opts.cmd, function(x) -- greedy match anything after last space @@ -51,19 +44,20 @@ M.status = function(opts) end local function git_cmd(opts) - if not is_git_repo() then return end + if not path.is_git_repo(opts.cwd) then return end + opts.cmd = path.git_cwd(opts.cmd, opts.cwd) coroutine.wrap(function () opts.fzf_fn = fzf_helpers.cmd_line_transformer(opts.cmd, function(x) return x end) local selected = core.fzf(opts, opts.fzf_fn) if not selected then return end - actions.act(opts.actions, selected) + actions.act(opts.actions, selected, opts) end)() end M.commits = function(opts) opts = config.normalize_opts(opts, config.globals.git.commits) - opts.preview = vim.fn.shellescape(opts.preview) + opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) return git_cmd(opts) end @@ -76,13 +70,13 @@ M.bcommits = function(opts) if git_ver and tonumber(git_ver) >= 2.31 then opts.preview = opts.preview .. " --rotate-to=" .. vim.fn.shellescape(file) end - opts.preview = vim.fn.shellescape(opts.preview) + opts.preview = vim.fn.shellescape(path.git_cwd(opts.preview, opts.cwd)) return git_cmd(opts) end M.branches = function(opts) opts = config.normalize_opts(opts, config.globals.git.branches) - opts._preview = opts.preview + opts._preview = path.git_cwd(opts.preview, opts.cwd) opts.preview = fzf_helpers.choices_to_shell_cmd_previewer(function(items) local branch = items[1]:gsub("%*", "") -- remove the * from current branch if branch:find("%)") ~= nil then diff --git a/lua/fzf-lua/utils.lua b/lua/fzf-lua/utils.lua index d49046b..c779b6c 100644 --- a/lua/fzf-lua/utils.lua +++ b/lua/fzf-lua/utils.lua @@ -61,12 +61,6 @@ function M.shell_error() return vim.v.shell_error ~= 0 end -function M.is_git_repo() - -- can also use: "git rev-parse is-inside-work-tree" - vim.fn.system("git rev-parse --git-dir") - return M._if(M.shell_error(), false, true) -end - function M.rg_escape(str) if not str then return str end -- [(~'"\/$?'`*&&||;[]<>)]