Skip to content

Commit

Permalink
feat: use prompt for input
Browse files Browse the repository at this point in the history
  • Loading branch information
fdschmidt93 committed Jul 14, 2022
1 parent d17f47b commit bb397ba
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 24 deletions.
67 changes: 43 additions & 24 deletions lua/telescope/_extensions/file_browser/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ local transform_mod = require("telescope.actions.mt").transform_mod
local Path = require "plenary.path"
local popup = require "plenary.popup"

-- custom input cb so finder works with built-in input
local stem_prompt = function(prompt)
return { prompt = prompt:find(Path.path.sep) and table.remove(Path:new(prompt):_split()) or prompt }
end

local fb_actions = setmetatable({}, {
__index = function(_, k)
error("Key does not exist for 'fb_actions': " .. tostring(k))
Expand Down Expand Up @@ -101,7 +106,13 @@ fb_actions.create = function(prompt_bufnr)
local finder = current_picker.finder

local default = get_target_dir(finder) .. os_sep
vim.ui.input({ prompt = "Insert the file name: ", default = default, completion = "file" }, function(input)
-- vim.ui.input({ prompt = "Insert the file name: ", default = default }, function(file)
fb_utils.input({
prompt = "Insert the file name: ",
default = default,
prompt_bufnr = prompt_bufnr,
on_input_filter_cb = stem_prompt,
}, function(input)
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
local file = create(input, finder)
if file then
Expand Down Expand Up @@ -232,7 +243,11 @@ fb_actions.rename = function(prompt_bufnr)
fb_utils.notify("action.rename", { msg = "Please select a valid file or folder!", level = "WARN", quiet = quiet })
return
end
vim.ui.input({ prompt = "Insert a new name: ", default = old_path:absolute(), completion = "file" }, function(file)
fb_utils.input({
prompt = "Rename: " .. table.remove(entry.Path:_split()),
prompt_bufnr = prompt_bufnr,
on_input_filter_cb = stem_prompt,
}, function(file)
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
if file == "" or file == nil then
fb_utils.notify("action.rename", { msg = "Renaming aborted!", level = "WARN", quiet = quiet })
Expand Down Expand Up @@ -383,9 +398,9 @@ fb_actions.copy = function(prompt_bufnr)
end
if exists then
exists = false
vim.ui.input({
fb_utils.input({
prompt = string.format(
"Please enter a new name, <CR> to overwrite (merge), or <ESC> to skip file (folder):\n",
"Please enter a new name, <CR> to overwrite (merge), or <ESC> to skip file (folder):",
name
),
default = destination:absolute(),
Expand Down Expand Up @@ -457,29 +472,33 @@ fb_actions.remove = function(prompt_bufnr)
local message = "Selections to be deleted: " .. table.concat(files, ", ")
fb_utils.notify("actions.remove", { msg = message, level = "INFO", quiet = quiet })
-- TODO fix default vim.ui.input and nvim-notify 'selections to be deleted' message
vim.ui.input({ prompt = "Remove selections [y/N]: " }, function(input)
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
if input and input:lower() == "y" then
for _, p in ipairs(selections) do
local is_dir = p:is_dir()
p:rm { recursive = is_dir }
-- clean up opened buffers
if not is_dir then
fb_utils.delete_buf(p:absolute())
else
fb_utils.delete_dir_buf(p:absolute())
-- vim.ui.input({ prompt = "Remove selections [y/N]: " }, function(input)
fb_utils.input(
{ prompt = "Remove selections [y/N]: ", prompt_bufnr = prompt_bufnr, on_input_filter_cb = stem_prompt },
function(input)
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
if input and input:lower() == "y" then
for _, p in ipairs(selections) do
local is_dir = p:is_dir()
p:rm { recursive = is_dir }
-- clean up opened buffers
if not is_dir then
fb_utils.delete_buf(p:absolute())
else
fb_utils.delete_dir_buf(p:absolute())
end
table.insert(removed, p.filename:sub(#p:parent().filename + 2))
end
table.insert(removed, p.filename:sub(#p:parent().filename + 2))
fb_utils.notify(
"actions.remove",
{ msg = "Removed: " .. table.concat(removed, ", "), level = "INFO", quiet = quiet }
)
current_picker:refresh(current_picker.finder)
else
fb_utils.notify("actions.remove", { msg = "Removing selections aborted!", level = "INFO", quiet = quiet })
end
fb_utils.notify(
"actions.remove",
{ msg = "Removed: " .. table.concat(removed, ", "), level = "INFO", quiet = quiet }
)
current_picker:refresh(current_picker.finder)
else
fb_utils.notify("actions.remove", { msg = "Removing selections aborted!", level = "INFO", quiet = quiet })
end
end)
)
end

--- Toggle hidden files or folders for |telescope-file-browser.picker.file_browser|.
Expand Down
1 change: 1 addition & 0 deletions lua/telescope/_extensions/file_browser/make_entry.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local fb_utils = require "telescope._extensions.file_browser.utils"
local utils = require "telescope.utils"
local log = require "telescope.log"
local entry_display = require "telescope.pickers.entry_display"
Expand Down
137 changes: 137 additions & 0 deletions lua/telescope/_extensions/file_browser/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local a = vim.api

local action_state = require "telescope.actions.state"
local utils = require "telescope.utils"
local mappings = require "telescope.mappings"

local Path = require "plenary.path"
local os_sep = Path.path.sep
Expand Down Expand Up @@ -191,4 +192,140 @@ fb_utils.selection_callback = function(current_picker, absolute_path)
end)
end

fb_utils.get_fb_prompt = function()
local prompt_buf = vim.tbl_filter(function(b)
return vim.bo[b].filetype == "TelescopePrompt"
end, vim.api.nvim_list_bufs())
-- vim.ui.{input, select} might be telescope pickers
if #prompt_buf > 1 then
for _, buf in ipairs(prompt_buf) do
local current_picker = action_state.get_current_picker(prompt_buf)
if current_picker.finder._browse_files then
prompt_buf = buf
break
end
end
else
prompt_buf = prompt_buf[1]
end
return prompt_buf
end

local set_prompt = function(prompt_bufnr)
local value = action_state.get_selected_entry().value
local current_picker = action_state.get_current_picker(prompt_bufnr)
current_picker:reset_prompt(value)
end

local get_action = function(action_name, keymappings)
return vim.tbl_filter(function(mapping)
return mapping.func[1] == action_name
end, keymappings)[1].func
end

-- keep_mappings: array of {mode = "n|i", lhs = string }k
local clear_mappings = function(prompt_bufnr, keep_mappings)
mappings.clear(prompt_bufnr)
for _, m in ipairs { "n", "i" } do
vim.tbl_map(function(keymap)
local keep_map = vim.tbl_filter(function(map)
if map.mode == m and map.lhs == keymap.lhs then
return true
end
end, keep_mappings)
if vim.tbl_isempty(keep_map) then
vim.api.nvim_buf_del_keymap(prompt_bufnr, m, keymap.lhs)
end
end, vim.api.nvim_buf_get_keymap(prompt_bufnr, m))
end
end

local function clear_buffer_mappings(bufnr)
for _, mode in ipairs { "n", "i" } do
local buffer_mappings = vim.api.nvim_buf_get_keymap(bufnr, mode)
for _, mapping in ipairs(buffer_mappings) do
vim.api.nvim_buf_del_keymap(bufnr, mode, mapping.lhs)
end
end
end

-- TODO
-- [x] handle ESC, <C-c>
-- [ ] multiple prompts?
-- [ ] refactor into components
-- [ ] namespace for mappings ...
-- highlighting with prompt callback
fb_utils.input = function(opts, on_confirm)
opts.prompt_bufnr = vim.F.if_nil(opts.prompt_bufnr, fb_utils.get_fb_prompt())
local current_picker = action_state.get_current_picker(opts.prompt_bufnr)
local picker_status = {
prompt = current_picker:_get_prompt(),
prompt_prefix = current_picker.prompt_prefix,
title = current_picker.prompt_title,
selection_strategy = current_picker.selection_strategy,
on_input_filter_cb = current_picker._on_input_filter_cb,
attach_mappings = current_picker.attach_mappings,
}

mappings.clear(opts.prompt_bufnr)

opts.on_input_filter_cb = vim.F.if_nil(opts.on_input_filter_cb)
opts.prompt_prefix = vim.F.if_nil(opts.prompt_prefix, current_picker.prompt_prefix)

current_picker.selection_strategy = vim.F.if_nil(opts.selection_strategy, "none")
current_picker.prompt_border:change_title(opts.prompt)
-- vim.fn.prompt_setprompt(opts.prompt_bufnr, opts.prompt_prefix)
current_picker.prompt_prefix = opts.prompt_prefix
current_picker:reset_prompt(opts.default or "")
current_picker._on_input_filter_cb = vim.F.if_nil(opts.on_input_filter_cb, function() end)

local _on_confirm = function(_, confirm_opts)
confirm_opts = confirm_opts or {}
confirm_opts.nil_input = vim.F.if_nil(confirm_opts.nil_input, false)
local prompt = current_picker:_get_prompt()
current_picker._finder_attached = true
current_picker.prompt_border:change_title(picker_status.title)
current_picker.selection_strategy = picker_status.selection_strategy
current_picker.prompt_prefix = picker_status.prompt_prefix
current_picker._on_input_filter_cb = picker_status.on_input_filter_cb
current_picker._finder_attached = true
vim.fn.prompt_setprompt(opts.prompt_bufnr, picker_status.prompt_prefix)
current_picker:reset_prompt ""
-- clear all input mappings prior to re-attaching original fb mappings
clear_buffer_mappings(opts.prompt_bufnr)
mappings.clear(opts.prompt_bufnr)
require("telescope.actions.mt").clear_all()
mappings.apply_keymap(opts.prompt_bufnr, picker_status.attach_mappings, require("telescope.config").values.mappings)
on_confirm(not confirm_opts.nil_input and prompt or nil)
end

local attach_mappings = function(_, map)
local actions = require "telescope.actions"
for _, action in ipairs { actions.move_selection_next, actions.move_selection_previous } do
action:enhance {
pre = function()
current_picker:_toggle_finder_attach()
end,
post = function()
set_prompt(opts.prompt_bufnr)
current_picker:_toggle_finder_attach()
end,
}
actions.select_default:replace(_on_confirm)
actions.close:replace(function()
_on_confirm(_, { nil_input = true })
end)
map("i", "<C-c>", actions.close)
map("i", "<CR>", actions.select_default)
map("n", "<ESC>", actions.close)
return false
end
end
-- clear all mappings prior to attaching input mappings
clear_buffer_mappings(opts.prompt_bufnr)
mappings.clear(opts.prompt_bufnr)
require("telescope.actions.mt").clear_all()
mappings.apply_keymap(opts.prompt_bufnr, attach_mappings, {})
end

return fb_utils

0 comments on commit bb397ba

Please sign in to comment.