Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search for file then method/line #1042

Closed
johans opened this issue Jul 23, 2021 · 4 comments
Closed

Search for file then method/line #1042

johans opened this issue Jul 23, 2021 · 4 comments
Labels
enhancement Enhancement to performance, inner workings or existent features

Comments

@johans
Copy link

johans commented Jul 23, 2021

First, thanks for this awsome project! I only miss this one feature described below.

Sublime Text and recently also VS Code has this really nice feature which lets you go directly to a function/method or line number via the quick open meny using the search patterns:

  • "partOfFileName@function" and
  • "partOfFileName:linenumber"

What's also nice is that it supports previewing as you type which is really useful if you just want to look something up really quick.

Is something like this possible to implement in Telescope? Currently I first search and open the file then use lsp_document_symbols({prompt_prefix=' ', default_text=' :method: '}) to filter on methods. This works but would be so cool if it could be improved into one action.

Attached a small video showing the feature:

sublime

@johans johans added the enhancement Enhancement to performance, inner workings or existent features label Jul 23, 2021
@fdschmidt93
Copy link
Member

fdschmidt93 commented Jul 28, 2021

I'm afraid it is buried deep in telescope/pickers.lua and undocumented but something like this is possible with a few workarounds :)

local actions = require "telescope.actions"

file_and_symbol = function()
  require("telescope.builtin").find_files {
    -- if I read it correctly, this `on_input_filter_cb` is evaluated before finding/sorting, so any char should be safe to hook into here
    on_input_filter_cb = function(prompt)
      if prompt:sub(#prompt) == "@" then
        vim.schedule(function()
          -- schedule is required as actions otherwise don't work in async
          local prompt_bufnr = vim.api.nvim_get_current_buf()
          require("telescope.actions").select_default(prompt_bufnr)
          require("telescope.builtin").lsp_document_symbols()
          -- hack as otherwise picker doesn't go into insert mode
          vim.cmd [[normal! A]]
        end)
      end
    end,
  }
end

One issue with this though is that the file from which you are opening the picker needs to have the same LSP attached or you somehow attach the LSP timely enough.

Small showcase:

switch.mp4

@johans
Copy link
Author

johans commented Jul 28, 2021

@fdschmidt93 Amazing, it works really well! Thank you so much for this!

@fdschmidt93
Copy link
Member

@johans

This came up again in gitter.

You can amend the above solution with something like this in your telescope- find_files picker setup to preview and goto line

local actions = require "telescope.actions"
local action_state = require "telescope.action.state"

require"telescope".setup{
  pickers =
    find_files = {
      on_input_filter_cb = function(prompt)
        local find_colon = string.find(prompt, ":")
        if find_colon then
          local ret = string.sub(prompt, 1, find_colon - 1)
          vim.schedule(function()
            local prompt_bufnr = vim.api.nvim_get_current_buf()
            local picker = action_state.get_current_picker(prompt_bufnr)
            local lnum = tonumber(prompt:sub(find_colon + 1))
            if type(lnum) == "number" then
              local win = picker.previewer.state.winid
              local bufnr = picker.previewer.state.bufnr
              local line_count = vim.api.nvim_buf_line_count(bufnr)
              vim.api.nvim_win_set_cursor(win, { math.max(1, math.min(lnum, line_count)), 0 })
            end
          end)
          return { prompt = ret }
        end
      end,
      attach_mappings = function()
        actions.select_default:enhance {
          post = function()
            -- if we found something, go to line
            local prompt = action_state.get_current_line()
            local find_colon = string.find(prompt, ":")
            if find_colon then
              local lnum = tonumber(prompt:sub(find_colon + 1))
              vim.api.nvim_win_set_cursor(0, { lnum, 0 })
            end
          end,
        }
        return true
      end,
    },
  }
}

Further, you could use extmarks/highlighting to show line numbers and / or highlight the respective line.. I'd leave that to you though :)

@johans
Copy link
Author

johans commented Aug 11, 2021

@fdschmidt93 So cool! Thanks for taking the time to post this here aswell! 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement to performance, inner workings or existent features
Projects
None yet
Development

No branches or pull requests

2 participants