Skip to content

Commit bb397ba

Browse files
committed
feat: use prompt for input
1 parent d17f47b commit bb397ba

File tree

3 files changed

+181
-24
lines changed

3 files changed

+181
-24
lines changed

lua/telescope/_extensions/file_browser/actions.lua

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ local transform_mod = require("telescope.actions.mt").transform_mod
4141
local Path = require "plenary.path"
4242
local popup = require "plenary.popup"
4343

44+
-- custom input cb so finder works with built-in input
45+
local stem_prompt = function(prompt)
46+
return { prompt = prompt:find(Path.path.sep) and table.remove(Path:new(prompt):_split()) or prompt }
47+
end
48+
4449
local fb_actions = setmetatable({}, {
4550
__index = function(_, k)
4651
error("Key does not exist for 'fb_actions': " .. tostring(k))
@@ -101,7 +106,13 @@ fb_actions.create = function(prompt_bufnr)
101106
local finder = current_picker.finder
102107

103108
local default = get_target_dir(finder) .. os_sep
104-
vim.ui.input({ prompt = "Insert the file name: ", default = default, completion = "file" }, function(input)
109+
-- vim.ui.input({ prompt = "Insert the file name: ", default = default }, function(file)
110+
fb_utils.input({
111+
prompt = "Insert the file name: ",
112+
default = default,
113+
prompt_bufnr = prompt_bufnr,
114+
on_input_filter_cb = stem_prompt,
115+
}, function(input)
105116
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
106117
local file = create(input, finder)
107118
if file then
@@ -232,7 +243,11 @@ fb_actions.rename = function(prompt_bufnr)
232243
fb_utils.notify("action.rename", { msg = "Please select a valid file or folder!", level = "WARN", quiet = quiet })
233244
return
234245
end
235-
vim.ui.input({ prompt = "Insert a new name: ", default = old_path:absolute(), completion = "file" }, function(file)
246+
fb_utils.input({
247+
prompt = "Rename: " .. table.remove(entry.Path:_split()),
248+
prompt_bufnr = prompt_bufnr,
249+
on_input_filter_cb = stem_prompt,
250+
}, function(file)
236251
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
237252
if file == "" or file == nil then
238253
fb_utils.notify("action.rename", { msg = "Renaming aborted!", level = "WARN", quiet = quiet })
@@ -383,9 +398,9 @@ fb_actions.copy = function(prompt_bufnr)
383398
end
384399
if exists then
385400
exists = false
386-
vim.ui.input({
401+
fb_utils.input({
387402
prompt = string.format(
388-
"Please enter a new name, <CR> to overwrite (merge), or <ESC> to skip file (folder):\n",
403+
"Please enter a new name, <CR> to overwrite (merge), or <ESC> to skip file (folder):",
389404
name
390405
),
391406
default = destination:absolute(),
@@ -457,29 +472,33 @@ fb_actions.remove = function(prompt_bufnr)
457472
local message = "Selections to be deleted: " .. table.concat(files, ", ")
458473
fb_utils.notify("actions.remove", { msg = message, level = "INFO", quiet = quiet })
459474
-- TODO fix default vim.ui.input and nvim-notify 'selections to be deleted' message
460-
vim.ui.input({ prompt = "Remove selections [y/N]: " }, function(input)
461-
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
462-
if input and input:lower() == "y" then
463-
for _, p in ipairs(selections) do
464-
local is_dir = p:is_dir()
465-
p:rm { recursive = is_dir }
466-
-- clean up opened buffers
467-
if not is_dir then
468-
fb_utils.delete_buf(p:absolute())
469-
else
470-
fb_utils.delete_dir_buf(p:absolute())
475+
-- vim.ui.input({ prompt = "Remove selections [y/N]: " }, function(input)
476+
fb_utils.input(
477+
{ prompt = "Remove selections [y/N]: ", prompt_bufnr = prompt_bufnr, on_input_filter_cb = stem_prompt },
478+
function(input)
479+
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
480+
if input and input:lower() == "y" then
481+
for _, p in ipairs(selections) do
482+
local is_dir = p:is_dir()
483+
p:rm { recursive = is_dir }
484+
-- clean up opened buffers
485+
if not is_dir then
486+
fb_utils.delete_buf(p:absolute())
487+
else
488+
fb_utils.delete_dir_buf(p:absolute())
489+
end
490+
table.insert(removed, p.filename:sub(#p:parent().filename + 2))
471491
end
472-
table.insert(removed, p.filename:sub(#p:parent().filename + 2))
492+
fb_utils.notify(
493+
"actions.remove",
494+
{ msg = "Removed: " .. table.concat(removed, ", "), level = "INFO", quiet = quiet }
495+
)
496+
current_picker:refresh(current_picker.finder)
497+
else
498+
fb_utils.notify("actions.remove", { msg = "Removing selections aborted!", level = "INFO", quiet = quiet })
473499
end
474-
fb_utils.notify(
475-
"actions.remove",
476-
{ msg = "Removed: " .. table.concat(removed, ", "), level = "INFO", quiet = quiet }
477-
)
478-
current_picker:refresh(current_picker.finder)
479-
else
480-
fb_utils.notify("actions.remove", { msg = "Removing selections aborted!", level = "INFO", quiet = quiet })
481500
end
482-
end)
501+
)
483502
end
484503

485504
--- Toggle hidden files or folders for |telescope-file-browser.picker.file_browser|.

lua/telescope/_extensions/file_browser/make_entry.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
local fb_utils = require "telescope._extensions.file_browser.utils"
12
local utils = require "telescope.utils"
23
local log = require "telescope.log"
34
local entry_display = require "telescope.pickers.entry_display"

lua/telescope/_extensions/file_browser/utils.lua

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local a = vim.api
22

33
local action_state = require "telescope.actions.state"
44
local utils = require "telescope.utils"
5+
local mappings = require "telescope.mappings"
56

67
local Path = require "plenary.path"
78
local os_sep = Path.path.sep
@@ -191,4 +192,140 @@ fb_utils.selection_callback = function(current_picker, absolute_path)
191192
end)
192193
end
193194

195+
fb_utils.get_fb_prompt = function()
196+
local prompt_buf = vim.tbl_filter(function(b)
197+
return vim.bo[b].filetype == "TelescopePrompt"
198+
end, vim.api.nvim_list_bufs())
199+
-- vim.ui.{input, select} might be telescope pickers
200+
if #prompt_buf > 1 then
201+
for _, buf in ipairs(prompt_buf) do
202+
local current_picker = action_state.get_current_picker(prompt_buf)
203+
if current_picker.finder._browse_files then
204+
prompt_buf = buf
205+
break
206+
end
207+
end
208+
else
209+
prompt_buf = prompt_buf[1]
210+
end
211+
return prompt_buf
212+
end
213+
214+
local set_prompt = function(prompt_bufnr)
215+
local value = action_state.get_selected_entry().value
216+
local current_picker = action_state.get_current_picker(prompt_bufnr)
217+
current_picker:reset_prompt(value)
218+
end
219+
220+
local get_action = function(action_name, keymappings)
221+
return vim.tbl_filter(function(mapping)
222+
return mapping.func[1] == action_name
223+
end, keymappings)[1].func
224+
end
225+
226+
-- keep_mappings: array of {mode = "n|i", lhs = string }k
227+
local clear_mappings = function(prompt_bufnr, keep_mappings)
228+
mappings.clear(prompt_bufnr)
229+
for _, m in ipairs { "n", "i" } do
230+
vim.tbl_map(function(keymap)
231+
local keep_map = vim.tbl_filter(function(map)
232+
if map.mode == m and map.lhs == keymap.lhs then
233+
return true
234+
end
235+
end, keep_mappings)
236+
if vim.tbl_isempty(keep_map) then
237+
vim.api.nvim_buf_del_keymap(prompt_bufnr, m, keymap.lhs)
238+
end
239+
end, vim.api.nvim_buf_get_keymap(prompt_bufnr, m))
240+
end
241+
end
242+
243+
local function clear_buffer_mappings(bufnr)
244+
for _, mode in ipairs { "n", "i" } do
245+
local buffer_mappings = vim.api.nvim_buf_get_keymap(bufnr, mode)
246+
for _, mapping in ipairs(buffer_mappings) do
247+
vim.api.nvim_buf_del_keymap(bufnr, mode, mapping.lhs)
248+
end
249+
end
250+
end
251+
252+
-- TODO
253+
-- [x] handle ESC, <C-c>
254+
-- [ ] multiple prompts?
255+
-- [ ] refactor into components
256+
-- [ ] namespace for mappings ...
257+
-- highlighting with prompt callback
258+
fb_utils.input = function(opts, on_confirm)
259+
opts.prompt_bufnr = vim.F.if_nil(opts.prompt_bufnr, fb_utils.get_fb_prompt())
260+
local current_picker = action_state.get_current_picker(opts.prompt_bufnr)
261+
local picker_status = {
262+
prompt = current_picker:_get_prompt(),
263+
prompt_prefix = current_picker.prompt_prefix,
264+
title = current_picker.prompt_title,
265+
selection_strategy = current_picker.selection_strategy,
266+
on_input_filter_cb = current_picker._on_input_filter_cb,
267+
attach_mappings = current_picker.attach_mappings,
268+
}
269+
270+
mappings.clear(opts.prompt_bufnr)
271+
272+
opts.on_input_filter_cb = vim.F.if_nil(opts.on_input_filter_cb)
273+
opts.prompt_prefix = vim.F.if_nil(opts.prompt_prefix, current_picker.prompt_prefix)
274+
275+
current_picker.selection_strategy = vim.F.if_nil(opts.selection_strategy, "none")
276+
current_picker.prompt_border:change_title(opts.prompt)
277+
-- vim.fn.prompt_setprompt(opts.prompt_bufnr, opts.prompt_prefix)
278+
current_picker.prompt_prefix = opts.prompt_prefix
279+
current_picker:reset_prompt(opts.default or "")
280+
current_picker._on_input_filter_cb = vim.F.if_nil(opts.on_input_filter_cb, function() end)
281+
282+
local _on_confirm = function(_, confirm_opts)
283+
confirm_opts = confirm_opts or {}
284+
confirm_opts.nil_input = vim.F.if_nil(confirm_opts.nil_input, false)
285+
local prompt = current_picker:_get_prompt()
286+
current_picker._finder_attached = true
287+
current_picker.prompt_border:change_title(picker_status.title)
288+
current_picker.selection_strategy = picker_status.selection_strategy
289+
current_picker.prompt_prefix = picker_status.prompt_prefix
290+
current_picker._on_input_filter_cb = picker_status.on_input_filter_cb
291+
current_picker._finder_attached = true
292+
vim.fn.prompt_setprompt(opts.prompt_bufnr, picker_status.prompt_prefix)
293+
current_picker:reset_prompt ""
294+
-- clear all input mappings prior to re-attaching original fb mappings
295+
clear_buffer_mappings(opts.prompt_bufnr)
296+
mappings.clear(opts.prompt_bufnr)
297+
require("telescope.actions.mt").clear_all()
298+
mappings.apply_keymap(opts.prompt_bufnr, picker_status.attach_mappings, require("telescope.config").values.mappings)
299+
on_confirm(not confirm_opts.nil_input and prompt or nil)
300+
end
301+
302+
local attach_mappings = function(_, map)
303+
local actions = require "telescope.actions"
304+
for _, action in ipairs { actions.move_selection_next, actions.move_selection_previous } do
305+
action:enhance {
306+
pre = function()
307+
current_picker:_toggle_finder_attach()
308+
end,
309+
post = function()
310+
set_prompt(opts.prompt_bufnr)
311+
current_picker:_toggle_finder_attach()
312+
end,
313+
}
314+
actions.select_default:replace(_on_confirm)
315+
actions.close:replace(function()
316+
_on_confirm(_, { nil_input = true })
317+
end)
318+
map("i", "<C-c>", actions.close)
319+
map("i", "<CR>", actions.select_default)
320+
map("n", "<ESC>", actions.close)
321+
return false
322+
end
323+
end
324+
-- clear all mappings prior to attaching input mappings
325+
clear_buffer_mappings(opts.prompt_bufnr)
326+
mappings.clear(opts.prompt_bufnr)
327+
require("telescope.actions.mt").clear_all()
328+
mappings.apply_keymap(opts.prompt_bufnr, attach_mappings, {})
329+
end
330+
194331
return fb_utils

0 commit comments

Comments
 (0)