feat: Support Line Column in file pickers (#2791)
This implements a experimental interface for allowing prompts like this `file.txt:3:4`. It is already enabled on default for `find_files` and `git_files`. Be wary of breaking changes for the interface if you plan to manually enable it.
This commit is contained in:
committed by
GitHub
parent
87e92ea31b
commit
0bf09d05ab
@@ -384,8 +384,9 @@ files.find_files = function(opts)
|
|||||||
pickers
|
pickers
|
||||||
.new(opts, {
|
.new(opts, {
|
||||||
prompt_title = "Find Files",
|
prompt_title = "Find Files",
|
||||||
|
__locations_input = true,
|
||||||
finder = finders.new_oneshot_job(find_command, opts),
|
finder = finders.new_oneshot_job(find_command, opts),
|
||||||
previewer = conf.file_previewer(opts),
|
previewer = conf.grep_previewer(opts),
|
||||||
sorter = conf.file_sorter(opts),
|
sorter = conf.file_sorter(opts),
|
||||||
})
|
})
|
||||||
:find()
|
:find()
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ git.files = function(opts)
|
|||||||
pickers
|
pickers
|
||||||
.new(opts, {
|
.new(opts, {
|
||||||
prompt_title = "Git Files",
|
prompt_title = "Git Files",
|
||||||
|
__locations_input = true,
|
||||||
finder = finders.new_oneshot_job(
|
finder = finders.new_oneshot_job(
|
||||||
vim.tbl_flatten {
|
vim.tbl_flatten {
|
||||||
opts.git_command,
|
opts.git_command,
|
||||||
@@ -54,7 +55,7 @@ git.files = function(opts)
|
|||||||
},
|
},
|
||||||
opts
|
opts
|
||||||
),
|
),
|
||||||
previewer = conf.file_previewer(opts),
|
previewer = conf.grep_previewer(opts),
|
||||||
sorter = conf.file_sorter(opts),
|
sorter = conf.file_sorter(opts),
|
||||||
})
|
})
|
||||||
:find()
|
:find()
|
||||||
|
|||||||
@@ -319,6 +319,8 @@ function Picker:new(opts)
|
|||||||
cache_picker = config.resolve_table_opts(opts.cache_picker, vim.deepcopy(config.values.cache_picker)),
|
cache_picker = config.resolve_table_opts(opts.cache_picker, vim.deepcopy(config.values.cache_picker)),
|
||||||
|
|
||||||
__scrolling_limit = tonumber(vim.F.if_nil(opts.temp__scrolling_limit, 250)),
|
__scrolling_limit = tonumber(vim.F.if_nil(opts.temp__scrolling_limit, 250)),
|
||||||
|
|
||||||
|
__locations_input = vim.F.if_nil(opts.__locations_input, false),
|
||||||
}, self)
|
}, self)
|
||||||
|
|
||||||
obj.create_layout = opts.create_layout or config.values.create_layout or default_create_layout
|
obj.create_layout = opts.create_layout or config.values.create_layout or default_create_layout
|
||||||
@@ -624,6 +626,21 @@ function Picker:find()
|
|||||||
local start_time = vim.loop.hrtime()
|
local start_time = vim.loop.hrtime()
|
||||||
|
|
||||||
local prompt = self:_get_next_filtered_prompt()
|
local prompt = self:_get_next_filtered_prompt()
|
||||||
|
if self.__locations_input == true then
|
||||||
|
local filename, line_number, column_number = utils.__separate_file_path_location(prompt)
|
||||||
|
|
||||||
|
if line_number or column_number then
|
||||||
|
state.set_global_key("prompt_location", { row = line_number, col = column_number })
|
||||||
|
elseif state.get_global_key "prompt_location" then
|
||||||
|
state.set_global_key("prompt_location", nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- it is important to continue behaving as if there is no location in prompt
|
||||||
|
prompt = filename
|
||||||
|
elseif state.get_global_key "prompt_location" then
|
||||||
|
-- in case new picker that does not support locations is opened clear the location
|
||||||
|
state.set_global_key("prompt_location", nil)
|
||||||
|
end
|
||||||
|
|
||||||
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
|
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
|
||||||
if self.cache_picker == false or self.cache_picker.is_cached ~= true then
|
if self.cache_picker == false or self.cache_picker.is_cached ~= true then
|
||||||
@@ -1044,6 +1061,19 @@ function Picker:set_selection(row)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local entry = self.manager:get_entry(self:get_index(row))
|
local entry = self.manager:get_entry(self:get_index(row))
|
||||||
|
|
||||||
|
local prompt_location = state.get_global_key "prompt_location"
|
||||||
|
if entry and prompt_location then
|
||||||
|
entry.lnum = prompt_location.row or 0
|
||||||
|
if prompt_location.col and prompt_location.col > 0 then
|
||||||
|
entry.col = prompt_location.col
|
||||||
|
entry.colend = prompt_location.col + 1
|
||||||
|
else
|
||||||
|
entry.col = 1 -- we do + 1 here because previewer does -1
|
||||||
|
entry.colend = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
state.set_global_key("selected_entry", entry)
|
state.set_global_key("selected_entry", entry)
|
||||||
|
|
||||||
if not entry then
|
if not entry then
|
||||||
@@ -1101,6 +1131,7 @@ function Picker:set_selection(row)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:refresh_previewer()
|
||||||
if old_entry == entry and self._selection_row == row then
|
if old_entry == entry and self._selection_row == row then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -1109,8 +1140,6 @@ function Picker:set_selection(row)
|
|||||||
self._selection_entry = entry
|
self._selection_entry = entry
|
||||||
self._selection_row = row
|
self._selection_row = row
|
||||||
|
|
||||||
self:refresh_previewer()
|
|
||||||
|
|
||||||
vim.api.nvim_win_set_cursor(self.results_win, { row + 1, 0 })
|
vim.api.nvim_win_set_cursor(self.results_win, { row + 1, 0 })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ local utils = require "telescope.utils"
|
|||||||
local putils = require "telescope.previewers.utils"
|
local putils = require "telescope.previewers.utils"
|
||||||
local Previewer = require "telescope.previewers.previewer"
|
local Previewer = require "telescope.previewers.previewer"
|
||||||
local conf = require("telescope.config").values
|
local conf = require("telescope.config").values
|
||||||
|
local global_state = require "telescope.state"
|
||||||
|
|
||||||
local pscan = require "plenary.scandir"
|
local pscan = require "plenary.scandir"
|
||||||
|
|
||||||
@@ -345,8 +346,6 @@ previewers.new_buffer_previewer = function(opts)
|
|||||||
|
|
||||||
local old_bufs = {}
|
local old_bufs = {}
|
||||||
local bufname_table = {}
|
local bufname_table = {}
|
||||||
|
|
||||||
local global_state = require "telescope.state"
|
|
||||||
local preview_window_id
|
local preview_window_id
|
||||||
|
|
||||||
local function get_bufnr(self)
|
local function get_bufnr(self)
|
||||||
|
|||||||
@@ -567,4 +567,40 @@ utils.list_find = function(func, list)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Takes the path and parses optional cursor location `$file:$line:$column`
|
||||||
|
--- If line or column not present `0` returned.
|
||||||
|
--- @param path string
|
||||||
|
utils.__separate_file_path_location = function(path)
|
||||||
|
local location_numbers = {}
|
||||||
|
for i = #path, 1, -1 do
|
||||||
|
if path:sub(i, i) == ":" then
|
||||||
|
if i == #path then
|
||||||
|
path = path:sub(1, i - 1)
|
||||||
|
else
|
||||||
|
local location_value = tonumber(path:sub(i + 1))
|
||||||
|
if location_value then
|
||||||
|
table.insert(location_numbers, location_value)
|
||||||
|
path = path:sub(1, i - 1)
|
||||||
|
|
||||||
|
if #location_numbers == 2 then
|
||||||
|
-- There couldn't be more than 2 : separated number
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #location_numbers == 2 then
|
||||||
|
-- because of the reverse the line number will be second
|
||||||
|
return path, location_numbers[2], location_numbers[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
if #location_numbers == 1 then
|
||||||
|
return path, location_numbers[1], 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return path, 0, 0
|
||||||
|
end
|
||||||
|
|
||||||
return utils
|
return utils
|
||||||
|
|||||||
@@ -78,3 +78,48 @@ describe("is_uri", function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe("separates file path location", function()
|
||||||
|
local suites = {
|
||||||
|
{
|
||||||
|
input = "file.txt:12:4",
|
||||||
|
file = "file.txt",
|
||||||
|
row = 12,
|
||||||
|
col = 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input = "file.txt:12",
|
||||||
|
file = "file.txt",
|
||||||
|
row = 12,
|
||||||
|
col = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input = "file:12:4",
|
||||||
|
file = "file",
|
||||||
|
row = 12,
|
||||||
|
col = 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input = "file:12:",
|
||||||
|
file = "file",
|
||||||
|
row = 12,
|
||||||
|
col = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input = "file:",
|
||||||
|
file = "file",
|
||||||
|
row = 0,
|
||||||
|
col = 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, suite in ipairs(suites) do
|
||||||
|
it("separtates file path for " .. suite.input, function()
|
||||||
|
local file, row, col = utils.__separate_file_path_location(suite.input)
|
||||||
|
|
||||||
|
assert.are.equal(file, suite.file)
|
||||||
|
assert.are.equal(row, suite.row)
|
||||||
|
assert.are.equal(col, suite.col)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|||||||
Reference in New Issue
Block a user