local pickers = require("telescope.pickers") local finders = require("telescope.finders") local conf = require("telescope.config").values local actions = require("telescope.actions") local action_state = require("telescope.actions.state") local previewers = require("telescope.previewers") -- Custom previewer that dynamically calculates how many lines -- can fit in the preview window, then shows a centered slice. local dynamic_previewer = previewers.new_buffer_previewer({ define_preview = function(self, entry, status) -- 'entry.lnum' is the *actual file line number*. local filepath = entry.path local target = entry.lnum or 1 -- Get the preview buffer & window local pbufnr = self.state.bufnr local pwinid = status.preview_win if not pbufnr or not vim.api.nvim_buf_is_valid(pbufnr) then return end if not pwinid or not vim.api.nvim_win_is_valid(pwinid) then return end -- How many lines can we show in the preview window? -- Subtract a bit (e.g., 1 or 2) if you use borders or want extra margin. local lines_in_window = vim.api.nvim_win_get_height(pwinid) - 1 if lines_in_window < 1 then lines_in_window = 1 end -- Read the entire file, figure out the slice to show local all_lines = vim.fn.readfile(filepath) local total = #all_lines -- We'll center on the target line, if possible local half_context = math.floor(lines_in_window / 2) local start_line = math.max(target - half_context, 1) local end_line = math.min(start_line + lines_in_window - 1, total) -- Collect that slice of lines local preview_lines = {} for i = start_line, end_line do table.insert(preview_lines, all_lines[i]) end -- Write the slice to the preview buffer vim.api.nvim_buf_set_lines(pbufnr, 0, -1, false, preview_lines) vim.api.nvim_buf_clear_namespace(pbufnr, -1, 0, -1) -- Highlight the target line within the slice local relative_line = target - start_line + 1 if relative_line >= 1 and relative_line <= #preview_lines then vim.api.nvim_buf_add_highlight( pbufnr, -1, "Search", relative_line - 1, 0, -1 ) end end, }) local function jump_to_line() local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) local current_file = vim.api.nvim_buf_get_name(0) local entries = {} for i, text in ipairs(lines) do table.insert(entries, { value = text, display = string.format("%d: %s", i, text), ordinal = text, path = current_file, -- needed by the previewer lnum = i, -- actual file line number }) end pickers.new({}, { prompt_title = "Jump to Line", finder = finders.new_table({ results = entries, entry_maker = function(e) return e end, }), sorter = conf.generic_sorter({}), previewer = dynamic_previewer, attach_mappings = function(prompt_bufnr, _) actions.select_default:replace(function() actions.close(prompt_bufnr) local selection = action_state.get_selected_entry() if selection then local target_line = selection.lnum local closed_line = vim.fn.foldclosed(target_line) if closed_line ~= -1 then target_line = closed_line end -- Jump and open the fold vim.cmd(string.format("normal! %dG", target_line)) vim.cmd("normal! zv") end end) return true end, }):find() end return { jump_to_line = jump_to_line }