telescope.nvim icon indicating copy to clipboard operation
telescope.nvim copied to clipboard

Ability to focus with cursor on the preview window

Open Tal500 opened this issue 2 years ago • 10 comments

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.

Tal500 avatar Nov 12 '23 04:11 Tal500

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

xzbdmw avatar Jul 02 '24 09:07 xzbdmw

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

daUnknownCoder avatar Jul 03 '24 11:07 daUnknownCoder

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

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

daUnknownCoder avatar Jul 03 '24 11:07 daUnknownCoder

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 })

xzbdmw avatar Jul 03 '24 11:07 xzbdmw

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,

daUnknownCoder avatar Jul 03 '24 11:07 daUnknownCoder

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,
                        },
                    },

xzbdmw avatar Jul 03 '24 11:07 xzbdmw

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",
      },

daUnknownCoder avatar Jul 03 '24 11:07 daUnknownCoder

how to scroll in preview window using hjkl ? or <c-h> <c-j> <c-k> <c-l>

erlangparasu avatar Jul 13 '24 09:07 erlangparasu

@xzbdmw do you know how to see the number and relative number in the preview? Thanks

mvillafuertem avatar Aug 04 '24 21:08 mvillafuertem

@mvillafuertem

vim.api.nvim_create_autocmd({ "User" }, {
    pattern = "TelescopePreviewerLoaded",
    callback = function(data)
        local winid = data.data.winid
        vim.wo[winid].number = true
    end,
})

xzbdmw avatar Aug 05 '24 00:08 xzbdmw

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

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 avatar Nov 16 '24 23:11 emmanueltouzery

@emmanueltouzery see here

xzbdmw avatar Nov 17 '24 05:11 xzbdmw

@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

emmanueltouzery avatar Nov 17 '24 07:11 emmanueltouzery

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

danrasmuson avatar Nov 24 '24 19:11 danrasmuson