Ability to focus with cursor on the preview window
Is your feature request related to a problem? Please describe. I don't know if it's legit here to compare my VSCode/VS/similar experience with Nvim. There are IDEs that allow you to inspect the preview window(says floating like telescope) with a full cursor support, either on a modifiable buffer or not, but still with a full "cursor" yanking and visual mode support. An example use-case that is really missing for me, is that when browsing git commit log on Telescope, you can only scroll the preview window that tells you the diff per file, but you cannot move your cursor to the preview buffer, go to the file path mentioned, and then press "gf" to quickly open this file in a new buffer. There could be more advanced features for navigating there reminding "treesitter" keyboard navigation, but that's for later if we'd like.
Describe the solution you'd like The simple(?) ability to "jump" the focus to the preview window(back and forth) and have a cursor there in the (non/)modifiable buffer (similar to the global help buffers).
I know that Telescope tries to mimic FZF UI, and the latter have no cursor support on preview, but in an editor it makes sense in my opinion to add this (optional) feature.
Describe alternatives you've considered For each specific feature domain (git, grep, ...) just use a specific different plugin, but still miss the telescope floating UI and get an emacs-like UI(e.g. neogit that is emacs-maggit port to nvim) instead, in addition to the non-uniform UI.
You can achieve this by
local focus_preview = function(prompt_bufnr)
local action_state = require("telescope.actions.state")
local picker = action_state.get_current_picker(prompt_bufnr)
local prompt_win = picker.prompt_win
local previewer = picker.previewer
local winid = previewer.state.winid
local bufnr = previewer.state.bufnr
vim.keymap.set("n", "<Tab>", function()
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", prompt_win))
end, { buffer = bufnr })
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", winid))
-- api.nvim_set_current_win(winid)
end
and bind to a key
["<Tab>"] = focus_preview,
now use tab to jump between prompt and preview. Note that any edit takes no effect in real file, you'd better only yank or move around
now use tab to jump between prompt and preview.
i used this, but my tab always adds 4 spaces instead of switching to the preview window
now use tab to jump between prompt and preview.
i used this, but my
tabalways adds 4 spaces instead of switching to the preview window
i remapped it to S-Tab which does get me to the preview but i cannot go back to the prompt and insert mode is bugged, check video:
https://github.com/nvim-telescope/telescope.nvim/assets/84800625/92841579-6b3c-458f-bb5b-1c1af962fa6a
idk why
i used this, but my tab always adds 4 spaces instead of switching to the preview window
Probably because you bind at normal mode and not insert mode, for jumping back, try bind to a different key say f4?
vim.keymap.set({"n","i"}, "<f4>", function()
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", prompt_win))
end, { buffer = bufnr })
look idk how telescope works, but this is my config and also check the video, all problems have been recorded there
config = function()
local telescope_status_ok, telescope = pcall(require, "telescope")
if not telescope_status_ok then
print("Telescope not found!")
end
local icons_ok, icons = pcall(require, "NeutronVim.core.icons")
if not icons_ok then
print("Unable to import icons!")
end
local previewers = require("telescope.previewers")
local _bad = { ".*%.csv", ".*%.scm" }
local bad_files = function(filepath)
for _, v in ipairs(_bad) do
if filepath:match(v) then
return false
end
end
return true
end
local new_maker = function(filepath, bufnr, opts)
opts = opts or {}
if opts.use_ft_detect == nil then
opts.use_ft_detect = true
end
opts.use_ft_detect = opts.use_ft_detect == false and false or bad_files(filepath)
previewers.buffer_previewer_maker(filepath, bufnr, opts)
end
local focus_preview = function(prompt_bufnr)
local action_state = require("telescope.actions.state")
local picker = action_state.get_current_picker(prompt_bufnr)
local prompt_win = picker.prompt_win
local previewer = picker.previewer
local winid = previewer.state.winid
local bufnr = previewer.state.bufnr
vim.keymap.set("n", "<Tab>", function()
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", prompt_win))
end, { buffer = bufnr })
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", winid))
end
telescope.setup({
defaults = {
entry_prefix = icons.ui.Edge,
selection_caret = icons.ui.Item .. " ",
prompt_prefix = icons.ui.ArrowClosed,
multi_icon = icons.ui.Check,
path_display = { shorten = { len = 1, exclude = { 1, -1 } } },
dynamic_preview_title = true,
buffer_previewer_maker = new_maker,
initial_mode = "insert",
selection_strategy = "reset",
sorting_strategy = "ascending",
layout_strategy = "horizontal",
preview = {
filesize_limit = 1, -- MB
},
mappings = {
n = {
["<C-p>"] = require("telescope.actions.layout").toggle_preview,
},
i = {
["<esc>"] = require("telescope.actions").close,
["<C-u>"] = false,
["<C-i>"] = false,
["<S-Tab>"] = false,
["<Tab>"] = false,
["<C-p>"] = require("telescope.actions.layout").toggle_preview,
},
},
layout_config = {
horizontal = {
prompt_position = "top",
preview_width = 0.55,
results_width = 0.5,
},
vertical = {
mirror = false,
},
width = 0.87,
height = 0.8,
preview_cutoff = 120,
},
},
extensions = {
fzf = {
fuzzy = true,
override_generic_sorter = true,
override_file_sorter = true,
case_mode = "smart_case",
},
aerial = {
show_nesting = {
["_"] = false,
json = true,
yaml = true,
},
},
import = {
insert_at_top = true,
},
},
pickers = {
find_files = {
mappings = {
n = {
["cd"] = function(prompt_bufnr)
local selection = require("telescope.actions.state").get_selected_entry()
local dir = vim.fn.fnamemodify(selection.path, ":p:h")
require("telescope.actions").close(prompt_bufnr)
vim.cmd(string.format("silent lcd %s", dir))
end,
},
},
},
},
})
end,
change this part, c-i and tab is the same thing in terminal
mappings = {
n = {
["<C-p>"] = require("telescope.actions.layout").toggle_preview,
["<Tab>"] = focus_preview,
},
i = {
["<esc>"] = require("telescope.actions").close,
["<C-u>"] = false,
["<S-Tab>"] = false,
["<Tab>"] = focus_preview,
["<C-p>"] = require("telescope.actions.layout").toggle_preview,
},
},
i actually have this thats why i tried to disable <c-i> is mapped to another plugin in insert mode:
{
"<C-i>",
"<cmd>IconPickerInsert<CR>",
desc = "Pick icon [Insert]",
mode = "i",
},
how to scroll in preview window using hjkl ?
or <c-h> <c-j> <c-k> <c-l>
@xzbdmw do you know how to see the number and relative number in the preview? Thanks
@mvillafuertem
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "TelescopePreviewerLoaded",
callback = function(data)
local winid = data.data.winid
vim.wo[winid].number = true
end,
})
You can achieve this by
local focus_preview = function(prompt_bufnr) local action_state = require("telescope.actions.state") local picker = action_state.get_current_picker(prompt_bufnr) local prompt_win = picker.prompt_win local previewer = picker.previewer local winid = previewer.state.winid local bufnr = previewer.state.bufnr vim.keymap.set("n", "<Tab>", function() vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", prompt_win)) end, { buffer = bufnr }) vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", winid)) -- api.nvim_set_current_win(winid) endand bind to a key
["<Tab>"] = focus_preview,now use tab to jump between prompt and preview. Note that any edit takes no effect in real file, you'd better only yank or move around
this is super useful, however it doesn't work for terminal previews, in that case the previewer.state doesn't contain winid and bufnr as expected, but only termopen_id (which is not a window id) and termopen_bufnr. so i couldn't make it work in that scenario.
@emmanueltouzery see here
@xzbdmw thank you, works great!
so the updated code is:
local focus_preview = function(prompt_bufnr)
local action_state = require("telescope.actions.state")
local picker = action_state.get_current_picker(prompt_bufnr)
local prompt_win = picker.prompt_win
local previewer = picker.previewer
local bufnr = previewer.state.bufnr or previewer.state.termopen_bufnr
local winid = previewer.state.winid or vim.fn.win_findbuf(bufnr)[1]
vim.keymap.set("n", "<Tab>", function()
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", prompt_win))
end, { buffer = bufnr })
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", winid))
-- api.nvim_set_current_win(winid)
end
Putting it all togeather here is what I have in LazyVim...
~/.config/nvim/lua/plugins/telescope.nvim.lua
local function focus_preview(prompt_bufnr)
local action_state = require("telescope.actions.state")
local picker = action_state.get_current_picker(prompt_bufnr)
local prompt_win = picker.prompt_win
local previewer = picker.previewer
local bufnr = previewer.state.bufnr or previewer.state.termopen_bufnr
local winid = previewer.state.winid or vim.fn.win_findbuf(bufnr)[1]
vim.keymap.set("n", "<Tab>", function()
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", prompt_win))
end, { buffer = bufnr })
vim.cmd(string.format("noautocmd lua vim.api.nvim_set_current_win(%s)", winid))
-- api.nvim_set_current_win(winid)
end
return {
"nvim-telescope/telescope.nvim",
opts = {
defaults = {
mappings = {
n = {
["<Tab>"] = focus_preview,
},
},
},
},
}
And then in telescope pressing <esc> to enter normal mode and then <tab> to move to my cursor to the preview screen