feat: cycle previewers with commit and bcommit already using it (#528)

- new git previewers
- jump to line in bcommit previewer
- vimdiff for bcommits
- dynamic preview window titles
- more previewers documentation

Cycle previewers are not mapped yet. So you need to setup yourself:
```lua
require('telescope').setup {
  defaults = {
    mappings = {
      i = {
        ["<C-s>"] = actions.cycle_previewers_next,
        ["<C-a>"] = actions.cycle_previewers_prev,
      },
    },
  }
}
```

Co-authored-by: Thore Strassburg <thore@weilbier.net>
This commit is contained in:
Simon Hauser
2021-06-14 21:50:46 +02:00
committed by GitHub
parent 0c1bc129da
commit 6ac5ee0854
11 changed files with 566 additions and 76 deletions

View File

@@ -59,6 +59,25 @@ local colorize_ls = function(bufnr, data, sections)
end
end
local search_cb_jump = function(self, bufnr, query)
if not query then return end
vim.api.nvim_buf_call(bufnr, function()
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.winid)
vim.cmd "norm! gg"
vim.fn.search(query, "W")
vim.cmd "norm! zz"
self.state.hl_id = vim.fn.matchadd('TelescopePreviewMatch', query)
end)
end
local search_teardown = function(self)
if self.state and self.state.hl_id then
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win)
self.state.hl_id = nil
end
end
previewers.file_maker = function(filepath, bufnr, opts)
opts = opts or {}
if opts.use_ft_detect == nil then opts.use_ft_detect = true end
@@ -107,6 +126,8 @@ previewers.new_buffer_previewer = function(opts)
local opt_setup = opts.setup
local opt_teardown = opts.teardown
local opt_title = opts.title
local opt_dyn_title = opts.dyn_title
local old_bufs = {}
local bufname_table = {}
@@ -140,6 +161,24 @@ previewers.new_buffer_previewer = function(opts)
end
end
function opts.title(self)
if opt_title then
if type(opt_title) == 'function' then
return opt_title(self)
else
return opt_title
end
end
return "Preview"
end
function opts.dyn_title(self, entry)
if opt_dyn_title then
return opt_dyn_title(self, entry)
end
return "Preview"
end
function opts.setup(self)
local state = {}
if opt_setup then vim.tbl_deep_extend("force", state, opt_setup(self)) end
@@ -228,8 +267,15 @@ previewers.new_buffer_previewer = function(opts)
return Previewer:new(opts)
end
previewers.cat = defaulter(function(_)
previewers.cat = defaulter(function(opts)
opts = opts or {}
local cwd = opts.cwd or vim.loop.cwd()
return previewers.new_buffer_previewer {
title = "File Preview",
dyn_title = function(_, entry)
return path.normalize(from_entry.path(entry, true), cwd)
end,
get_buffer_by_name = function(_, entry)
return from_entry.path(entry, true)
end,
@@ -244,7 +290,10 @@ previewers.cat = defaulter(function(_)
}
end, {})
previewers.vimgrep = defaulter(function(_)
previewers.vimgrep = defaulter(function(opts)
opts = opts or {}
local cwd = opts.cwd or vim.loop.cwd()
local jump_to_line = function(self, bufnr, lnum)
if lnum and lnum > 0 then
pcall(vim.api.nvim_buf_add_highlight, bufnr, ns_previewer, "TelescopePreviewLine", lnum - 1, 0, -1)
@@ -256,10 +305,13 @@ previewers.vimgrep = defaulter(function(_)
end
return previewers.new_buffer_previewer {
title = "Grep Preview",
dyn_title = function(_, entry)
return path.normalize(from_entry.path(entry, true), cwd)
end,
setup = function()
return {
last_set_bufnr = nil
}
return { last_set_bufnr = nil }
end,
teardown = function(self)
@@ -326,6 +378,7 @@ previewers.ctags = defaulter(function(_)
end
return previewers.new_buffer_previewer {
title = "Tags Preview",
teardown = function(self)
if self.state and self.state.hl_id then
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win)
@@ -354,16 +407,8 @@ end, {})
previewers.builtin = defaulter(function(_)
return previewers.new_buffer_previewer {
setup = function()
return {}
end,
teardown = function(self)
if self.state and self.state.hl_id then
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win)
self.state.hl_id = nil
end
end,
title = "Grep Preview",
teardown = search_teardown,
get_buffer_by_name = function(_, entry)
return entry.filename
@@ -381,14 +426,7 @@ previewers.builtin = defaulter(function(_)
conf.buffer_previewer_maker(entry.filename, self.state.bufnr, {
bufname = self.state.bufname,
callback = function(bufnr)
vim.api.nvim_buf_call(bufnr, function()
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.winid)
vim.cmd "norm! gg"
vim.fn.search(text, "W")
vim.cmd "norm! zz"
self.state.hl_id = vim.fn.matchadd('TelescopePreviewMatch', text)
end)
search_cb_jump(self, bufnr, text)
end
})
end
@@ -397,16 +435,8 @@ end, {})
previewers.help = defaulter(function(_)
return previewers.new_buffer_previewer {
setup = function()
return {}
end,
teardown = function(self)
if self.state and self.state.hl_id then
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win)
self.state.hl_id = nil
end
end,
title = "Help Preview",
teardown = search_teardown,
get_buffer_by_name = function(_, entry)
return entry.filename
@@ -420,16 +450,8 @@ previewers.help = defaulter(function(_)
conf.buffer_previewer_maker(entry.filename, self.state.bufnr, {
bufname = self.state.bufname,
callback = function(bufnr)
vim.api.nvim_buf_call(bufnr, function()
vim.cmd(':ownsyntax help')
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.winid)
vim.cmd "norm! gg"
vim.fn.search(query, "W")
vim.cmd "norm! zz"
self.state.hl_id = vim.fn.matchadd('TelescopePreviewMatch', query)
end)
putils.regex_highlighter(bufnr, 'help')
search_cb_jump(self, bufnr, query)
end
})
end
@@ -441,6 +463,7 @@ previewers.man = defaulter(function(opts)
return vim.fn.executable('col') == 1 and 'col -bx' or ''
end)
return previewers.new_buffer_previewer {
title = "Man Preview",
get_buffer_by_name = function(_, entry)
return entry.value
end,
@@ -483,6 +506,7 @@ previewers.git_branch_log = defaulter(function(opts)
end
return previewers.new_buffer_previewer {
title = "Git Branch Preview",
get_buffer_by_name = function(_, entry)
return entry.value
end,
@@ -506,6 +530,7 @@ end, {})
previewers.git_stash_diff = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "Git Stash Preview",
get_buffer_by_name = function(_, entry)
return entry.value
end,
@@ -521,25 +546,128 @@ previewers.git_stash_diff = defaulter(function(opts)
}
end, {})
previewers.git_commit_diff = defaulter(function(opts)
previewers.git_commit_diff_to_parent = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "Git Diff to Parent Preview",
teardown = search_teardown,
get_buffer_by_name = function(_, entry)
return entry.value
end,
define_preview = function(self, entry, status)
putils.job_maker({ 'git', '--no-pager', 'diff', entry.value .. '^!' }, self.state.bufnr, {
local cmd = { 'git', '--no-pager', 'diff', entry.value .. '^!' }
if opts.current_file then
table.insert(cmd, '--')
table.insert(cmd, opts.current_file)
end
putils.job_maker(cmd, self.state.bufnr, {
value = entry.value,
bufname = self.state.bufname,
cwd = opts.cwd
cwd = opts.cwd,
callback = function(bufnr)
search_cb_jump(self, bufnr, opts.current_line)
end
})
putils.regex_highlighter(self.state.bufnr, 'diff')
end
}
end, {})
previewers.git_commit_diff_to_head = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "Git Diff to Head Preview",
teardown = search_teardown,
get_buffer_by_name = function(_, entry)
return entry.value
end,
define_preview = function(self, entry, status)
local cmd = { 'git', '--no-pager', 'diff', '--cached', entry.value }
if opts.current_file then
table.insert(cmd, '--')
table.insert(cmd, opts.current_file)
end
putils.job_maker(cmd, self.state.bufnr, {
value = entry.value,
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
search_cb_jump(self, bufnr, opts.current_line)
end
})
putils.regex_highlighter(self.state.bufnr, 'diff')
end
}
end, {})
previewers.git_commit_diff_as_was = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "Git Show Preview",
teardown = search_teardown,
get_buffer_by_name = function(_, entry)
return entry.value
end,
define_preview = function(self, entry, status)
local cmd = { 'git', '--no-pager', 'show' }
local cf = opts.current_file and path.make_relative(opts.current_file, opts.cwd)
local value = cf and (entry.value .. ':' .. cf) or (entry.value)
local ft = cf and pfiletype.detect(value) or 'diff'
table.insert(cmd, value)
putils.job_maker(cmd, self.state.bufnr, {
value = entry.value,
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr)
search_cb_jump(self, bufnr, opts.current_line)
end
})
putils.highlighter(self.state.bufnr, ft)
end
}
end, {})
previewers.git_commit_message = defaulter(function(opts)
local hl_map = {
'TelescopeResultsIdentifier',
'TelescopePreviewUser',
'TelescopePreviewDate'
}
return previewers.new_buffer_previewer {
title = "Git Message",
get_buffer_by_name = function(_, entry)
return entry.value
end,
define_preview = function(self, entry, status)
local cmd = { 'git', '--no-pager', 'log', '-n 1', entry.value }
putils.job_maker(cmd, self.state.bufnr, {
value = entry.value,
bufname = self.state.bufname,
cwd = opts.cwd,
callback = function(bufnr, content)
if not content then return end
for k, v in ipairs(hl_map) do
local _, s = content[k]:find('%s')
if s then
vim.api.nvim_buf_add_highlight(bufnr, ns_previewer, v, k - 1, s, #content[k])
end
end
end
})
end
}
end, {})
previewers.git_file_diff = defaulter(function(opts)
return previewers.new_buffer_previewer {
title = "Git File Diff Preview",
get_buffer_by_name = function(_, entry)
return entry.value
end,
@@ -565,6 +693,7 @@ end, {})
previewers.autocommands = defaulter(function(_)
return previewers.new_buffer_previewer {
title = "Autocommands Preview",
teardown = function(self)
if self.state and self.state.last_set_bufnr and vim.api.nvim_buf_is_valid(self.state.last_set_bufnr) then
pcall(vim.api.nvim_buf_clear_namespace, self.state.last_set_bufnr, ns_previewer, 0, -1)
@@ -623,6 +752,7 @@ end, {})
previewers.highlights = defaulter(function(_)
return previewers.new_buffer_previewer {
title = "Highlights Preview",
teardown = function(self)
if self.state and self.state.last_set_bufnr and vim.api.nvim_buf_is_valid(self.state.last_set_bufnr) then
vim.api.nvim_buf_clear_namespace(self.state.last_set_bufnr, ns_previewer, 0, -1)

View File

@@ -53,6 +53,11 @@ local previewers = {}
--- - `teardown` function(self): Will be called on cleanup.
--- - `preview_fn` function(self, entry, status): Will be called each time
--- a new entry was selected.
--- - `title` function(self): Will return the static title of the previewer.
--- - `dynamic_title` function(self, entry): Will return the dynamic title of
--- the previewer. Will only be called
--- when config value dynamic_preview_title
--- is true.
--- - `send_input` function(self, input): This is meant for
--- `termopen_previewer` and it can be
--- used to send input to the terminal
@@ -78,6 +83,11 @@ end
--- end
--- </pre>
---
--- Additionally you can define:
--- - `title` a static title for example "File Preview"
--- - `dyn_title(self, entry)` a dynamic title function which gets called
--- when config value `dynamic_preview_title = true`
---
--- It's an easy way to get your first previewer going and it integrates well
--- with `bat` and `less`. Providing out of the box scrolling if the command
--- uses less.
@@ -166,6 +176,9 @@ previewers.qflist = term_previewer.qflist
--- useful if you have one file but multiple entries. This happens for grep
--- and lsp builtins. So to make the cache work only load content if
--- `self.state.bufname ~= entry.your_unique_key`
--- - `title` a static title for example "File Preview"
--- - `dyn_title(self, entry)` a dynamic title function which gets called
--- when config value `dynamic_preview_title = true`
---
--- `self.state` table:
--- - `self.state.bufnr`
@@ -259,11 +272,35 @@ previewers.vim_buffer_vimgrep = buffer_previewer.vimgrep
--- case it's configured that way.
previewers.vim_buffer_qflist = buffer_previewer.qflist
--- A previewer that shows a log of a branch as graph
previewers.git_branch_log = buffer_previewer.git_branch_log
previewers.git_branch_log = buffer_previewer.git_branch_log
previewers.git_commit_diff = buffer_previewer.git_commit_diff
previewers.git_file_diff = buffer_previewer.git_file_diff
previewers.git_stash_diff = buffer_previewer.git_stash_diff
--- A previewer that shows a diff of a stash
previewers.git_stash_diff = buffer_previewer.git_stash_diff
--- A previewer that shows a diff of a commit to a parent commit.<br>
--- The run command is `git --no-pager diff SHA^! -- $CURRENT_FILE`
---
--- The current file part is optional. So is only uses it with bcommits.
previewers.git_commit_diff_to_parent = buffer_previewer.git_commit_diff_to_parent
--- A previewer that shows a diff of a commit to head.<br>
--- The run command is `git --no-pager diff --cached $SHA -- $CURRENT_FILE`
---
--- The current file part is optional. So is only uses it with bcommits.
previewers.git_commit_diff_to_head = buffer_previewer.git_commit_diff_to_head
--- A previewer that shows a diff of a commit as it was.<br>
--- The run command is `git --no-pager show $SHA:$CURRENT_FILE` or `git --no-pager show $SHA`
previewers.git_commit_diff_as_was = buffer_previewer.git_commit_diff_as_was
--- A previewer that shows the commit message of a diff.<br>
--- The run command is `git --no-pager log -n 1 $SHA`
previewers.git_commit_message = buffer_previewer.git_commit_message
--- A previewer that shows the current diff of a file. Used in git_status.<br>
--- The run command is `git --no-pager diff $FILE`
previewers.git_file_diff = buffer_previewer.git_file_diff
previewers.ctags = buffer_previewer.ctags

View File

@@ -6,6 +6,8 @@ function Previewer:new(opts)
return setmetatable({
state = nil,
_title_fn = opts.title,
_dyn_title_fn = opts.dyn_title,
_setup_func = opts.setup,
_teardown_func = opts.teardown,
_send_input = opts.send_input,
@@ -30,6 +32,20 @@ function Previewer:preview(entry, status)
return self:preview_fn(entry, status)
end
function Previewer:title()
if self._title_fn then
return self:_title_fn()
end
return "Preview"
end
function Previewer:dynamic_title(entry)
if self._title_fn then
return self:_dyn_title_fn(entry)
end
return "Preview"
end
function Previewer:teardown()
if self._teardown_func then
self:_teardown_func()

View File

@@ -1,5 +1,6 @@
local conf = require('telescope.config').values
local utils = require('telescope.utils')
local path = require('telescope.path')
local putils = require('telescope.previewers.utils')
local from_entry = require('telescope.from_entry')
local Previewer = require('telescope.previewers.previewer')
@@ -112,6 +113,8 @@ previewers.new_termopen_previewer = function(opts)
local opt_setup = opts.setup
local opt_teardown = opts.teardown
local opt_title = opts.title
local opt_dyn_title = opts.dyn_title
local old_bufs = {}
@@ -135,6 +138,24 @@ previewers.new_termopen_previewer = function(opts)
if self.state then self.state.termopen_bufnr = value end
end
function opts.title(self)
if opt_title then
if type(opt_title) == 'function' then
return opt_title(self)
else
return opt_title
end
end
return "Preview"
end
function opts.dyn_title(self, entry)
if opt_dyn_title then
return opt_dyn_title(self, entry)
end
return "Preview"
end
function opts.setup(self)
local state = {}
if opt_setup then vim.tbl_deep_extend("force", state, opt_setup(self)) end
@@ -210,9 +231,17 @@ previewers.new_termopen_previewer = function(opts)
end
previewers.cat = defaulter(function(opts)
opts = opts or {}
local maker = get_maker(opts)
local cwd = opts.cwd or vim.loop.cwd()
return previewers.new_termopen_previewer {
title = "File Preview",
dyn_title = function(_, entry)
return path.normalize(from_entry.path(entry, true), cwd)
end,
get_command = function(entry)
local p = from_entry.path(entry, true)
if p == nil or p == '' then return end
@@ -223,9 +252,17 @@ previewers.cat = defaulter(function(opts)
end, {})
previewers.vimgrep = defaulter(function(opts)
opts = opts or {}
local maker = get_maker(opts)
local cwd = opts.cwd or vim.loop.cwd()
return previewers.new_termopen_previewer {
title = "Grep Preview",
dyn_title = function(_, entry)
return path.normalize(from_entry.path(entry, true), cwd)
end,
get_command = function(entry, status)
local win_id = status.preview_win
local height = vim.api.nvim_win_get_height(win_id)
@@ -251,8 +288,14 @@ previewers.qflist = defaulter(function(opts)
opts = opts or {}
local maker = get_maker(opts)
local cwd = opts.cwd or vim.loop.cwd()
return previewers.new_termopen_previewer {
title = "Grep Preview",
dyn_title = function(_, entry)
return path.normalize(from_entry.path(entry, true), cwd)
end,
get_command = function(entry, status)
local win_id = status.preview_win
local height = vim.api.nvim_win_get_height(win_id)