added builtin previewer

main
bhagwan 3 years ago
parent 233062d7e6
commit eefed45175

@ -199,9 +199,8 @@ require'fzf-lua'.setup {
win_col = 0.50, -- window col position (0=left, 1=right)
-- win_border = false, -- window border? or borderchars?
win_border = { '╭', '─', '╮', '│', '╯', '─', '╰', '│' },
window_on_create = function() -- nvim window options override
vim.cmd("set winhl=Normal:Normal") -- popup bg match normal windows
end,
hl_normal = 'Normal', -- window normal color
hl_border = 'FloatBorder', -- window border color
},
-- fzf_bin = 'sk', -- use skim instead of fzf?
fzf_layout = 'reverse', -- fzf '--layout='
@ -226,7 +225,7 @@ require'fzf-lua'.setup {
preview_layout = 'flex', -- horizontal|vertical|flex
flip_columns = 120, -- #cols to switch to horizontal on flex
-- default_previewer = "bat", -- override the default previewer?
-- by default auto-detect bat|cat
-- by default uses the builtin previewer
previewers = {
cmd = {
-- custom previewer, will execute:
@ -252,6 +251,24 @@ require'fzf-lua'.setup {
cmd = "git diff",
args = "--color",
},
builtin = {
title = true, -- preview title?
scrollbar = true, -- scrollbar?
scrollchar = '█', -- scrollbar character
wrap = false, -- wrap lines?
syntax = true, -- preview syntax highlight?
fullscreen = false, -- preview max size?
hl_cursor = 'Cursor', -- cursor highlight
hl_range = 'IncSearch', -- ranger highlight (not yet in use)
keymap = {
toggle_full = '<F2>', -- toggle full screen
toggle_wrap = '<F3>', -- toggle line wrap
toggle_hide = '<F4>', -- toggle on/off (not yet in use)
page_up = '<S-up>', -- preview scroll up
page_down = '<S-down>', -- preview scroll down
page_reset = '<S-left>', -- reset scroll to orig pos
},
},
},
-- provider setup
files = {
@ -365,9 +382,6 @@ require'fzf-lua'.setup {
winopts = {
win_height = 0.55,
win_width = 0.30,
window_on_create = function()
vim.cmd("set winhl=Normal:Normal")
end,
},
post_reset_cb = function()
-- reset statusline highlights after
@ -422,7 +436,7 @@ EOF
## TODO
- [ ] Add more providers
- [x] Add more providers
+ [x] ~~LSP (refs, symbols, etc)~~ (2021-07-20)
+ [x] ~~git commits~~ (2021-08-05)
+ [x] ~~git branches~~ (2021-08-05)
@ -435,8 +449,9 @@ EOF
* [x] ~~spelling suggestions~~ (2021-08-14)
* [x] ~~marks~~ (2021-08-14)
+ [x] ~~tags~~ (2021-08-15)
- [ ] Improve previewer for `buffers`, `marks`
- [ ] Built-in previewer with treesitter support
- [x] ~~Built-in previewer with treesitter support~~ (2021-08-29)
- [x] ~~Improve previewer for `buffers`~~ (2021-08-29)
- [ ] Add support for `marks` in the builtin previewer
- [ ] Add built-in plugin documentation
- [ ] Complete the Wiki

@ -25,10 +25,13 @@ M.globals = {
win_row = 0.30,
win_col = 0.50,
win_border = true,
window_on_create = function()
borderchars = { '', '', '', '', '', '', '', '' },
hl_normal = 'Normal',
hl_border = 'FloatBorder',
--[[ window_on_create = function()
-- Set popup background same as normal windows
vim.cmd("set winhl=Normal:Normal")
end,
vim.cmd("set winhl=Normal:Normal,FloatBorder:FloatBorder")
end, ]]
},
default_prompt = '> ',
fzf_bin = nil,
@ -61,7 +64,7 @@ M.globals = {
preview_horizontal = 'right:60%',
preview_layout = 'flex',
flip_columns = 120,
default_previewer = utils._if(vim.fn.executable("bat")==1, "bat", "cat"),
default_previewer = "builtin",
previewers = {
cmd = {
-- custom previewer to be overidden by the user
@ -100,11 +103,29 @@ M.globals = {
_new = function() return require 'fzf-lua.previewer'.cmd_async end,
},
builtin = {
treesitter = true,
_new = function() return require 'fzf-lua.previewer'.builtin end,
title = true,
scrollbar = true,
scrollchar = '',
wrap = false,
syntax = true,
syntax_delay = 0,
fullscreen = false,
hl_cursor = 'Cursor',
hl_range = 'IncSearch',
keymap = {
toggle_full = '<F2>', -- toggle full screen
toggle_wrap = '<F3>', -- toggle line wrap
toggle_hide = '<F4>', -- toggle on/off (not yet in use)
page_up = '<S-up>', -- preview scroll up
page_down = '<S-down>', -- preview scroll down
page_reset = '<S-left>', -- reset scroll to orig pos
},
_new = function() return require 'fzf-lua.previewer.builtin' end,
},
},
files = {
}
M.globals.files = {
previewer = function() return M.globals.default_previewer end,
prompt = '> ',
cmd = nil, -- default: auto detect find|fd
file_icons = true and M._has_devicons,
@ -124,11 +145,11 @@ M.globals = {
["ctrl-q"] = actions.file_sel_to_qf,
},
}
}
-- Must construct our opts table in stages
-- so we can reference 'M.globals.files'
M.globals.git = {
files = {
previewer = function() return M.globals.default_previewer end,
prompt = 'GitFiles> ',
cmd = "git ls-files --exclude-standard",
file_icons = true and M._has_devicons,
@ -177,6 +198,7 @@ M.globals.git = {
},
}
M.globals.grep = {
previewer = function() return M.globals.default_previewer end,
prompt = 'Rg> ',
input_prompt = 'Grep For> ',
cmd = nil, -- default: auto detect rg|grep
@ -196,6 +218,7 @@ M.globals.grep = {
},
}
M.globals.oldfiles = {
previewer = function() return M.globals.default_previewer end,
prompt = 'History> ',
file_icons = true and M._has_devicons,
color_icons = true,
@ -211,6 +234,7 @@ M.globals.oldfiles = {
},
}
M.globals.quickfix = {
previewer = function() return M.globals.default_previewer end,
prompt = 'Quickfix> ',
separator = '',
file_icons = true and M._has_devicons,
@ -227,6 +251,7 @@ M.globals.quickfix = {
},
}
M.globals.loclist = {
previewer = function() return M.globals.default_previewer end,
prompt = 'Locations> ',
separator = '',
file_icons = true and M._has_devicons,
@ -243,6 +268,7 @@ M.globals.loclist = {
},
}
M.globals.buffers = {
previewer = "builtin",
prompt = 'Buffers> ',
file_icons = true and M._has_devicons,
color_icons = true,
@ -259,6 +285,7 @@ M.globals.buffers = {
},
}
M.globals.tags = {
previewer = function() return M.globals.default_previewer end,
prompt = 'Tags> ',
ctags_file = "tags",
file_icons = true and M._has_devicons,
@ -273,6 +300,7 @@ M.globals.tags = {
},
}
M.globals.btags = {
previewer = function() return M.globals.default_previewer end,
prompt = 'BTags> ',
ctags_file = "tags",
file_icons = true and M._has_devicons,
@ -317,6 +345,7 @@ M.globals.manpages = {
},
}
M.globals.lsp = {
previewer = function() return M.globals.default_previewer end,
prompt = '> ',
file_icons = true and M._has_devicons,
color_icons = true,
@ -413,47 +442,6 @@ M.globals.file_icon_colors = {
["desktop"] = "magenta",
}
M.winopts = function(opts)
if not opts then opts = {} end
if not opts.winopts then opts.winopts = {} end
opts.winopts = vim.tbl_deep_extend("keep", opts.winopts, M.globals.winopts)
opts.winopts_raw = opts.winopts_raw or M.globals.winopts_raw
local raw = {}
if opts.winopts_raw and type(opts.winopts_raw) == "function" then
raw = opts.winopts_raw()
end
local winopts = opts.winopts
local height = raw.height or math.floor(vim.o.lines * winopts.win_height)
local width = raw.width or math.floor(vim.o.columns * winopts.win_width)
local row = raw.row or math.floor((vim.o.lines - height) * winopts.win_row)
local col = raw.col or math.floor((vim.o.columns - width) * winopts.win_col)
return {
-- style = 'minimal',
height = height, width = width, row = row, col = col,
border = raw.border or winopts.win_border,
window_on_create = raw.window_on_create or winopts.window_on_create
}
end
M.preview_window = function(opts)
local o = vim.tbl_deep_extend("keep", opts, M.globals)
local preview_veritcal = string.format('%s:%s:%s:%s',
o.preview_opts, o.preview_border, o.preview_wrap, o.preview_vertical)
local preview_horizontal = string.format('%s:%s:%s:%s',
o.preview_opts, o.preview_border, o.preview_wrap, o.preview_horizontal)
if o.preview_layout == "vertical" then
return preview_veritcal
elseif o.preview_layout == "flex" then
return utils._if(vim.o.columns>o.flip_columns, preview_horizontal, preview_veritcal)
else
return preview_horizontal
end
end
function M.normalize_opts(opts, defaults)
if not opts then opts = {} end
opts = vim.tbl_deep_extend("keep", opts, defaults)
@ -461,8 +449,10 @@ function M.normalize_opts(opts, defaults)
if not opts.winopts then opts.winopts = {} end
opts.winopts = vim.tbl_deep_extend("keep", opts.winopts, defaults.winopts)
end
if not opts.previewer or not M.globals.previewers[opts.previewer] then
opts.previewer = M.globals.default_previewer
if type(opts.previewer) == 'function' then
-- we use a function so the user can override
-- globals.default_previewer
opts.previewer = opts.previewer()
end
return opts
end

@ -3,25 +3,37 @@ local path = require "fzf-lua.path"
local utils = require "fzf-lua.utils"
local config = require "fzf-lua.config"
local actions = require "fzf-lua.actions"
local win = require "fzf-lua.win"
local M = {}
M.fzf = function(o, contents, fzf_cli_args, options)
if o.winopts and o.winopts.split then
vim.cmd(o.winopts.split)
local bufnr = vim.api.nvim_get_current_buf()
local winid = vim.api.nvim_get_current_win()
local selected = fzf.raw_fzf(contents, fzf_cli_args, options)
if vim.api.nvim_win_is_valid(winid) then
vim.api.nvim_win_close(winid, {force=true})
end
if vim.api.nvim_buf_is_valid(bufnr) then
vim.api.nvim_buf_delete(bufnr, {force=true})
M.fzf = function(opts, contents, previewer)
-- setup the fzf window and preview layout
local fzf_win = win(opts)
-- instantiate the previewer
-- if not opts.preview and not previewer and
if not previewer and
opts.previewer and type(opts.previewer) == 'string' then
local preview_opts = config.globals.previewers[opts.previewer]
if preview_opts then
previewer = preview_opts._new()(preview_opts, opts, fzf_win)
opts.preview = previewer:cmdline()
if type(previewer.override_fzf_preview_window) == 'function' then
-- do we need to override the preview_window args?
-- this can happen with the builtin previewer
-- (1) when using a split we use the previewer as placeholder
-- (2) we use 'right:0' to call the previewer function only
if previewer:override_fzf_preview_window() then
opts.preview_window = previewer:preview_window()
end
end
end
return selected
else
return fzf.fzf(contents, fzf_cli_args, options)
end
fzf_win:attach_previewer(previewer)
fzf_win:create()
local selected = fzf.raw_fzf(contents, M.build_fzf_cli(opts))
fzf_win:close()
return selected
end
M.get_devicon = function(file, ext)
@ -34,6 +46,21 @@ M.get_devicon = function(file, ext)
return icon
end
M.preview_window = function(opts)
local o = vim.tbl_deep_extend("keep", opts, config.globals)
local preview_vertical = string.format('%s:%s:%s:%s',
o.preview_opts, o.preview_border, o.preview_wrap, o.preview_vertical)
local preview_horizontal = string.format('%s:%s:%s:%s',
o.preview_opts, o.preview_border, o.preview_wrap, o.preview_horizontal)
if o.preview_layout == "vertical" then
return preview_vertical
elseif o.preview_layout == "flex" then
return utils._if(vim.o.columns>o.flip_columns, preview_horizontal, preview_vertical)
else
return preview_horizontal
end
end
M.build_fzf_cli = function(opts, debug_print)
opts.prompt = opts.prompt or config.globals.default_prompt
opts.preview_offset = opts.preview_offset or ''
@ -48,7 +75,7 @@ M.build_fzf_cli = function(opts, debug_print)
utils._if(opts.fzf_binds, opts.fzf_binds,
vim.fn.shellescape(table.concat(config.globals.fzf_binds, ','))),
vim.fn.shellescape(opts.prompt),
utils._if(opts.preview_window, opts.preview_window, config.preview_window(opts)),
utils._if(opts.preview_window, opts.preview_window, M.preview_window(opts)),
utils._if(#opts.preview_offset>0, ":"..opts.preview_offset, ''),
utils._if(opts.preview and #opts.preview>0, opts.preview, "''"),
-- HACK: support skim (rust version of fzf)
@ -195,17 +222,7 @@ M.fzf_files = function(opts)
end
if not opts.preview then
local preview_opts = config.globals.previewers[opts.previewer]
if preview_opts then
local preview = preview_opts._new()(preview_opts, opts)
opts.preview = preview:cmdline()
end
end
local selected = M.fzf(opts, opts.fzf_fn,
M.build_fzf_cli(opts),
config.winopts(opts))
local selected = M.fzf(opts, opts.fzf_fn)
if opts.post_select_cb then
opts.post_select_cb()

@ -3,6 +3,7 @@ if not pcall(require, "fzf") then
end
local fzf = require "fzf"
local utils = require "fzf-lua.utils"
local config = require "fzf-lua.config"
@ -14,6 +15,12 @@ function M.setup(opts)
for k, _ in pairs(globals.winopts) do
if opts[k] ~= nil then globals.winopts[k] = opts[k] end
end
-- deprecate message for window_on_create
if globals.winopts.window_on_create then
utils.warn(
"setting highlights using 'window_on_create' is " ..
"deprecated, use 'winopts.hl_xxx' instead.")
end
-- override BAT_CONFIG_PATH to prevent a
-- conflct with '$XDG_DATA_HOME/bat/config'
if globals.previewers.bat.config then
@ -23,8 +30,6 @@ function M.setup(opts)
if globals.previewers.bat.theme and #globals.previewers.bat.theme > 0 then
vim.env.BAT_THEME = globals.previewers.bat.theme
end
-- reset default window opts if set by user
fzf.default_window_options = config.winopts()
-- set the fzf binary if set by the user
if globals.fzf_bin ~= nil and vim.fn.executable(globals.fzf_bin) ~= 1 then
globals.fzf_bin = nil
@ -42,10 +47,6 @@ function M.setup(opts)
-- _G.dump(config.globals)
end
-- we usually send winopts with every fzf.fzf call
-- but set default window options just in case
fzf.default_window_options = config.winopts()
M.fzf_files = require'fzf-lua.core'.fzf_files
M.files = require'fzf-lua.providers.files'.files
M.grep = require'fzf-lua.providers.grep'.grep

@ -134,6 +134,8 @@ function M.entry_to_file(entry, cwd)
local sep = ":"
local s = strsplit(entry, sep)
local file = s[1]:match("[^"..utils.nbsp.."]*$")
-- entries from 'buffers'
local bufnr = s[1]:match("%[(%d+)")
local idx = lastIndexOf(s[1], utils.nbsp) or 0
local noicons = string.sub(entry, idx+1)
local line = s[2]
@ -143,6 +145,7 @@ function M.entry_to_file(entry, cwd)
noicons = M.join({cwd, noicons})
end
return {
bufnr = bufnr,
noicons = noicons,
path = file,
line = line or 1,

@ -0,0 +1,374 @@
local path = require "fzf-lua.path"
local utils = require "fzf-lua.utils"
local previewer_base = require "fzf-lua.previewer".base
local raw_action = require("fzf.actions").raw_action
local api = vim.api
local fn = vim.fn
local cmd = vim.cmd
local Previewer = {}
-- signgleton instance used for our keymappings
local _self = nil
setmetatable(Previewer, {
__call = function (cls, ...)
return cls:new(...)
end,
})
function Previewer:setup_keybinds()
if not self.win or not self.win.fzf_bufnr then return end
local keymap_tbl = {
toggle_full = { module = 'previewer.builtin', fnc = 'toggle_full()' },
toggle_wrap = { module = 'previewer.builtin', fnc = 'toggle_wrap()' },
toggle_hide = { module = 'previewer.builtin', fnc = 'toggle_hide()' },
page_up = { module = 'previewer.builtin', fnc = 'scroll(-1)' },
page_down = { module = 'previewer.builtin', fnc = 'scroll(1)' },
page_reset = { module = 'previewer.builtin', fnc = 'scroll(0)' },
}
local function funcref_str(keymap)
return ([[<Cmd>lua require('fzf-lua.%s').%s<CR>]]):format(keymap.module, keymap.fnc)
end
for action, key in pairs(self.keymap) do
local keymap = keymap_tbl[action]
if keymap and not vim.tbl_isempty(keymap) and key ~= false then
api.nvim_buf_set_keymap(self.win.fzf_bufnr, 't', key,
funcref_str(keymap), {nowait = true, noremap = true})
end
end
end
function Previewer:new(o, opts, fzf_win)
self = setmetatable(previewer_base(o, opts), {
__index = vim.tbl_deep_extend("keep",
self, previewer_base
)})
self.type = "builtin"
self.win = fzf_win
self.wrap = o.wrap
self.title = o.title
self.scrollbar = o.scrollbar
if o.scrollchar then
self.win.winopts.scrollchar = o.scrollchar
end
self.fullscreen = o.fullscreen
self.syntax = o.syntax
self.syntax_delay = o.syntax_delay
self.hl_cursor = o.hl_cursor
self.hl_range = o.hl_range
self.keymap = o.keymap
self.backups = {}
_self = self
return self
end
function Previewer:close()
-- restore winopts backup for those that weren't restored
-- (usually the last previewed loaded buffer)
for bufnr, _ in pairs(self.backups) do
self:restore_winopts(bufnr, self.win.preview_winid)
end
self:clear_preview_buf()
self.backups = {}
_self = nil
end
function Previewer:update_border(entry)
if self.title then
local title = (' %s '):format(entry.path)
if entry.bufnr then
-- local border_width = api.nvim_win_get_width(self.win.preview_winid)
local buf_str = ('buf %d:'):format(entry.bufnr)
title = (' %s %s '):format(buf_str, entry.path)
end
self.win:update_title(title)
end
if self.scrollbar then
self.win:update_scrollbar()
end
end
function Previewer:gen_winopts()
return {
wrap = self.wrap,
number = true,
relativenumber = false,
cursorline = true,
cursorcolumn = false,
signcolumn = 'no',
foldenable = false,
foldmethod = 'manual',
}
end
function Previewer:backup_winopts(key, win)
if not key then return end
if not win or not api.nvim_win_is_valid(win) then return end
self.backups[key] = {}
for opt, _ in pairs(self:gen_winopts()) do
self.backups[key][opt] = api.nvim_win_get_option(win, opt)
end
end
function Previewer:restore_winopts(key, win)
if not self.backups[key] then return end
if not win or not api.nvim_win_is_valid(win) then return end
for opt, v in pairs(self.backups[key]) do
api.nvim_win_set_option(win, opt, v)
end
self.backups[key] = nil
end
function Previewer:set_winopts(win)
if not win or not api.nvim_win_is_valid(win) then return end
for opt, v in pairs(self:gen_winopts()) do
api.nvim_win_set_option(win, opt, v)
--[[ api.nvim_win_call(win, function()
api.nvim_win_set_option(0, opt, v)
end) ]]
end
end
local function set_cursor_hl(self, entry)
local lnum, col = tonumber(entry.line), tonumber(entry.col)
local pattern = entry.pattern or entry.text
if not lnum or lnum < 1 then
api.nvim_win_set_cursor(0, {1, 0})
if pattern ~= '' then
fn.search(pattern, 'c')
end
else
if not pcall(api.nvim_win_set_cursor, 0, {lnum, math.max(0, col - 1)}) then
return
end
end
utils.zz()
self.orig_pos = api.nvim_win_get_cursor(0)
fn.clearmatches()
if lnum and lnum > 0 and col and col > 1 then
fn.matchaddpos(self.hl_cursor, {{lnum, math.max(1, col)}}, 11)
end
cmd(('noa call nvim_set_current_win(%d)'):format(self.win.preview_winid))
end
function Previewer:do_syntax(entry)
if not self.preview_bufnr then return end
local bufnr = self.preview_bufnr
local preview_winid = self.win.preview_winid
if self.preview_bufloaded and vim.bo[bufnr].filetype == '' then
if fn.bufwinid(bufnr) == preview_winid then
-- do not enable for lage files, treesitter still has perf issues:
-- https://github.com/nvim-treesitter/nvim-treesitter/issues/556
-- https://github.com/nvim-treesitter/nvim-treesitter/issues/898
local lcount = api.nvim_buf_line_count(bufnr)
local bytes = api.nvim_buf_get_offset(bufnr, lcount)
if bytes / lcount < 1000 then
-- nvim_buf_call is less side-effects than changing window
-- make sure that buffer in preview window must not in normal window
local ext = path.extension(entry.path)
api.nvim_buf_call(bufnr, function()
if ext then vim.cmd('set ft=' .. ext) end
vim.cmd('filetype detect')
end)
end
end
end
end
function Previewer:set_tmp_buffer()
if not self.win or not self.win:validate_preview() then return end
local tmp_buf = api.nvim_create_buf(false, true)
api.nvim_buf_set_option(tmp_buf, 'bufhidden', 'wipe')
api.nvim_win_set_buf(self.win.preview_winid, tmp_buf)
return tmp_buf
end
function Previewer:clear_preview_buf()
local retbuf = nil
if self.win and self.win:validate_preview() then
-- attach a temp buffer to the window
-- so we can safely delete the buffer
-- ('nvim_buf_delete' removes the attached win)
retbuf = self:set_tmp_buffer()
end
if self.preview_bufloaded then
local bufnr = self.preview_bufnr
if vim.api.nvim_buf_is_valid(bufnr) then
api.nvim_buf_call(bufnr, function()
vim.cmd('delm \\"')
end)
vim.api.nvim_buf_delete(bufnr, {force=true})
end
end
self.preview_bufnr = nil
self.preview_bufloaded = nil
return retbuf
end
function Previewer:display_last_entry()
self:display_entry(self.last_entry)
end
function Previewer:preview_buf_post(entry)
-- backup window options
local bufnr = self.preview_bufnr
local preview_winid = self.win.preview_winid
self:backup_winopts(bufnr, preview_winid)
-- set preview win options or load the file
-- if not already loaded from buffer
utils.win_execute(preview_winid, function()
set_cursor_hl(self, entry)
end)
-- set preview window options
self:set_winopts(preview_winid)
-- reset the preview window highlights
self.win:reset_win_highlights(preview_winid)
-- local ml = vim.bo[entry.bufnr].ml
-- vim.bo[entry.bufnr].ml = false
if self.syntax then
vim.defer_fn(function()
self:do_syntax(entry)
-- vim.bo[entry.bufnr].ml = ml
end, self.syntax_delay)
end
self:update_border(entry)
end
function Previewer:display_entry(entry)
if not entry then return
else
-- save last entry even if we don't display
self.last_entry = entry
end
if not self.win or not self.win:validate_preview() then return end
local preview_winid = self.win.preview_winid
local previous_bufnr = api.nvim_win_get_buf(preview_winid)
assert(not self.preview_bufnr or previous_bufnr == self.preview_bufnr)
-- restore settings for the buffer we were previously viewing
self:restore_winopts(previous_bufnr, preview_winid)
-- clear the current preview buffer
local bufnr = self:clear_preview_buf()
-- store the preview buffer
self.preview_bufnr = bufnr
if entry.bufnr and api.nvim_buf_is_loaded(entry.bufnr) then
-- must convert to number or our backup will have conflicting keys
bufnr = tonumber(entry.bufnr)
-- display the buffer in the preview
api.nvim_win_set_buf(preview_winid, bufnr)
-- store current preview buffer
self.preview_bufnr = bufnr
self:preview_buf_post(entry)
else
-- mark the buffer for unloading the next call
self.preview_bufloaded = true
-- read the file into the buffer
utils.read_file_async(entry.path, vim.schedule_wrap(function(data)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
local ok = pcall(vim.api.nvim_buf_set_lines, bufnr, 0, -1, false, vim.split(data, "[\r]?\n"))
if not ok then
return
end
self:preview_buf_post(entry)
end))
end
end
function Previewer:action(_)
local act = raw_action(function (items, _, _)
local entry = path.entry_to_file(items[1], self.opts.cwd)
self:display_entry(entry)
return ""
end)
return act
end
function Previewer:cmdline(_)
return vim.fn.shellescape(self:action())
-- return 'true'
end
function Previewer:preview_window(_)
return 'nohidden:right:0'
end
function Previewer:override_fzf_preview_window()
return self.win and not self.win.winopts.split
end
function Previewer.scroll(direction)
if not _self then return end
local self = _self
local preview_winid = self.win.preview_winid
if preview_winid < 0 or not direction then
return
end
local fzf_winid = self.win.fzf_winid
utils.win_execute(preview_winid, function()
if direction == 0 then
api.nvim_win_set_cursor(preview_winid, self.orig_pos)
else
-- ^D = 0x04, ^U = 0x15
fn.execute(('norm! %c'):format(direction > 0 and 0x04 or 0x15))
end
utils.zz()
cmd(('noa call nvim_set_current_win(%d)'):format(fzf_winid))
end)
if self.scrollbar then
self.win:update_scrollbar()
end
end
function Previewer.toggle_wrap()
if not _self then return end
local self = _self
self.wrap = not self.wrap
if self.win and self.win:validate_preview() then
api.nvim_win_set_option(self.win.preview_winid, 'wrap', self.wrap)
end
end
function Previewer.toggle_full()
if not _self then return end
local self = _self
self.fullscreen = not self.fullscreen
if self.win and self.win:validate_preview() then
self.win:redraw_preview()
end
end
function Previewer.toggle_hide()
if not _self then return end
local self = _self
if self.win then
if self.win:validate_preview() then
self.win:close_preview()
else
self.win:redraw_preview()
self:display_last_entry()
end
end
-- close_preview() calls Previewer:close()
-- which will clear out our singleton so
-- we must save it again to call redraw
_self = self
end
return Previewer

@ -17,7 +17,9 @@ local function getbufnumber(line)
end
local function getfilename(line)
return string.match(line, "%[.*%] (.+)")
-- return string.match(line, "%[.*%] (.+)")
-- greedy match anything after last nbsp
return line:match("[^" .. utils.nbsp .. "]*$")
end
M.buffers = function(opts)
@ -102,7 +104,7 @@ M.buffers = function(opts)
elseif buf.flag == '#' then
flags = utils.ansi_codes.cyan(buf.flag) .. flags
else
flags = " " .. flags
flags = utils.nbsp .. flags
end
local bufnrstr = string.format("%s%s%s", leftbr,
utils.ansi_codes.yellow(string.format(buf.bufnr)), rightbr)
@ -111,12 +113,19 @@ M.buffers = function(opts)
local extension = path.extension(buf.info.name)
buficon = core.get_devicon(buf.info.name, extension)
if opts.color_icons then
buficon = utils.ansi_codes[config.globals.file_icon_colors[extension] or "dark_grey"](buficon) .. " "
buficon = utils.ansi_codes[config.globals.file_icon_colors[extension] or "dark_grey"](buficon)
end
end
local item_str = string.format("%s%s %s %s%s",
utils._if(buf.bufnr>9, '' , ' '),
bufnrstr, flags, buficon, bufname)
local item_str = string.format("%s%s%s%s%s%s%s",
utils._if(header_line and vim.tbl_isempty(items),
string.format("%-16s", bufnrstr),
string.format("%-32s", bufnrstr)),
utils.nbsp,
flags,
utils.nbsp,
buficon,
utils.nbsp,
bufname)
table.insert(items, item_str)
end
@ -126,9 +135,7 @@ M.buffers = function(opts)
'--header-lines=1', ''
)
local selected = require("fzf").fzf(items,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, items)
if not selected then return end

@ -40,9 +40,7 @@ M.colorschemes = function(opts)
opts.preview_window = opts.preview_window or 'nohidden:right:0'
opts.nomulti = utils._if(opts.nomulti~=nil, opts.nomulti, true)
local selected = core.fzf(opts, colors,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, colors)
-- reset color scheme if live_preview is enabled
-- and nothing or non-default action was selected

@ -55,9 +55,7 @@ local function git_cmd(opts)
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,
core.build_fzf_cli(opts, false),
config.winopts(opts))
local selected = core.fzf(opts, opts.fzf_fn)
if not selected then return end
actions.act(opts.actions, selected)
end)()

@ -107,9 +107,7 @@ M.helptags = function(opts)
opts.preview_window = opts.preview_window or 'right:0'
opts.nomulti = utils._if(opts.nomulti~=nil, opts.nomulti, true)
local selected = core.fzf(opts, fzf_function,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, fzf_function)
if not selected then return end

@ -296,6 +296,7 @@ M.code_actions = function(opts)
end)
opts.nomulti = true
opts.previewer = false
opts.preview_window = 'right:0'
opts._fzf_cli_args = "--delimiter=':'"
opts = set_lsp_fzf_fn(opts)
@ -305,9 +306,7 @@ M.code_actions = function(opts)
coroutine.wrap(function ()
local selected = core.fzf(opts, opts.fzf_fn,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, opts.fzf_fn)
if opts.post_select_cb then
opts.post_select_cb()

@ -44,9 +44,7 @@ M.manpages = function(opts)
opts.preview_window = opts.preview_window or 'right:0'
opts.nomulti = utils._if(opts.nomulti~=nil, opts.nomulti, true)
local selected = core.fzf(opts, fzf_fn,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, fzf_fn)
if not selected then return end

@ -36,9 +36,7 @@ M.metatable = function(opts)
opts.preview_window = 'hidden:down:10'
opts.nomulti = true
local selected = core.fzf(opts, methods,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, methods)
if not selected then return end

@ -36,9 +36,7 @@ M.commands = function(opts)
opts.nomulti = true
opts.preview = prev_act
local selected = core.fzf(opts, entries,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, entries)
if not selected then return end
actions.act(opts.actions, selected)
@ -64,9 +62,7 @@ local history = function(opts, str)
opts.preview = nil
opts.preview_window = 'hidden:down:0'
local selected = core.fzf(opts, entries,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, entries)
if not selected then return end
actions.act(opts.actions, selected)
@ -121,9 +117,7 @@ M.marks = function(opts)
opts.preview = prev_act
-- opts.preview_window = 'hidden:down:0'
local selected = core.fzf(opts, entries,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, entries)
if not selected then return end
actions.act(opts.actions, selected)
@ -166,9 +160,7 @@ M.registers = function(opts)
opts.nomulti = true
opts.preview = prev_act
local selected = core.fzf(opts, entries,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, entries)
if not selected then return end
actions.act(opts.actions, selected)
@ -227,9 +219,7 @@ M.keymaps = function(opts)
opts.nomulti = true
opts.preview = prev_act
local selected = core.fzf(opts, entries,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, entries)
if not selected then return end
actions.act(opts.actions, selected)
@ -253,9 +243,7 @@ M.spell_suggest = function(opts)
opts.preview = nil
opts.preview_window = 'hidden:down:0'
local selected = core.fzf(opts, entries,
core.build_fzf_cli(opts),
config.winopts(opts))
local selected = core.fzf(opts, entries)
if not selected then return end
actions.act(opts.actions, selected)

@ -21,6 +21,14 @@ M._if = function(bool, a, b)
end
end
function M.round(num, limit)
if not num then return nil end
if not limit then limit = 0.5 end
local fraction = num - math.floor(num)
if fraction > limit then return math.ceil(num) end
return math.floor(num)
end
function M._echo_multiline(msg)
for _, s in ipairs(vim.fn.split(msg, "\n")) do
vim.cmd("echom '" .. s:gsub("'", "''").."'")
@ -178,6 +186,7 @@ function M.get_visual_selection()
-- :visual leaves ex-mode back to normal mode
-- use 'gv' to reselect the text
vim.cmd[[visual]]
-- M.feed_keys_termcodes("<CR>")
local _, csrow, cscol, _ = unpack(vim.fn.getpos("'<"))
local _, cerow, cecol, _ = unpack(vim.fn.getpos("'>"))
local lines = vim.fn.getline(csrow, cerow)
@ -210,4 +219,46 @@ function M.delayed_cb(cb, fn)
end, 20)
end
function M.zz()
local lnum1 = vim.api.nvim_win_get_cursor(0)[1]
local lcount = vim.api.nvim_buf_line_count(0)
local zb = 'keepj norm! %dzb'
if lnum1 == lcount then
vim.fn.execute(zb:format(lnum1))
return
end
vim.cmd('norm! zvzz')
lnum1 = vim.api.nvim_win_get_cursor(0)[1]
vim.cmd('norm! L')
local lnum2 = vim.api.nvim_win_get_cursor(0)[1]
if lnum2 + vim.fn.getwinvar(0, '&scrolloff') >= lcount then
vim.fn.execute(zb:format(lnum2))
end
if lnum1 ~= lnum2 then
vim.cmd('keepj norm! ``')
end
end
function M.win_execute(winid, func)
vim.validate({
winid = {
winid, function(w)
return w and vim.api.nvim_win_is_valid(w)
end, 'a valid window'
},
func = {func, 'function'}
})
local cur_winid = vim.api.nvim_get_current_win()
local noa_set_win = 'noa call nvim_set_current_win(%d)'
if cur_winid ~= winid then
vim.cmd(noa_set_win:format(winid))
end
local ret = func()
if cur_winid ~= winid then
vim.cmd(noa_set_win:format(cur_winid))
end
return ret
end
return M

@ -0,0 +1,475 @@
local utils = require "fzf-lua.utils"
local config = require "fzf-lua.config"
local api = vim.api
local fn = vim.fn
local FzfWin = {}
setmetatable(FzfWin, {
__call = function (cls, ...)
return cls:new(...)
end,
})
local generate_layout = function(winopts)
local row, col = winopts.row, winopts.col
local height, width = winopts.height, winopts.width
local preview_pos = winopts.preview_pos
local preview_size = winopts.preview_size
local prev_row, prev_col = row, col
local prev_height, prev_width
local padding = 2
local anchor
local vert_split = winopts.split and winopts.split:match("vnew") ~= nil
if preview_pos == 'down' or preview_pos == 'up' then
height = height - padding
prev_width = width
prev_height = utils.round(height * preview_size/100, 0.6)
height = height - prev_height
if preview_pos == 'up' then
row = row + prev_height + padding
if winopts.split then
anchor = 'NW'
prev_row = 1
prev_height = prev_height - 1
if vert_split then
prev_col = 1
end
else
anchor = 'SW'
prev_row = row - padding
end
else
anchor = 'NW'
if winopts.split then
prev_col = 1
prev_row = height + padding
prev_height = prev_height - 1
else
prev_row = row + height + padding
end
end
elseif preview_pos == 'left' or preview_pos == 'right' then
prev_height = height
prev_width = utils.round(width * preview_size/100)
width = width - prev_width
if preview_pos == 'left' then
anchor = 'NE'
col = col + prev_width
prev_col = col - padding
if winopts.split then
prev_row = 1
prev_height = prev_height - padding
if vert_split then
anchor = 'NW'
prev_col = 1
prev_width = prev_width + 1
else
prev_width = prev_width - 1
end
end
else
anchor = 'NW'
if winopts.split then
prev_row = 1
prev_height = prev_height - padding
if vert_split then
prev_col = width + 2
prev_width = prev_width - 1
else
prev_col = width + 3
prev_width = prev_width - padding
end
else
prev_col = col + width + padding
end
end
end
return {
fzf = {
row = row, col = col,
height = height, width = width,
},
preview = {
anchor = anchor,
row = prev_row, col = prev_col,
height = prev_height, width = prev_width,
}
}
end
local normalize_winopts = function(opts)
if not opts then opts = {} end
if not opts.winopts then opts.winopts = {} end
opts = vim.tbl_deep_extend("keep", opts, config.globals)
opts.winopts = vim.tbl_deep_extend("keep", opts.winopts, config.globals.winopts)
opts.winopts_raw = opts.winopts_raw or config.globals.winopts_raw
local raw = {}
if opts.winopts_raw and type(opts.winopts_raw) == "function" then
raw = opts.winopts_raw()
end
local winopts = opts.winopts
local height = raw.height or math.floor(vim.o.lines * winopts.win_height)
local width = raw.width or math.floor(vim.o.columns * winopts.win_width)
local row = raw.row or math.floor((vim.o.lines - height) * winopts.win_row)
local col = raw.col or math.floor((vim.o.columns - width) * winopts.win_col)
local border = raw.border or winopts.win_border
local scrollchar = raw.scrollchar or winopts.scrollchar
local hl_normal = raw.hl_normal or winopts.hl_normal
local hl_border = raw.hl_border or winopts.hl_border
-- normalize border option for nvim_open_win()
if border == false then
border = "none"
elseif border == true or border == nil then
border = config.globals.winopts.borderchars
end
-- did user supply the scroll char at 9th slot?
if type(border) == 'table' and #border == 9 then
if not scrollchar then scrollchar = border[9] end
border[9] = nil
end
-- parse preview options
local preview = opts.preview_horizontal
if opts.preview_layout == "vertical" then
preview = opts.preview_vertical
elseif opts.preview_layout == "flex" then
preview = utils._if(vim.o.columns>opts.flip_columns, opts.preview_horizontal, opts.preview_vertical)
end
-- builtin previewer params
local prev_pos = preview:match("[^:]+") or 'right'
local prev_size = tonumber(preview:match(":(%d+)%%")) or 50
return {
height = height, width = width, row = row, col = col, border = border,
window_on_create = raw.window_on_create or winopts.window_on_create,
split = raw.split or winopts.split,
hl_normal = hl_normal, hl_border = hl_border,
-- builtin previewer params
scrollchar = scrollchar or '',
preview_pos = prev_pos, preview_size = prev_size,
}
end
function FzfWin:reset_win_highlights(win, is_border)
local hl = ("Normal:%s,FloatBorder:%s"):format(
self.winopts.hl_normal, self.winopts.hl_border)
if is_border then
-- our border is manuually drawn so we need
-- to replace Normal with the border color
hl = ("Normal:%s"):format(self.winopts.hl_border)
end
vim.api.nvim_win_set_option(win, 'winhighlight', hl)
--[[ if self.winopts.window_on_create then
utils.win_execute(win, function()
self.winopts.window_on_create()
end)
end ]]
end
function FzfWin:new(o)
o = o or {}
self = setmetatable({}, { __index = self })
self.winopts = normalize_winopts(o)
self.previewer = o.previewer
self.previewer_type = o.previewer_type
if self.previewer_type == 'builtin' or self.previewer == 'builtin' then
self.previewer_is_builtin = true
end
if not self.winopts.split and self.previewer_is_builtin then
self.layout = generate_layout(self.winopts)
end
return self
end
function FzfWin:attach_previewer(previewer)
self._previewer = previewer
end
function FzfWin:fs_preview_layout(fs)
local prev_winopts = self.prev_winopts
local border_winopts = self.border_winopts
if not fs or self.winopts.split
or not prev_winopts or not border_winopts
or vim.tbl_isempty(prev_winopts)
or vim.tbl_isempty(border_winopts) then
return prev_winopts, border_winopts
end
local preview_pos = self.winopts.preview_pos
local height_diff = 0
local width_diff = 0
if preview_pos == 'down' or preview_pos == 'up'then
width_diff = vim.o.columns - border_winopts.width
if preview_pos == 'down' then
height_diff = vim.o.lines - border_winopts.row - border_winopts.height - 3
elseif preview_pos == 'up' then
height_diff = border_winopts.row - border_winopts.height + 1
end
prev_winopts.col = prev_winopts.col - width_diff/2
border_winopts.col = border_winopts.col - width_diff/2
elseif preview_pos == 'left' or preview_pos == 'right'then
height_diff = vim.o.lines - border_winopts.height - 2
if preview_pos == 'left' then
width_diff = border_winopts.col - border_winopts.width + 1
elseif preview_pos == 'right' then
width_diff = vim.o.columns - border_winopts.col - border_winopts.width - 1
end
prev_winopts.row = prev_winopts.row - height_diff/2 - 1
border_winopts.row = border_winopts.row - height_diff/2 - 1
end
prev_winopts.height = prev_winopts.height + height_diff
border_winopts.height = border_winopts.height + height_diff
prev_winopts.width = prev_winopts.width + width_diff
border_winopts.width = border_winopts.width + width_diff
return prev_winopts, border_winopts
end
function FzfWin:preview_layout()
if self.winopts.split and self.previewer_is_builtin then
local wininfo = fn.getwininfo(self.fzf_winid)[1]
self.layout = generate_layout({
row = wininfo.winrow,
col = wininfo.wincol,
height = wininfo.height,
width = api.nvim_win_get_width(self.fzf_winid),
preview_pos = self.winopts.preview_pos,
preview_size = self.winopts.preview_size,
split = self.winopts.split,
})
end
if not self.layout then return {}, {} end
local anchor = self.layout.preview.anchor
local row, col = self.layout.preview.row, self.layout.preview.col
local width, height = self.layout.preview.width, self.layout.preview.height
if not anchor or not width or width < 1 or not height or height < 1 then
return {}, {}
end
local winopts = {relative = 'win', win = self.fzf_winid, focusable = false, style = 'minimal'}
if self.winopts.split then
width = width - 2
end
local preview_opts = vim.tbl_extend('force', winopts, {
anchor = anchor,
width = width,
height = height,
col = col,
row = row
})
local border_winopts = vim.tbl_extend('force', winopts, {
anchor = anchor,
width = width + 2,
height = height + 2,
col = anchor:match('W') and col - 1 or col + 1,
row = anchor:match('N') and row - 1 or row + 1
})
return preview_opts, border_winopts
end
function FzfWin:validate_preview()
return self.preview_winid and self.preview_winid > 0
and api.nvim_win_is_valid(self.preview_winid)
and self.border_winid and self.border_winid > 0
and api.nvim_win_is_valid(self.border_winid)
end
function FzfWin:preview_winids()
return self.preview_winid, self.border_winid
end
function FzfWin:update_border_buf()
local border_buf = self.border_buf
local border_winopts = self.border_winopts
local border_chars = self.winopts.border
local width, height = border_winopts.width, border_winopts.height
local top = border_chars[1] .. border_chars[2]:rep(width - 2) .. border_chars[3]
local mid = border_chars[8] .. (' '):rep(width - 2) .. border_chars[4]
local bot = border_chars[7] .. border_chars[6]:rep(width - 2) .. border_chars[5]
local lines = {top}
for _ = 1, height - 2 do
table.insert(lines, mid)
end
table.insert(lines, bot)
if not border_buf then
border_buf = api.nvim_create_buf(false, true)
-- run nvim with `-M` will reset modifiable's default value to false
vim.bo[border_buf].modifiable = true
vim.bo[border_buf].bufhidden = 'wipe'
end
api.nvim_buf_set_lines(border_buf, 0, -1, 1, lines)
return border_buf
end
function FzfWin:redraw_preview()
self.prev_winopts, self.border_winopts = self:preview_layout()
if vim.tbl_isempty(self.prev_winopts) or vim.tbl_isempty(self.border_winopts) then
return -1, -1
end
-- fullscreen preview only if set by the previewer
if self._previewer and self._previewer.fullscreen then
self.prev_winopts, self.border_winopts =
self:fs_preview_layout(self._previewer.fullscreen)
end
if self:validate_preview() then
self.border_buf = api.nvim_win_get_buf(self.border_winid)
self:update_border_buf()
api.nvim_win_set_config(self.border_winid, self.border_winopts)
api.nvim_win_set_config(self.preview_winid, self.prev_winopts)
if self._previewer and self._previewer.set_winopts then
self._previewer:set_winopts(self.preview_winid)
self._previewer:display_last_entry()
end
else
local tmp_buf = api.nvim_create_buf(false, true)
api.nvim_buf_set_option(tmp_buf, 'bufhidden', 'wipe')
self.border_buf = self:update_border_buf()
self.preview_winid = api.nvim_open_win(tmp_buf, false, self.prev_winopts)
self.border_winid = api.nvim_open_win(self.border_buf, false, self.border_winopts)
end
self:reset_win_highlights(self.border_winid, true)
self:reset_win_highlights(self.preview_winid)
return self.preview_winid, self.border_winid
end
function FzfWin:create()
-- save sending bufnr/winid
self.src_bufnr = vim.api.nvim_get_current_buf()
self.src_winid = vim.api.nvim_get_current_win()
if self.winopts.split then
vim.cmd(self.winopts.split)
self.fzf_bufnr = vim.api.nvim_get_current_buf()
self.fzf_winid = vim.api.nvim_get_current_win()
else
local relative = self.winopts.relative or 'editor'
local columns, lines = vim.o.columns, vim.o.lines
if relative == 'win' then
columns, lines = vim.api.nvim_win_get_width(0), vim.api.nvim_win_get_height(0)
end
local winopts = self.winopts
if self.layout then winopts = self.layout.fzf end
local win_opts = {
width = winopts.width or math.min(columns - 4, math.max(80, columns - 20)),
height = winopts.height or math.min(lines - 4, math.max(20, lines - 10)),
style = 'minimal',
relative = relative,
border = self.winopts.border
}
win_opts.row = winopts.row or math.floor(((lines - win_opts.height) / 2) - 1)
win_opts.col = winopts.col or math.floor((columns - win_opts.width) / 2)
self.fzf_bufnr = vim.api.nvim_create_buf(false, true)
self.fzf_winid = vim.api.nvim_open_win(self.fzf_bufnr, true, win_opts)
end
self:reset_win_highlights(self.fzf_winid)
if self.winopts.window_on_create then
self.winopts.window_on_create()
end
-- create or redraw the preview win
self:redraw_preview()
-- setup the keybinds for the builtin previewer
if self._previewer and self._previewer.setup_keybinds then
self._previewer:setup_keybinds()
end
return {
src_bufnr = self.src_bufnr,
src_winid = self.src_winid,
fzf_bufnr = self.fzf_bufnr,
fzf_winid = self.fzf_winid,
}
end
function FzfWin:close_preview()
if self._previewer and self._previewer.close then
self._previewer:close()
end
if not self:validate_preview() then return end
if vim.api.nvim_win_is_valid(self.border_winid) then
api.nvim_win_close(self.border_winid, true)
end
if vim.api.nvim_buf_is_valid(self.border_buf) then
vim.api.nvim_buf_delete(self.border_buf, {force=true})
end
if vim.api.nvim_win_is_valid(self.preview_winid) then
api.nvim_win_close(self.preview_winid, true)
end
self.border_buf = nil
self.border_winid = nil
self.preview_winid = nil
end
function FzfWin:close()
self:close_preview()
if vim.api.nvim_win_is_valid(self.fzf_winid) then
vim.api.nvim_win_close(self.fzf_winid, {force=true})
end
if vim.api.nvim_buf_is_valid(self.fzf_bufnr) then
vim.api.nvim_buf_delete(self.fzf_bufnr, {force=true})
end
if vim.api.nvim_win_is_valid(self.src_winid) then
vim.api.nvim_set_current_win(self.src_winid)
end
end
function FzfWin:update_scrollbar()
local border_winid = self.border_winid
local preview_winid = self.preview_winid
local border_chars = self.winopts.border
local buf = api.nvim_win_get_buf(preview_winid)
local border_buf = api.nvim_win_get_buf(border_winid)
local line_count = api.nvim_buf_line_count(buf)
local win_info = fn.getwininfo(preview_winid)[1]
local topline, height = win_info.topline, win_info.height
local bar_size = math.min(height, math.ceil(height * height / line_count))
local bar_pos = math.ceil(height * topline / line_count)
if bar_pos + bar_size > height then
bar_pos = height - bar_size + 1
end
local lines = api.nvim_buf_get_lines(border_buf, 1, -2, true)
for i = 1, #lines do
local bar_char
if i >= bar_pos and i < bar_pos + bar_size then
bar_char = self.winopts.scrollchar
else
bar_char = border_chars[4]
end
local line = lines[i]
lines[i] = fn.strcharpart(line, 0, fn.strwidth(line) - 1) .. bar_char
end
api.nvim_buf_set_lines(border_buf, 1, -2, 0, lines)
end
function FzfWin:update_title(title)
self:update_border_buf()
local border_buf = api.nvim_win_get_buf(self.border_winid)
local top = api.nvim_buf_get_lines(border_buf, 0, 1, 0)[1]
local prefix = fn.strcharpart(top, 0, 3)
local suffix = fn.strcharpart(top, fn.strwidth(title) + 3, fn.strwidth(top))
title = ('%s%s%s'):format(prefix, title, suffix)
api.nvim_buf_set_lines(border_buf, 0, 1, 1, {title})
end
return FzfWin
Loading…
Cancel
Save