From 544c5ee40752ac5552595da86a62abaa39e2dfa9 Mon Sep 17 00:00:00 2001 From: Simon Hauser Date: Sun, 1 May 2022 09:46:50 +0200 Subject: [PATCH] fix: termopen previewer (#1901) - buffer leaking - still insert mode on confirm --- README.md | 16 ++-- doc/telescope.txt | 3 - lua/telescope/actions/init.lua | 4 +- lua/telescope/pickers.lua | 25 +++---- lua/telescope/previewers/init.lua | 3 - lua/telescope/previewers/term_previewer.lua | 82 +++++++++++---------- 6 files changed, 65 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index a86d0ff..cf558a1 100644 --- a/README.md +++ b/README.md @@ -334,14 +334,14 @@ Built-in functions. Ready to be bound to any key you like. ## Previewers -| Previewers | Description | -|------------------------------------|-----------------------------------------------------------------| -| `previewers.vim_buffer_cat.new` | Default previewer for files. Uses vim buffers | -| `previewers.vim_buffer_vimgrep.new`| Default previewer for grep and similar. Uses vim buffers | -| `previewers.vim_buffer_qflist.new` | Default previewer for qflist. Uses vim buffers | -| `previewers.cat.new` | Deprecated previewer for files. Uses `cat`/`bat` | -| `previewers.vimgrep.new` | Deprecated previewer for grep and similar. Uses `cat`/`bat` | -| `previewers.qflist.new` | Deprecated previewer for qflist. Uses `cat`/`bat` | +| Previewers | Description | +|------------------------------------|-----------------------------------------------------------| +| `previewers.vim_buffer_cat.new` | Default previewer for files. Uses vim buffers | +| `previewers.vim_buffer_vimgrep.new`| Default previewer for grep and similar. Uses vim buffers | +| `previewers.vim_buffer_qflist.new` | Default previewer for qflist. Uses vim buffers | +| `previewers.cat.new` | Terminal previewer for files. Uses `cat`/`bat` | +| `previewers.vimgrep.new` | Terminal previewer for grep and similar. Uses `cat`/`bat` | +| `previewers.qflist.new` | Terminal previewer for qflist. Uses `cat`/`bat` | The default previewers are from now on `vim_buffer_` previewers. They use vim buffers for displaying files and use tree-sitter or regex for file highlighting. diff --git a/doc/telescope.txt b/doc/telescope.txt index a2516b6..1adb7e2 100644 --- a/doc/telescope.txt +++ b/doc/telescope.txt @@ -2932,9 +2932,6 @@ previewers.new_termopen_previewer() *telescope.previewers.new_termopen_previewer Furthermore, it will forward all `config.set_env` environment variables to that terminal process. - While this interface is a good start, it was replaced with the way more - flexible `buffer_previewer` and is now deprecated. - previewers.cat() *telescope.previewers.cat()* diff --git a/lua/telescope/actions/init.lua b/lua/telescope/actions/init.lua index be55390..5899629 100644 --- a/lua/telescope/actions/init.lua +++ b/lua/telescope/actions/init.lua @@ -345,13 +345,11 @@ end actions.close = function(prompt_bufnr) action_state.get_current_history():reset() 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 actions.close_pum(prompt_bufnr) - vim.api.nvim_win_close(prompt_win, true) - pcall(vim.cmd, string.format([[silent bdelete! %s]], prompt_bufnr)) + require("telescope.pickers").on_close_prompt(prompt_bufnr) pcall(a.nvim_set_current_win, original_win_id) end diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 6e8b36b..77f88f3 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -731,23 +731,15 @@ end ---@param status table: table containing information on the picker --- and associated windows. Generally obtained from `state.get_status` function Picker.close_windows(status) - local prompt_win = status.prompt_win - local results_win = status.results_win - local preview_win = status.preview_win + utils.win_delete("results_win", status.results_win, true, true) + utils.win_delete("preview_win", status.preview_win, true, true) - local prompt_border_win = status.prompt_border_win - local results_border_win = status.results_border_win - local preview_border_win = status.preview_border_win - - utils.win_delete("results_win", results_win, true, true) - utils.win_delete("preview_win", preview_win, true, true) - - utils.win_delete("prompt_border_win", prompt_border_win, true, true) - utils.win_delete("results_border_win", results_border_win, true, true) - utils.win_delete("preview_border_win", preview_border_win, true, true) + utils.win_delete("prompt_border_win", status.prompt_border_win, true, true) + utils.win_delete("results_border_win", status.results_border_win, true, true) + utils.win_delete("preview_border_win", status.preview_border_win, true, true) vim.defer_fn(function() - utils.win_delete("prompt_win", prompt_win, true) + utils.win_delete("prompt_win", status.prompt_win, true) end, 10) state.clear_status(status.prompt_bufnr) @@ -1468,6 +1460,11 @@ function pickers.on_close_prompt(prompt_bufnr) picker.close_windows(status) mappings.clear(prompt_bufnr) + vim.api.nvim_clear_autocmds { + group = "PickerInsert", + event = "BufLeave", + buffer = prompt_bufnr, + } end function pickers.on_resize_window(prompt_bufnr) diff --git a/lua/telescope/previewers/init.lua b/lua/telescope/previewers/init.lua index 1e28e41..4b20f06 100644 --- a/lua/telescope/previewers/init.lua +++ b/lua/telescope/previewers/init.lua @@ -95,9 +95,6 @@ end --- --- Furthermore, it will forward all `config.set_env` environment variables to --- that terminal process. ---- ---- While this interface is a good start, it was replaced with the way more ---- flexible `buffer_previewer` and is now deprecated. previewers.new_termopen_previewer = term_previewer.new_termopen_previewer --- Provides a `termopen_previewer` which has the ability to display files. diff --git a/lua/telescope/previewers/term_previewer.lua b/lua/telescope/previewers/term_previewer.lua index 7402796..1cbb6f8 100644 --- a/lua/telescope/previewers/term_previewer.lua +++ b/lua/telescope/previewers/term_previewer.lua @@ -1,14 +1,9 @@ local conf = require("telescope.config").values local utils = require "telescope.utils" local Path = require "plenary.path" -local putils = require "telescope.previewers.utils" local from_entry = require "telescope.from_entry" local Previewer = require "telescope.previewers.previewer" -local flatten = vim.tbl_flatten -local buf_delete = utils.buf_delete -local job_is_running = utils.job_is_running - local defaulter = utils.make_default_callable local previewers = {} @@ -56,7 +51,7 @@ local bat_maker = function(filename, lnum, start, finish) end end - return flatten { + return vim.tbl_flatten { command, bat_options, "--", @@ -120,27 +115,24 @@ previewers.new_termopen_previewer = function(opts) local opt_teardown = opts.teardown local old_bufs = {} + local bufentry_table = {} + local term_ids = {} local function get_term_id(self) - if not self.state then - return nil + if self.state then + return self.state.termopen_id end - return self.state.termopen_id end local function get_bufnr(self) - if not self.state then - return nil + if self.state then + return self.state.termopen_bufnr end - return self.state.termopen_bufnr end local function set_term_id(self, value) - if job_is_running(get_term_id(self)) then - vim.fn.jobstop(get_term_id(self)) - end - if self.state then - self.state.termopen_id = value + if self.state and term_ids[self.state.termopen_bufnr] == nil then + term_ids[self.state.termopen_bufnr] = value end end @@ -153,6 +145,18 @@ previewers.new_termopen_previewer = function(opts) end end + local function get_bufnr_by_bufentry(self, value) + if self.state then + return bufentry_table[value] + end + end + + local function set_bufentry(self, value) + if self.state and value then + bufentry_table[value] = get_bufnr(self) + end + end + function opts.setup(self) local state = {} if opt_setup then @@ -166,17 +170,17 @@ previewers.new_termopen_previewer = function(opts) opt_teardown(self) end - local term_id = get_term_id(self) - if term_id and utils.job_is_running(term_id) then - vim.fn.jobclose(term_id) - end - - set_term_id(self, nil) set_bufnr(self, nil) + set_bufentry(self, nil) for _, bufnr in ipairs(old_bufs) do - buf_delete(bufnr) + local term_id = term_ids[bufnr] + if term_id and utils.job_is_running(term_id) then + vim.fn.jobstop(term_id) + end + utils.buf_delete(bufnr) end + bufentry_table = {} end function opts.preview_fn(self, entry, status) @@ -184,24 +188,28 @@ previewers.new_termopen_previewer = function(opts) set_bufnr(self, vim.api.nvim_win_get_buf(status.preview_win)) end - set_bufnr(self, vim.api.nvim_create_buf(false, true)) + local prev_bufnr = get_bufnr_by_bufentry(self, entry) + if prev_bufnr then + self.state.bufnr = prev_bufnr + vim.api.nvim_win_set_buf(status.preview_win, self.state.bufnr) + else + local bufnr = vim.api.nvim_create_buf(false, true) + set_bufnr(self, bufnr) + vim.api.nvim_win_set_buf(status.preview_win, bufnr) - local bufnr = get_bufnr(self) - vim.api.nvim_win_set_buf(status.preview_win, bufnr) + local term_opts = { + cwd = opts.cwd or vim.loop.cwd(), + env = conf.set_env, + } - local term_opts = { - cwd = opts.cwd or vim.fn.getcwd(), - env = conf.set_env, - } - - putils.with_preview_window(status, bufnr, function() local cmd = opts.get_command(entry, status) if cmd then - set_term_id(self, vim.fn.termopen(cmd, term_opts)) + vim.api.nvim_buf_call(bufnr, function() + set_term_id(self, vim.fn.termopen(cmd, term_opts)) + end) end - end) - - vim.api.nvim_buf_set_name(bufnr, tostring(bufnr)) + set_bufentry(self, entry) + end end if not opts.send_input then