From dae78fc15312487e864e17d0b45183b7245a1809 Mon Sep 17 00:00:00 2001 From: bhagwan Date: Sat, 9 Jul 2022 12:53:02 -0700 Subject: [PATCH] feat(git): improvements in git 'status|commits|bcommits': - Option to define 'preview_pager' (e.g. `delta`) which will be piped onto the preview command, more convinient than having to rewrite the preview command or have to define it under 'previewers.git_diff' for 'git.status' - Added timestamp & author name to 'commits|bcommits' default command - Added timestamp to 'commits' default preview command - 'bcommits' changes: + disabled for unnamed buffers + default preview now shows `git diff` for the specific file (instead of showing the entire commit + will attempt to detect the current buffers git root in case current working directory changed, i.e. 'bcommits' will work as long as the current buffer is under a git repo) - 'branches': better branch extraction lua pattern --- README.md | 53 +++++++++++++++++---------- doc/fzf-lua.txt | 53 +++++++++++++++++---------- lua/fzf-lua/config.lua | 8 ++-- lua/fzf-lua/previewer/fzf.lua | 6 +-- lua/fzf-lua/providers/git.lua | 69 ++++++++++++++++++++++------------- 5 files changed, 118 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 1ed3b9c..2064cbf 100644 --- a/README.md +++ b/README.md @@ -507,7 +507,9 @@ require'fzf-lua'.setup { cmd_deleted = "git diff --color HEAD --", cmd_modified = "git diff --color HEAD", cmd_untracked = "git diff --color --no-index /dev/null", - -- pager = "delta", -- if you have `delta` installed + -- uncomment if you wish to use git-delta as pager + -- can also be set under 'git.status.preview_pager' + -- pager = "delta --width=$FZF_PREVIEW_COLUMNS", }, man = { -- NOTE: remove the `-c` flag when using man-db @@ -563,23 +565,27 @@ require'fzf-lua'.setup { }, git = { files = { - prompt = 'GitFiles❯ ', - cmd = 'git ls-files --exclude-standard', - multiprocess = true, -- run command in a separate process - git_icons = true, -- show git icons? - file_icons = true, -- show file icons? - color_icons = true, -- colorize file|git icons + prompt = 'GitFiles❯ ', + cmd = 'git ls-files --exclude-standard', + multiprocess = true, -- run command in a separate process + git_icons = true, -- show git icons? + file_icons = true, -- show file icons? + color_icons = true, -- colorize file|git icons -- force display the cwd header line regardles of your current working -- directory can also be used to hide the header when not wanted -- show_cwd_header = true }, status = { - prompt = 'GitStatus❯ ', - cmd = "git status -s", - previewer = "git_diff", - file_icons = true, - git_icons = true, - color_icons = true, + prompt = 'GitStatus❯ ', + -- consider using `git status -su` if you wish to see + -- untracked files individually under their subfolders + cmd = "git status -s", + file_icons = true, + git_icons = true, + color_icons = true, + previewer = "git_diff", + -- uncomment if you wish to use git-delta as pager + --preview_pager = "delta --width=$FZF_PREVIEW_COLUMNS" actions = { -- actions inherit from 'actions.files' and merge ["right"] = { actions.git_unstage, actions.resume }, @@ -587,17 +593,26 @@ require'fzf-lua'.setup { }, }, commits = { - prompt = 'Commits❯ ', - cmd = "git log --pretty=oneline --abbrev-commit --color", - preview = "git show --pretty='%Cred%H%n%Cblue%an%n%Cgreen%s' --color {1}", + prompt = 'Commits❯ ', + cmd = "git log --color --pretty=format:'%C(yellow)%h%Creset %Cgreen(%><(12)%cr%><|(12))%Creset %s %C(blue)<%an>%Creset'", + preview = "git show --pretty='%Cred%H%n%Cblue%an <%ae>%n%C(yellow)%cD%n%Cgreen%s' --color {1}", + -- uncomment if you wish to use git-delta as pager + --preview_pager = "delta --width=$FZF_PREVIEW_COLUMNS" actions = { ["default"] = actions.git_checkout, }, }, bcommits = { - prompt = 'BCommits❯ ', - cmd = "git log --pretty=oneline --abbrev-commit --color", - preview = "git show --pretty='%Cred%H%n%Cblue%an%n%Cgreen%s' --color {1}", + prompt = 'BCommits❯ ', + -- default preview shows a git diff vs the previous commit + -- if you prefer to see the entire commit you can use: + -- git show --color {1} --rotate-to= + -- {1} : commit SHA (fzf field index expression) + -- : filepath placement within the commands + cmd = "git log --color --pretty=format:'%C(yellow)%h%Creset %Cgreen(%><(12)%cr%><|(12))%Creset %s %C(blue)<%an>%Creset' ", + preview = "git diff --color {1}~1 {1} -- ", + -- uncomment if you wish to use git-delta as pager + --preview_pager = "delta --width=$FZF_PREVIEW_COLUMNS" actions = { ["default"] = actions.git_buf_edit, ["ctrl-s"] = actions.git_buf_split, diff --git a/doc/fzf-lua.txt b/doc/fzf-lua.txt index 914d52b..c88921d 100644 --- a/doc/fzf-lua.txt +++ b/doc/fzf-lua.txt @@ -546,7 +546,9 @@ open an issue and I'll be more than happy to help.** cmd_deleted = "git diff --color HEAD --", cmd_modified = "git diff --color HEAD", cmd_untracked = "git diff --color --no-index /dev/null", - -- pager = "delta", -- if you have `delta` installed + -- uncomment if you wish to use git-delta as pager + -- can also be set under 'git.status.preview_pager' + -- pager = "delta --width=$FZF_PREVIEW_COLUMNS", }, man = { -- NOTE: remove the `-c` flag when using man-db @@ -602,23 +604,27 @@ open an issue and I'll be more than happy to help.** }, git = { files = { - prompt = 'GitFiles❯ ', - cmd = 'git ls-files --exclude-standard', - multiprocess = true, -- run command in a separate process - git_icons = true, -- show git icons? - file_icons = true, -- show file icons? - color_icons = true, -- colorize file|git icons + prompt = 'GitFiles❯ ', + cmd = 'git ls-files --exclude-standard', + multiprocess = true, -- run command in a separate process + git_icons = true, -- show git icons? + file_icons = true, -- show file icons? + color_icons = true, -- colorize file|git icons -- force display the cwd header line regardles of your current working -- directory can also be used to hide the header when not wanted -- show_cwd_header = true }, status = { - prompt = 'GitStatus❯ ', - cmd = "git status -s", - previewer = "git_diff", - file_icons = true, - git_icons = true, - color_icons = true, + prompt = 'GitStatus❯ ', + -- consider using `git status -su` if you wish to see + -- untracked files individually under their subfolders + cmd = "git status -s", + file_icons = true, + git_icons = true, + color_icons = true, + previewer = "git_diff", + -- uncomment if you wish to use git-delta as pager + --preview_pager = "delta --width=$FZF_PREVIEW_COLUMNS" actions = { -- actions inherit from 'actions.files' and merge ["right"] = { actions.git_unstage, actions.resume }, @@ -626,17 +632,26 @@ open an issue and I'll be more than happy to help.** }, }, commits = { - prompt = 'Commits❯ ', - cmd = "git log --pretty=oneline --abbrev-commit --color", - preview = "git show --pretty='%Cred%H%n%Cblue%an%n%Cgreen%s' --color {1}", + prompt = 'Commits❯ ', + cmd = "git log --color --pretty=format:'%C(yellow)%h%Creset %Cgreen(%><(12)%cr%><|(12))%Creset %s %C(blue)<%an>%Creset'", + preview = "git show --pretty='%Cred%H%n%Cblue%an <%ae>%n%C(yellow)%cD%n%Cgreen%s' --color {1}", + -- uncomment if you wish to use git-delta as pager + --preview_pager = "delta --width=$FZF_PREVIEW_COLUMNS" actions = { ["default"] = actions.git_checkout, }, }, bcommits = { - prompt = 'BCommits❯ ', - cmd = "git log --pretty=oneline --abbrev-commit --color", - preview = "git show --pretty='%Cred%H%n%Cblue%an%n%Cgreen%s' --color {1}", + prompt = 'BCommits❯ ', + -- default preview shows a git diff vs the preview commit + -- if you prefer to see the entire commit you can use: + -- git show --color {1} --rotate-to= + -- {1} : commit SHA (fzf field index expression) + -- : filepath placement within the commands + cmd = "git log --color --pretty=format:'%C(yellow)%h%Creset %Cgreen(%><(12)%cr%><|(12))%Creset %s %C(blue)<%an>%Creset' ", + preview = "git diff --color {1}~1 {1} -- ", + -- uncomment if you wish to use git-delta as pager + --preview_pager = "delta --width=$FZF_PREVIEW_COLUMNS" actions = { ["default"] = actions.git_buf_edit, ["ctrl-s"] = actions.git_buf_split, diff --git a/lua/fzf-lua/config.lua b/lua/fzf-lua/config.lua index 2b0abe6..da2dcb6 100644 --- a/lua/fzf-lua/config.lua +++ b/lua/fzf-lua/config.lua @@ -240,16 +240,16 @@ M.globals.git = { }, commits = { prompt = 'Commits> ', - cmd = "git log --pretty=oneline --abbrev-commit --color", - preview = "git show --pretty='%Cred%H%n%Cblue%an%n%Cgreen%s' --color {1}", + cmd = "git log --color --pretty=format:'%C(yellow)%h%Creset %Cgreen(%><(12)%cr%><|(12))%Creset %s %C(blue)<%an>%Creset'", + preview = "git show --pretty='%Cred%H%n%Cblue%an <%ae>%n%C(yellow)%cD%n%Cgreen%s' --color {1}", actions = { ["default"] = actions.git_checkout, }, }, bcommits = { prompt = 'BCommits> ', - cmd = "git log --pretty=oneline --abbrev-commit --color", - preview = "git show --pretty='%Cred%H%n%Cblue%an%n%Cgreen%s' --color {1}", + cmd = "git log --color --pretty=format:'%C(yellow)%h%Creset %Cgreen(%><(12)%cr%><|(12))%Creset %s %C(blue)<%an>%Creset' ", + preview = "git diff --color {1}~1 {1} -- ", actions = { ["default"] = actions.git_buf_edit, ["ctrl-s"] = actions.git_buf_split, diff --git a/lua/fzf-lua/previewer/fzf.lua b/lua/fzf-lua/previewer/fzf.lua index 6e541fa..3d8644b 100644 --- a/lua/fzf-lua/previewer/fzf.lua +++ b/lua/fzf-lua/previewer/fzf.lua @@ -244,7 +244,7 @@ function Previewer.git_diff:new(o, opts) self.cmd_deleted = path.git_cwd(o.cmd_deleted, opts) self.cmd_modified = path.git_cwd(o.cmd_modified, opts) self.cmd_untracked = path.git_cwd(o.cmd_untracked, opts) - self.pager = o.pager + self.pager = o.pager or opts.preview_pager do -- populate the icon mappings local icons_overrides = o._fn_git_icons and o._fn_git_icons() @@ -298,8 +298,8 @@ function Previewer.git_diff:cmdline(o) cmd = cmd .. " %s" end cmd = cmd:format(vim.fn.shellescape(file.path)) - cmd = ("FZF_PREVIEW_LINES=%d;FZF_PREVIEW_COLUMNS=%d;%s %s") - :format(fzf_lines, fzf_columns, cmd, pager) + cmd = ("LINES=%d;COLUMNS=%d;FZF_PREVIEW_LINES=%d;FZF_PREVIEW_COLUMNS=%d;%s %s") + :format(fzf_lines, fzf_columns, fzf_lines, fzf_columns, cmd, pager) cmd = 'sh -c ' .. vim.fn.shellescape(cmd) -- uncomment to see the command in the preview window -- cmd = vim.fn.shellescape(cmd) diff --git a/lua/fzf-lua/providers/git.lua b/lua/fzf-lua/providers/git.lua index f0efb69..32b6ed8 100644 --- a/lua/fzf-lua/providers/git.lua +++ b/lua/fzf-lua/providers/git.lua @@ -95,29 +95,46 @@ end M.commits = function(opts) opts = config.normalize_opts(opts, config.globals.git.commits) if not opts then return end - opts.preview = path.git_cwd(opts.preview, opts) + if opts.preview then + opts.preview = path.git_cwd(opts.preview, opts) + if opts.preview_pager then + opts.preview = string.format("%s | %s", opts.preview, opts.preview_pager) + end + end return git_cmd(opts) end M.bcommits = function(opts) opts = config.normalize_opts(opts, config.globals.git.bcommits) if not opts then return end + local bufname = vim.api.nvim_buf_get_name(0) + if not bufname or #bufname==0 then + utils.info("'bcommits' is not available for unnamed buffers.") + return + end + -- if caller did not specify cwd we attempt to auto detect the + -- file's git repo from its parent folder, could be further + -- optimized to prevent the duplicate call to `git rev-parse` + -- but overall it's not a big deal as it's a pretty cheap call + -- first 'git_root' call won't print a warning to ':messages' + if not opts.cwd and not opts.git_dir then + opts.cwd = path.git_root({ cwd = vim.fn.expand("%:p:h") }, true) + end local git_root = path.git_root(opts) if not git_root then return end local file = path.relative(vim.fn.expand("%:p"), git_root) - opts.cmd = opts.cmd .. " " .. file - local git_ver = utils.git_version() - -- rotate-to first appeared with git version 2.31 - if git_ver and git_ver >= 2.31 then - -- check if the user added a pipe (e.g. `| delta`) - local before_pipe = opts.preview:match("[^|]+") - local after_pipe = opts.preview:match("|.*$") or '' - opts.preview = before_pipe - .. " --rotate-to=" - .. vim.fn.shellescape(file) - .. after_pipe + if opts.cmd:match("", file) + else + opts.cmd = opts.cmd .. " " .. file + end + if type(opts.preview) == 'string' then + opts.preview = opts.preview:gsub("", vim.fn.shellescape(file)) + opts.preview = path.git_cwd(opts.preview, opts) + if opts.preview_pager then + opts.preview = string.format("%s | %s", opts.preview, opts.preview_pager) + end end - opts.preview = path.git_cwd(opts.preview, opts) return git_cmd(opts) end @@ -125,19 +142,19 @@ M.branches = function(opts) opts = config.normalize_opts(opts, config.globals.git.branches) if not opts then return end opts.fzf_opts["--no-multi"] = '' - opts.__preview = path.git_cwd(opts.preview, opts) - opts.preview = shell.raw_preview_action_cmd(function(items) - local branch = items[1]:gsub("%*", "") -- remove the * from current branch - if branch:find("%)") ~= nil then - -- (HEAD detached at origin/master) - branch = branch:match(".* ([^%)]+)") or "" - else - -- remove anything past space - branch = branch:match("[^ ]+") - end - return opts.__preview:gsub("{.*}", branch) - -- return "echo " .. branch - end, nil, opts.debug) + if opts.preview then + opts.__preview = path.git_cwd(opts.preview, opts) + opts.preview = shell.raw_preview_action_cmd(function(items) + -- all possible options; + -- branch + -- * branch + -- remotes/origin/branch + -- (HEAD detached at origin/branch) + local branch = items[1]:match("[^%s%*]*$"):gsub("%)$", "") + return opts.__preview:gsub("{.*}", branch) + -- return "echo " .. branch + end, nil, opts.debug) + end return git_cmd(opts) end