From e3546e82728da41fc2ecdaf91c173e81e716de68 Mon Sep 17 00:00:00 2001 From: bhagwan Date: Fri, 14 Jan 2022 21:45:57 -0800 Subject: [PATCH] new feature: press F1 for keybind help (#294) --- README.md | 7 ++- doc/fzf-lua.txt | 6 ++ lua/fzf-lua/config.lua | 52 ++++++++++++++++ lua/fzf-lua/win.lua | 138 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c7d69b0..f8dedf7 100644 --- a/README.md +++ b/README.md @@ -296,6 +296,7 @@ require'fzf-lua'.setup { -- delete or modify is sufficient builtin = { -- neovim `:tmap` mappings for the fzf win + [""] = "toggle-help", [""] = "toggle-fullscreen", -- Only valid with the 'builtin' previewer [""] = "toggle-preview-wrap", @@ -422,8 +423,8 @@ require'fzf-lua'.setup { 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 + -- 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 = { @@ -474,6 +475,8 @@ require'fzf-lua'.setup { ["M"] = { icon = "M", color = "yellow" }, ["D"] = { icon = "D", color = "red" }, ["A"] = { icon = "A", color = "green" }, + ["R"] = { icon = "R", color = "yellow" }, + ["C"] = { icon = "C", color = "yellow" }, ["?"] = { icon = "?", color = "magenta" }, -- override git icons? -- ["M"] = { icon = "★", color = "red" }, diff --git a/doc/fzf-lua.txt b/doc/fzf-lua.txt index 97e5c7a..1dc86d7 100644 --- a/doc/fzf-lua.txt +++ b/doc/fzf-lua.txt @@ -334,6 +334,7 @@ Consult the list below for available settings: -- delete or modify is sufficient builtin = { -- neovim `:tmap` mappings for the fzf win + [""] = "toggle-help", [""] = "toggle-fullscreen", -- Only valid with the 'builtin' previewer [""] = "toggle-preview-wrap", @@ -460,6 +461,9 @@ Consult the list below for available settings: 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❯ ', @@ -509,6 +513,8 @@ Consult the list below for available settings: ["M"] = { icon = "M", color = "yellow" }, ["D"] = { icon = "D", color = "red" }, ["A"] = { icon = "A", color = "green" }, + ["R"] = { icon = "R", color = "yellow" }, + ["C"] = { icon = "C", color = "yellow" }, ["?"] = { icon = "?", color = "magenta" }, -- override git icons? -- ["M"] = { icon = "★", color = "red" }, diff --git a/lua/fzf-lua/config.lua b/lua/fzf-lua/config.lua index 7e5ce96..fd48b5f 100644 --- a/lua/fzf-lua/config.lua +++ b/lua/fzf-lua/config.lua @@ -86,6 +86,7 @@ M.globals = { }, keymap = { builtin = { + [""] = "toggle-help", [""] = "toggle-fullscreen", -- Only valid with the 'builtin' previewer [""] = "toggle-preview-wrap", @@ -708,4 +709,55 @@ function M.normalize_opts(opts, defaults) return opts end +M.set_action_helpstr = function(fn, helpstr) + assert(type(fn) == 'function' and type(helpstr) == 'string') + M._action_to_helpstr[fn] = helpstr +end + +M.get_action_helpstr = function(fn) + return M._action_to_helpstr[fn] +end + +M._action_to_helpstr = { + [actions.file_edit] = "file-edit", + [actions.file_edit_or_qf] = "file-edit-or-qf", + [actions.file_split] = "file-split", + [actions.file_vsplit] = "file-vsplit", + [actions.file_tabedit] = "file-tabedit", + [actions.file_sel_to_qf] = "file-selection-to-qf", + [actions.buf_edit] = "buffer-edit", + [actions.buf_split] = "buffer-split", + [actions.buf_vsplit] = "buffer-vsplit", + [actions.buf_tabedit] = "buffer-tabedit", + [actions.buf_del] = "buffer-delete", + [actions.buf_switch] = "buffer-switch", + [actions.colorscheme] = "set-colorscheme", + [actions.run_builtin] = "run-builtin", + [actions.ex_run] = "edit-cmd", + [actions.ex_run_cr] = "exec-cmd", + [actions.search] = "edit-search", + [actions.search_cr] = "exec-search", + [actions.goto_mark] = "goto-mark", + [actions.goto_jump] = "goto-jump", + [actions.spell_apply] = "spell-apply", + [actions.set_filetype] = "set-filetype", + [actions.packadd] = "packadd", + [actions.help] = "help-open", + [actions.help_vert] = "help-vertical", + [actions.help_tab] = "help-tab", + [actions.man] = "man-open", + [actions.man_vert] = "man-vertical", + [actions.man_tab] = "man-tab", + [actions.git_switch] = "git-switch", + [actions.git_checkout] = "git-checkout", + [actions.git_stage] = "git-stage", + [actions.git_unstage] = "git-unstage", + [actions.git_buf_edit] = "git-buffer-edit", + [actions.git_buf_tabedit] = "git-buffer-tabedit", + [actions.git_buf_split] = "git-buffer-split", + [actions.git_buf_vsplit] = "git-buffer-vsplit", + [actions.arg_add] = "arg-list-add", + [actions.arg_del] = "arg-list-delete", +} + return M diff --git a/lua/fzf-lua/win.lua b/lua/fzf-lua/win.lua index bd6a071..a2ecd94 100644 --- a/lua/fzf-lua/win.lua +++ b/lua/fzf-lua/win.lua @@ -42,6 +42,7 @@ function FzfWin:setup_keybinds() end end local keymap_tbl = { + ['toggle-help'] = { module = 'win', fnc = 'toggle_help()' }, ['toggle-fullscreen'] = { module = 'win', fnc = 'toggle_fullscreen()' }, } if self.previewer_is_builtin then @@ -322,6 +323,7 @@ function FzfWin:new(o) end o = o or {} self = setmetatable({}, { __index = self }) + self.actions = o.actions self.winopts = normalize_winopts(o) self.fullscreen = self.winopts.fullscreen self.preview_wrap = not opt_matches(o, 'wrap', 'nowrap') @@ -1009,4 +1011,140 @@ function FzfWin.preview_scroll(direction) end end +function FzfWin.toggle_help() + if not _self then return end + local self = _self + + if self.km_winid then + -- help window is already open + -- close and dispose resources + if vim.api.nvim_win_is_valid(self.km_winid) then + vim.api.nvim_win_close(self.km_winid, true) + end + if vim.api.nvim_buf_is_valid(self.km_bufnr) then + vim.api.nvim_buf_delete(self.km_bufnr, {force=true}) + end + self.km_winid = nil + self.km_bufnr = nil + return + end + + local opts = {} + opts.max_height = opts.max_height or math.floor(0.4*vim.o.lines) + opts.mode_width = opts.mode_width or 10 + opts.name_width = opts.name_width or 28 + opts.keybind_width = opts.keybind_width or 14 + opts.normal_hl = opts.normal_hl or self.winopts.hl.normal + opts.border_hl = opts.border_hl or self.winopts.hl.border + opts.winblend = opts.winblend or 0 + opts.column_padding = opts.column_padding or " " + opts.column_width = opts.keybind_width + opts.name_width + #opts.column_padding + 2 + opts.close_with_action = opts.close_with_action or true + + local function format_bind(m, k, v, ml, kl, vl) + return ("%s%%-%ds %%-%ds %%-%ds") + :format(opts.column_padding, ml, kl, vl) + :format('`'..m..'`', '|'..k..'|', '*'..v..'*') + end + + local keymaps = {} + + -- fzf and neovim (builtin) keymaps + for _, m in ipairs({ 'builtin', 'fzf' }) do + for k, v in pairs(self.keymap[m]) do + table.insert(keymaps, + format_bind(m, k, v, opts.mode_width, opts.keybind_width, opts.name_width)) + end + end + + -- action keymaps + if self.actions then + for k, v in pairs(self.actions) do + if k == 'default' then k = 'enter' end + if type(v) =='table' then + v = config.get_action_helpstr(v[1]) or v + else + v = config.get_action_helpstr(v) or v + end + table.insert(keymaps, + format_bind('action', k, + ("%s"):format(v):gsub(" ", ""), + opts.mode_width, opts.keybind_width, opts.name_width)) + end + end + + -- sort alphabetically + table.sort(keymaps, function(x, y) + if x < y then + return true + else + return false + end + end) + + -- append to existing line based on + -- available columns + local function table_append(tbl, s) + local last = #tbl>0 and tbl[#tbl] + if not last or #last+#s>vim.o.columns then + table.insert(tbl, s) + else + tbl[#tbl] = last .. s + end + end + + local lines = {} + for _, km in ipairs(keymaps) do + table_append(lines, km) + end + + -- calc popup height based on no. of lines + local height = #lines ++once lua %s", + table.concat({ + string.format("pcall(vim.api.nvim_win_close, %s, true)", self.km_winid), + string.format("pcall(vim.api.nvim_buf_delete, %s, {force=true})", self.km_bufnr), + }, ";") + )) + + vim.api.nvim_buf_set_lines(self.km_bufnr, 0, -1, false, lines) + +end + return FzfWin