diff --git a/lua/telescope/actions/init.lua b/lua/telescope/actions/init.lua index 1677e10..1a86e6b 100644 --- a/lua/telescope/actions/init.lua +++ b/lua/telescope/actions/init.lua @@ -21,50 +21,10 @@ local transform_mod = require('telescope.actions.mt').transform_mod local actions = setmetatable({}, { __index = function(_, k) - -- TODO(conni2461): Remove deprecated messages - if k:find('goto_file_selection') then - error("`" .. k .. "` is removed and no longer usable. " .. - "Use `require('telescope.actions').select_` instead. Take a look at developers.md for more Information.") - elseif k == '_goto_file_selection' then - error("`_goto_file_selection` is deprecated and no longer replaceable. " .. - "Use `require('telescope.actions.set').edit` instead. Take a look at developers.md for more Information.") - end - error("Key does not exist for 'telescope.actions': " .. tostring(k)) end }) --- TODO(conni2461): Remove deprecated messages -local action_is_deprecated = function(name, err) - local messager = err and error or log.info - - return messager( - string.format("`actions.%s()` is deprecated." - .. "Use require('telescope.actions.state').%s() instead", - name, - name - ) - ) -end - -function actions.get_selected_entry() - -- TODO(1.0): Remove - action_is_deprecated("get_selected_entry") - return action_state.get_selected_entry() -end - -function actions.get_current_line() - -- TODO(1.0): Remove - action_is_deprecated("get_current_line") - return action_state.get_current_line() -end - -function actions.get_current_picker(prompt_bufnr) - -- TODO(1.0): Remove - action_is_deprecated("get_current_picker") - return action_state.get_current_picker(prompt_bufnr) -end - --- Move the selection to the next entry ---@param prompt_bufnr number: The prompt bufnr function actions.move_selection_next(prompt_bufnr) @@ -155,6 +115,17 @@ function actions.center(_) vim.cmd(':normal! zz') end +function actions.select_multi_default(prompt_bufnr) + local picker = action_state.get_current_picker(prompt_bufnr) + local manager = picker.manager + + for entry in manager:iter() do + action_set.select(entry) + end + + actions.close(prompt_bufnr) +end + function actions.select_default(prompt_bufnr) return action_set.select(prompt_bufnr, "default") end @@ -197,31 +168,36 @@ function actions.close_pum(_) end actions._close = function(prompt_bufnr, keepinsert) + log.warn("Closing:", prompt_bufnr) local picker = action_state.get_current_picker(prompt_bufnr) local prompt_win = state.get_status(prompt_bufnr).prompt_win local original_win_id = picker.original_win_id - if picker.previewer then - picker.previewer:teardown() - end + -- TODO: I don't think I want this here, because it will get cleared + -- when we do a NEW picker. + -- picker:teardown() actions.close_pum(prompt_bufnr) if not keepinsert then vim.cmd [[stopinsert]] end - vim.api.nvim_win_close(prompt_win, true) + if prompt_win and a.nvim_win_is_valid(prompt_win) then + vim.api.nvim_win_close(prompt_win, true) + pcall(a.nvim_set_current_win, original_win_id) + end - pcall(vim.cmd, string.format([[silent bdelete! %s]], prompt_bufnr)) - pcall(a.nvim_set_current_win, original_win_id) + if prompt_bufnr and a.nvim_buf_is_valid(prompt_bufnr) then + pcall(a.nvim_buf_delete, prompt_bufnr, { force = true }) + end end function actions.close(prompt_bufnr) actions._close(prompt_bufnr, false) end -actions.edit_command_line = function(prompt_bufnr) - local entry = action_state.get_selected_entry(prompt_bufnr) +actions.edit_command_line = function(prompt_bufnr, entry) + entry = entry or action_state.get_selected_entry(prompt_bufnr) actions.close(prompt_bufnr) a.nvim_feedkeys(a.nvim_replace_termcodes(":" .. entry.value , true, false, true), "t", true) end diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index aceea8b..e3e1148 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -1,3 +1,5 @@ +require('telescope') + local a = vim.api local popup = require('popup') @@ -8,8 +10,6 @@ local async = async_lib.async local await = async_lib.await local channel = async_util.channel -require('telescope') - local actions = require('telescope.actions') local action_set = require('telescope.actions.set') local config = require('telescope.config') @@ -281,6 +281,8 @@ function Picker:_next_find_id() end function Picker:find() + state.set_current_picker(self) + self:close_existing_pickers() self:reset_selection() @@ -421,21 +423,7 @@ function Picker:find() end) -- Register attach - vim.api.nvim_buf_attach(prompt_bufnr, false, { - on_lines = tx.send, - on_detach = function() - -- TODO: Can we add a "cleanup" / "teardown" function that completely removes these. - self.finder = nil - self.previewer = nil - self.sorter = nil - self.manager = nil - - self.closed = true - - -- TODO: Should we actually do this? - collectgarbage(); collectgarbage() - end, - }) + vim.api.nvim_buf_attach(prompt_bufnr, false, { on_lines = tx.send }) if self.sorter then self.sorter:_init() end async_lib.run(main_loop()) @@ -492,56 +480,6 @@ function Picker:hide_preview() end -function Picker.close_windows(status) - local prompt_win = status.prompt_win - local results_win = status.results_win - local preview_win = status.preview_win - - local prompt_border_win = status.prompt_border_win - local results_border_win = status.results_border_win - local preview_border_win = status.preview_border_win - - local function del_win(name, win_id, force, bdelete) - if not vim.api.nvim_win_is_valid(win_id) then - return - end - - local bufnr = vim.api.nvim_win_get_buf(win_id) - if bdelete - and vim.api.nvim_buf_is_valid(bufnr) - and not vim.api.nvim_buf_get_option(bufnr, 'buflisted') then - vim.cmd(string.format("silent! bdelete! %s", bufnr)) - end - - if not vim.api.nvim_win_is_valid(win_id) then - return - end - - if not pcall(vim.api.nvim_win_close, win_id, force) then - log.trace("Unable to close window: ", name, "/", win_id) - end - end - - del_win("prompt_win", prompt_win, true) - del_win("results_win", results_win, true, true) - del_win("preview_win", preview_win, true, true) - - del_win("prompt_border_win", prompt_border_win, true, true) - del_win("results_border_win", results_border_win, true, true) - del_win("preview_border_win", preview_border_win, true, true) - - -- vim.cmd(string.format("bdelete! %s", status.prompt_bufnr)) - - -- Major hack?? Why do I have to od this. - -- Probably because we're currently IN the buffer. - -- Should wait to do this until after we're done. - vim.defer_fn(function() - del_win("prompt_win", prompt_win, true) - end, 10) - - state.clear_status(status.prompt_bufnr) -end - function Picker:get_selection() return self._selection_entry end @@ -872,9 +810,16 @@ function Picker:_on_complete() end end +--- TODO: Can we remove this? function Picker:close_existing_pickers() for _, prompt_bufnr in ipairs(state.get_existing_prompts()) do - pcall(actions.close, prompt_bufnr) + error("Shouldn't happen -- close_existing_pickers: " .. tostring(prompt_bufnr)) + -- pcall(actions.close, prompt_bufnr) + -- local prompt_picker = (state.get_status(prompt_bufnr) or {}).picker + -- if prompt_picker then + -- log.warn("Tearing down picker...") + -- prompt_picker:teardown() + -- end end end @@ -1036,21 +981,6 @@ pickers.new = function(opts, defaults) return Picker:new(result) end -function pickers.on_close_prompt(prompt_bufnr) - local status = state.get_status(prompt_bufnr) - local picker = status.picker - - if picker.sorter then - picker.sorter:_destroy() - end - - if picker.previewer then - picker.previewer:teardown() - end - - picker.close_windows(status) -end - --- Get the prompt text without the prompt prefix. function Picker:_get_prompt() return vim.api.nvim_buf_get_lines(self.prompt_bufnr, 0, 1, false)[1]:sub(#self.prompt_prefix + 1) @@ -1060,7 +990,78 @@ function Picker:_reset_highlights() self.highlighter:clear_display() end +function pickers.on_close_prompt(prompt_bufnr) + pickers.close_windows(state.get_status(prompt_bufnr)) +end + +function pickers.close_windows(status) + local prompt_win = status.prompt_win + local results_win = status.results_win + local preview_win = status.preview_win + + local prompt_border_win = status.prompt_border_win + local results_border_win = status.results_border_win + local preview_border_win = status.preview_border_win + + local function del_win(name, win_id, force, bdelete) + if not vim.api.nvim_win_is_valid(win_id) then + return + end + + local bufnr = vim.api.nvim_win_get_buf(win_id) + if bdelete + and vim.api.nvim_buf_is_valid(bufnr) + and not vim.api.nvim_buf_get_option(bufnr, 'buflisted') then + a.nvim_buf_delete(bufnr, { force = true }) + end + + if not vim.api.nvim_win_is_valid(win_id) then + return + end + + if not pcall(vim.api.nvim_win_close, win_id, force) then + log.trace("Unable to close window: ", name, "/", win_id) + end + end + + del_win("prompt_win", prompt_win, true) + del_win("results_win", results_win, true, true) + del_win("preview_win", preview_win, true, true) + + del_win("prompt_border_win", prompt_border_win, true, true) + del_win("results_border_win", results_border_win, true, true) + del_win("preview_border_win", preview_border_win, true, true) + + -- Major hack?? Why do I have to od this. + -- Probably because we're currently IN the buffer. + -- Should wait to do this until after we're done. + vim.defer_fn(function() + del_win("prompt_win", prompt_win, true) + end, 10) + + state.clear_status(status.prompt_bufnr) +end + + +function Picker:teardown() + log.warn("CLEARING PICKER NOW") + + if self.sorter then + self.sorter:_destroy() + end + + if self.previewer then + self.previewer:teardown() + end + + for k, _ in pairs(self) do + self[k] = nil + end + + collectgarbage() + collectgarbage() +end + pickers._Picker = Picker - return pickers diff --git a/lua/telescope/state.lua b/lua/telescope/state.lua index 6a06eb1..36f0719 100644 --- a/lua/telescope/state.lua +++ b/lua/telescope/state.lua @@ -1,23 +1,38 @@ local state = {} -TelescopeGlobalState = TelescopeGlobalState or {} -TelescopeGlobalState.global = TelescopeGlobalState.global or {} - ---- Set the status for a particular prompt bufnr -function state.set_status(prompt_bufnr, status) - TelescopeGlobalState[prompt_bufnr] = status -end +_TelescopeGlobalState = _TelescopeGlobalState or {} +_TelescopeGlobalState.global = _TelescopeGlobalState.global or {} +_TelescopeGlobalState.prompt = _TelescopeGlobalState.prompt or {} function state.set_global_key(key, value) - TelescopeGlobalState.global[key] = value + _TelescopeGlobalState.global[key] = value end function state.get_global_key(key) - return TelescopeGlobalState.global[key] + return _TelescopeGlobalState.global[key] +end + +function state.set_current_picker(picker) + local old_picker = state.get_current_picker() + if old_picker then + old_picker:teardown() + old_picker = nil + end + + state.set_global_key('picker', picker) +end + +function state.get_current_picker() + return state.get_global_key('picker') +end + +--- Set the status for a particular prompt bufnr +function state.set_status(prompt_bufnr, status) + _TelescopeGlobalState.prompt[prompt_bufnr] = status end function state.get_status(prompt_bufnr) - return TelescopeGlobalState[prompt_bufnr] or {} + return _TelescopeGlobalState.prompt[prompt_bufnr] or {} end function state.clear_status(prompt_bufnr) @@ -25,7 +40,7 @@ function state.clear_status(prompt_bufnr) end function state.get_existing_prompts() - return vim.tbl_keys(TelescopeGlobalState) + return vim.tbl_keys(_TelescopeGlobalState.prompt) end return state