feat: file browser & refresh interface (#290)
and more picker api stuff for sunjon. refresh is implemented for file_browser and git_status
This commit is contained in:
@@ -354,6 +354,7 @@ Built-in functions. Ready to be bound to any key you like. :smile:
|
|||||||
| `builtin.git_files` | Lists Git files in current directory. |
|
| `builtin.git_files` | Lists Git files in current directory. |
|
||||||
| `builtin.grep_string` | Searches for a string under the cursor in current directory. |
|
| `builtin.grep_string` | Searches for a string under the cursor in current directory. |
|
||||||
| `builtin.live_grep` | Searches in current directory files. (respecting .gitignore) |
|
| `builtin.live_grep` | Searches in current directory files. (respecting .gitignore) |
|
||||||
|
| `builtin.file_browser` | Ivy-like file explorer. Creates files by typing in filename and pressing <C-e>. Press <C-e> without prompt for more info |
|
||||||
|
|
||||||
### Vim Pickers
|
### Vim Pickers
|
||||||
|
|
||||||
@@ -373,7 +374,7 @@ Built-in functions. Ready to be bound to any key you like. :smile:
|
|||||||
| `builtin.vim_options` | Lists vim options and on enter edit the options value. |
|
| `builtin.vim_options` | Lists vim options and on enter edit the options value. |
|
||||||
| `builtin.registers` | Lists vim registers and edit or paste selection. |
|
| `builtin.registers` | Lists vim registers and edit or paste selection. |
|
||||||
| `builtin.autocommands` | Lists vim autocommands and go to their declaration. |
|
| `builtin.autocommands` | Lists vim autocommands and go to their declaration. |
|
||||||
| `builtin.spell_suggest` | Lists spelling suggestions for <cword>.
|
| `builtin.spell_suggest` | Lists spelling suggestions for <cword>. |
|
||||||
| `builtin.keymaps` | Lists normal-mode mappings. |
|
| `builtin.keymaps` | Lists normal-mode mappings. |
|
||||||
| `builtin.filetypes` | Lists all filetypes. |
|
| `builtin.filetypes` | Lists all filetypes. |
|
||||||
| `builtin.highlights` | Lists all highlights. |
|
| `builtin.highlights` | Lists all highlights. |
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ action_set.select:replace_if(
|
|||||||
end, function(_, type)
|
end, function(_, type)
|
||||||
-- type is { "default", "horizontal", "vertical", "tab" }
|
-- type is { "default", "horizontal", "vertical", "tab" }
|
||||||
local path = actions.get_selected_entry().path
|
local path = actions.get_selected_entry().path
|
||||||
actions.refresh(prompt_bufnr, gen_new_finder(vim.fn.expand(path:sub(1, -2))), { reset_prompt = true })
|
action_state.get_current_picker(prompt_bufnr):refresh(gen_new_finder(new_cwd), { reset_prompt = true})
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -245,16 +245,11 @@ actions.git_staging_toggle = function(prompt_bufnr)
|
|||||||
local cwd = action_state.get_current_picker(prompt_bufnr).cwd
|
local cwd = action_state.get_current_picker(prompt_bufnr).cwd
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
|
|
||||||
-- If parts of the file are staged and unstaged at the same time, stage
|
|
||||||
-- changes. Else toggle between staged and unstaged if the file is tracked,
|
|
||||||
-- and between added and untracked if the file is untracked.
|
|
||||||
if selection.status:sub(2) == ' ' then
|
if selection.status:sub(2) == ' ' then
|
||||||
utils.get_os_command_output({ 'git', 'restore', '--staged', selection.value }, cwd)
|
utils.get_os_command_output({ 'git', 'restore', '--staged', selection.value }, cwd)
|
||||||
else
|
else
|
||||||
utils.get_os_command_output({ 'git', 'add', selection.value }, cwd)
|
utils.get_os_command_output({ 'git', 'add', selection.value }, cwd)
|
||||||
end
|
end
|
||||||
do_close(prompt_bufnr, true)
|
|
||||||
require('telescope.builtin').git_status()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local entry_to_qf = function(entry)
|
local entry_to_qf = function(entry)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
local actions = require('telescope.actions')
|
||||||
local action_state = require('telescope.actions.state')
|
local action_state = require('telescope.actions.state')
|
||||||
local action_set = require('telescope.actions.set')
|
local action_set = require('telescope.actions.set')
|
||||||
local finders = require('telescope.finders')
|
local finders = require('telescope.finders')
|
||||||
@@ -7,6 +8,10 @@ local previewers = require('telescope.previewers')
|
|||||||
local utils = require('telescope.utils')
|
local utils = require('telescope.utils')
|
||||||
local conf = require('telescope.config').values
|
local conf = require('telescope.config').values
|
||||||
|
|
||||||
|
local scan = require('plenary.scandir')
|
||||||
|
local Path = require('plenary.path')
|
||||||
|
local os_sep = Path.path.sep
|
||||||
|
|
||||||
local flatten = vim.tbl_flatten
|
local flatten = vim.tbl_flatten
|
||||||
|
|
||||||
local files = {}
|
local files = {}
|
||||||
@@ -191,6 +196,84 @@ local function prepare_match(entry, kind)
|
|||||||
return entries
|
return entries
|
||||||
end
|
end
|
||||||
|
|
||||||
|
files.file_browser = function(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
|
||||||
|
opts.cwd = opts.cwd and vim.fn.expand(opts.cwd) or vim.loop.cwd()
|
||||||
|
|
||||||
|
local gen_new_finder = function(path)
|
||||||
|
opts.cwd = path
|
||||||
|
local data = {}
|
||||||
|
|
||||||
|
scan.scan_dir(path, {
|
||||||
|
add_dirs = true,
|
||||||
|
depth = 1,
|
||||||
|
on_insert = function(entry, typ)
|
||||||
|
table.insert(data, typ == 'directory' and (entry .. os_sep) or entry)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
table.insert(data, 1, '../')
|
||||||
|
|
||||||
|
return finders.new_table {
|
||||||
|
results = data,
|
||||||
|
entry_maker = (function()
|
||||||
|
local tele_path = require'telescope.path'
|
||||||
|
local gen = make_entry.gen_from_file(opts)
|
||||||
|
return function(entry)
|
||||||
|
local tmp = gen(entry)
|
||||||
|
tmp.ordinal = tele_path.make_relative(entry, opts.cwd)
|
||||||
|
return tmp
|
||||||
|
end
|
||||||
|
end)()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
pickers.new(opts, {
|
||||||
|
prompt_title = 'Find Files',
|
||||||
|
finder = gen_new_finder(opts.cwd),
|
||||||
|
previewer = conf.file_previewer(opts),
|
||||||
|
sorter = conf.file_sorter(opts),
|
||||||
|
attach_mappings = function(prompt_bufnr, map)
|
||||||
|
action_set.select:replace_if(function()
|
||||||
|
return action_state.get_selected_entry().path:sub(-1) == os_sep
|
||||||
|
end, function()
|
||||||
|
local new_cwd = vim.fn.expand(action_state.get_selected_entry().path:sub(1, -2))
|
||||||
|
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||||
|
current_picker.cwd = new_cwd
|
||||||
|
current_picker:refresh(gen_new_finder(new_cwd), { reset_prompt = true })
|
||||||
|
end)
|
||||||
|
|
||||||
|
local create_new_file = function()
|
||||||
|
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||||
|
local file = action_state.get_current_line()
|
||||||
|
if file == "" then
|
||||||
|
print('To create a new file or directory(add ' .. os_sep .. ' at the end of file) ' ..
|
||||||
|
'write the desired new into the prompt and press <C-e>. ' ..
|
||||||
|
'It works for not existing nested input as well.' ..
|
||||||
|
'Example: this' .. os_sep .. 'is' .. os_sep .. 'a' .. os_sep .. 'new_file.lua')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local fpath = current_picker.cwd .. os_sep .. file
|
||||||
|
if string.sub(fpath, -1) ~= os_sep then
|
||||||
|
actions.close(prompt_bufnr)
|
||||||
|
Path:new(fpath):touch({ parents = true })
|
||||||
|
vim.cmd(string.format(':e %s', fpath))
|
||||||
|
else
|
||||||
|
Path:new(fpath:sub(1, -2)):mkdir({ parents = true })
|
||||||
|
local new_cwd = vim.fn.expand(fpath)
|
||||||
|
current_picker.cwd = new_cwd
|
||||||
|
current_picker:refresh(gen_new_finder(new_cwd), { reset_prompt = true })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
map('i', '<C-e>', create_new_file)
|
||||||
|
map('n', '<C-e>', create_new_file)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}):find()
|
||||||
|
end
|
||||||
|
|
||||||
files.treesitter = function(opts)
|
files.treesitter = function(opts)
|
||||||
opts.show_line = utils.get_default(opts.show_line, true)
|
opts.show_line = utils.get_default(opts.show_line, true)
|
||||||
|
|
||||||
@@ -295,7 +378,7 @@ files.tags = function(opts)
|
|||||||
attach_mappings = function()
|
attach_mappings = function()
|
||||||
action_set.select:enhance {
|
action_set.select:enhance {
|
||||||
post = function()
|
post = function()
|
||||||
local selection = action_set.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
|
|
||||||
if selection.scode then
|
if selection.scode then
|
||||||
local scode = string.gsub(selection.scode, '[$]$', '')
|
local scode = string.gsub(selection.scode, '[$]$', '')
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local actions = require('telescope.actions')
|
local actions = require('telescope.actions')
|
||||||
|
local action_state = require('telescope.actions.state')
|
||||||
local finders = require('telescope.finders')
|
local finders = require('telescope.finders')
|
||||||
local make_entry = require('telescope.make_entry')
|
local make_entry = require('telescope.make_entry')
|
||||||
local pickers = require('telescope.pickers')
|
local pickers = require('telescope.pickers')
|
||||||
@@ -108,6 +109,7 @@ git.branches = function(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
git.status = function(opts)
|
git.status = function(opts)
|
||||||
|
local gen_new_finder = function()
|
||||||
local output = utils.get_os_command_output({ 'git', 'status', '-s' }, opts.cwd)
|
local output = utils.get_os_command_output({ 'git', 'status', '-s' }, opts.cwd)
|
||||||
|
|
||||||
if table.getn(output) == 0 then
|
if table.getn(output) == 0 then
|
||||||
@@ -115,15 +117,27 @@ git.status = function(opts)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return finders.new_table {
|
||||||
|
results = output,
|
||||||
|
entry_maker = opts.entry_maker or make_entry.gen_from_git_status(opts)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local initial_finder = gen_new_finder()
|
||||||
|
if not initial_finder then return end
|
||||||
|
|
||||||
pickers.new(opts, {
|
pickers.new(opts, {
|
||||||
prompt_title = 'Git Status',
|
prompt_title = 'Git Status',
|
||||||
finder = finders.new_table {
|
finder = initial_finder,
|
||||||
results = output,
|
|
||||||
entry_maker = make_entry.gen_from_git_status(opts)
|
|
||||||
},
|
|
||||||
previewer = previewers.git_file_diff.new(opts),
|
previewer = previewers.git_file_diff.new(opts),
|
||||||
sorter = conf.file_sorter(opts),
|
sorter = conf.file_sorter(opts),
|
||||||
attach_mappings = function(_, map)
|
attach_mappings = function(prompt_bufnr, map)
|
||||||
|
actions.git_staging_toggle:enhance {
|
||||||
|
post = function()
|
||||||
|
action_state.get_current_picker(prompt_bufnr):refresh(gen_new_finder(), { reset_prompt = true })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
map('i', '<tab>', actions.git_staging_toggle)
|
map('i', '<tab>', actions.git_staging_toggle)
|
||||||
map('n', '<tab>', actions.git_staging_toggle)
|
map('n', '<tab>', actions.git_staging_toggle)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ builtin.live_grep = require('telescope.builtin.files').live_grep
|
|||||||
builtin.grep_string = require('telescope.builtin.files').grep_string
|
builtin.grep_string = require('telescope.builtin.files').grep_string
|
||||||
builtin.find_files = require('telescope.builtin.files').find_files
|
builtin.find_files = require('telescope.builtin.files').find_files
|
||||||
builtin.fd = builtin.find_files
|
builtin.fd = builtin.find_files
|
||||||
|
builtin.file_browser = require('telescope.builtin.files').file_browser
|
||||||
builtin.treesitter = require('telescope.builtin.files').treesitter
|
builtin.treesitter = require('telescope.builtin.files').treesitter
|
||||||
builtin.current_buffer_fuzzy_find = require('telescope.builtin.files').current_buffer_fuzzy_find
|
builtin.current_buffer_fuzzy_find = require('telescope.builtin.files').current_buffer_fuzzy_find
|
||||||
builtin.tags = require('telescope.builtin.files').tags
|
builtin.tags = require('telescope.builtin.files').tags
|
||||||
|
|||||||
@@ -54,11 +54,11 @@ function config.set_defaults(defaults)
|
|||||||
set("borderchars", { '─', '│', '─', '│', '╭', '╮', '╯', '╰'})
|
set("borderchars", { '─', '│', '─', '│', '╭', '╮', '╯', '╰'})
|
||||||
|
|
||||||
set("get_status_text", function(self)
|
set("get_status_text", function(self)
|
||||||
return string.format(
|
local xx = (self.stats.processed or 0) - (self.stats.filtered or 0)
|
||||||
"%s / %s",
|
local yy = self.stats.processed or 0
|
||||||
(self.stats.processed or 0) - (self.stats.filtered or 0),
|
if xx == 0 and yy == 0 then return "" end
|
||||||
self.stats.processed or 0
|
|
||||||
)
|
return string.format("%s / %s", xx, yy)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Builtin configuration
|
-- Builtin configuration
|
||||||
|
|||||||
@@ -380,10 +380,9 @@ function Picker:find()
|
|||||||
prompt_prefix = prompt_prefix .. " "
|
prompt_prefix = prompt_prefix .. " "
|
||||||
end
|
end
|
||||||
vim.fn.prompt_setprompt(prompt_bufnr, prompt_prefix)
|
vim.fn.prompt_setprompt(prompt_bufnr, prompt_prefix)
|
||||||
|
|
||||||
a.nvim_buf_add_highlight(prompt_bufnr, ns_telescope_prompt_prefix, 'TelescopePromptPrefix', 0, 0, #prompt_prefix)
|
|
||||||
end
|
end
|
||||||
self.prompt_prefix = prompt_prefix
|
self.prompt_prefix = prompt_prefix
|
||||||
|
self:_reset_prefix_color()
|
||||||
|
|
||||||
-- Temporarily disabled: Draw the screen ASAP. This makes things feel speedier.
|
-- Temporarily disabled: Draw the screen ASAP. This makes things feel speedier.
|
||||||
-- vim.cmd [[redraw]]
|
-- vim.cmd [[redraw]]
|
||||||
@@ -444,6 +443,8 @@ function Picker:find()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.__on_lines = on_lines
|
||||||
|
|
||||||
on_lines(nil, nil, nil, 0, 1)
|
on_lines(nil, nil, nil, 0, 1)
|
||||||
status_updater()
|
status_updater()
|
||||||
|
|
||||||
@@ -633,6 +634,59 @@ function Picker:reset_selection()
|
|||||||
self.multi_select = {}
|
self.multi_select = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Picker:_reset_prefix_color(hl_group)
|
||||||
|
self._current_prefix_hl_group = hl_group or nil
|
||||||
|
|
||||||
|
if self.prompt_prefix ~= '' then
|
||||||
|
vim.api.nvim_buf_add_highlight(self.prompt_bufnr,
|
||||||
|
ns_telescope_prompt_prefix,
|
||||||
|
self._current_prefix_hl_group or 'TelescopePromptPrefix',
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
#self.prompt_prefix
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO(conni2461): Maybe _ prefix these next two functions
|
||||||
|
-- TODO(conni2461): Next two functions only work together otherwise color doesn't work
|
||||||
|
-- Probably a issue with prompt buffers
|
||||||
|
function Picker:change_prompt_prefix(new_prefix, hl_group)
|
||||||
|
if not new_prefix then return end
|
||||||
|
|
||||||
|
if new_prefix ~= '' then
|
||||||
|
if not vim.endswith(new_prefix, " ") then
|
||||||
|
new_prefix = new_prefix .. " "
|
||||||
|
end
|
||||||
|
vim.fn.prompt_setprompt(self.prompt_bufnr, new_prefix)
|
||||||
|
else
|
||||||
|
vim.api.nvim_buf_set_text(self.prompt_bufnr, 0, 0, 0, #self.prompt_prefix, {})
|
||||||
|
vim.api.nvim_buf_set_option(self.prompt_bufnr, 'buftype', '')
|
||||||
|
end
|
||||||
|
self.prompt_prefix = new_prefix
|
||||||
|
self:_reset_prefix_color(hl_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Picker:reset_prompt()
|
||||||
|
vim.api.nvim_buf_set_lines(self.prompt_bufnr, 0, -1, false, { self.prompt_prefix })
|
||||||
|
self:_reset_prefix_color(self._current_prefix_hl_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- opts.new_prefix: Either as string or { new_string, hl_group }
|
||||||
|
--- opts.reset_prompt: bool
|
||||||
|
function Picker:refresh(finder, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
if opts.new_prefix then
|
||||||
|
local handle = type(opts.new_prefix) == 'table' and unpack or function(x) return x end
|
||||||
|
self:change_prompt_prefix(handle(opts.new_prefix))
|
||||||
|
end
|
||||||
|
if opts.reset_prompt then self:reset_prompt() end
|
||||||
|
|
||||||
|
self.finder:close()
|
||||||
|
self.finder = finder
|
||||||
|
self.__on_lines(nil, nil, nil, 0, 1)
|
||||||
|
end
|
||||||
|
|
||||||
function Picker:set_selection(row)
|
function Picker:set_selection(row)
|
||||||
row = self.scroller(self.max_results, self.manager:num_results(), row)
|
row = self.scroller(self.max_results, self.manager:num_results(), row)
|
||||||
|
|
||||||
@@ -648,7 +702,6 @@ 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 status = state.get_status(self.prompt_bufnr)
|
|
||||||
local results_bufnr = self.results_bufnr
|
local results_bufnr = self.results_bufnr
|
||||||
|
|
||||||
if row > a.nvim_buf_line_count(results_bufnr) then
|
if row > a.nvim_buf_line_count(results_bufnr) then
|
||||||
@@ -723,17 +776,21 @@ function Picker:set_selection(row)
|
|||||||
self._selection_entry = entry
|
self._selection_entry = entry
|
||||||
self._selection_row = row
|
self._selection_row = row
|
||||||
|
|
||||||
|
self:refresh_previewer()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Picker:refresh_previewer()
|
||||||
|
local status = state.get_status(self.prompt_bufnr)
|
||||||
if status.preview_win and self.previewer then
|
if status.preview_win and self.previewer then
|
||||||
self:_increment("previewed")
|
self:_increment("previewed")
|
||||||
|
|
||||||
self.previewer:preview(
|
self.previewer:preview(
|
||||||
entry,
|
self._selection_entry,
|
||||||
status
|
status
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Picker:entry_adder(index, entry, _, insert)
|
function Picker:entry_adder(index, entry, _, insert)
|
||||||
local row = self:get_row(index)
|
local row = self:get_row(index)
|
||||||
|
|
||||||
@@ -838,6 +895,10 @@ function Picker:_increment(key)
|
|||||||
self.stats[key] = (self.stats[key] or 0) + 1
|
self.stats[key] = (self.stats[key] or 0) + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Picker:_decrement(key)
|
||||||
|
self.stats[key] = (self.stats[key] or 0) - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- TODO: Decide how much we want to use this.
|
-- TODO: Decide how much we want to use this.
|
||||||
-- Would allow for better debugging of items.
|
-- Would allow for better debugging of items.
|
||||||
@@ -925,6 +986,10 @@ function Picker:get_result_processor(prompt, status_updater)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if entry.ignore_count ~= nil and entry.ignore_count == true then
|
||||||
|
self:_decrement("processed")
|
||||||
|
end
|
||||||
|
|
||||||
if sort_score == -1 then
|
if sort_score == -1 then
|
||||||
self:_increment("filtered")
|
self:_increment("filtered")
|
||||||
log.trace("Filtering out result: ", entry)
|
log.trace("Filtering out result: ", entry)
|
||||||
|
|||||||
Reference in New Issue
Block a user