Skip to content

fix: use :startinsert instead of feedkeys to switch to terminal mode #2034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lua/fzf-lua/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,10 @@ M.complete = function(selected, opts)
newline = line:sub(1, col) .. selected[1] .. after
newcol = col + #selected[1]
end
if opts.__CTX.mode == "t" and vim.bo[opts.__CTX.bufnr].buftype == "terminal" then
vim.api.nvim_chan_send(vim.bo.channel, newline)
return
end
vim.api.nvim_set_current_line(newline or opts.__CTX.line)
vim.api.nvim_win_set_cursor(0, { opts.__CTX.cursor[1], newcol or col })
if opts.__CTX.mode == "i" then
Expand Down
12 changes: 5 additions & 7 deletions lua/fzf-lua/fzf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ function M.raw_fzf(contents, fzf_cli_args, opts)
vim.keymap.set("t", "<C-c>", "<Esc>", { buffer = 0 })
end

-- local fzf_bufnr = vim.api.nvim_get_current_buf()
-- vim.api.nvim_create_autocmd("TermOpen", { once = true, buffer = fzf_bufnr, command = "startinsert" })
-- vim.api.nvim_create_autocmd("TermOpen",
-- { once = true, buffer = fzf_bufnr, callback = function() utils.ensure_startinsert(fzf_bufnr) end })
-- A more robust way of entering TERMINAL mode "t". We had quite a few issues
-- sending `feedkeys|startinsert` after the term job is started, this approach
-- seems more consistent as it triggers when entering terminal normal mode "nt"
Expand Down Expand Up @@ -333,14 +337,8 @@ function M.raw_fzf(contents, fzf_cli_args, opts)
-- fzf-tmux spawns outside neovim, don't set filetype/insert mode
if not opts.is_fzf_tmux then
vim.bo.filetype = "fzf"

-- See note in "ModeChanged" above
if vim.api.nvim_get_mode().mode == "t" then
-- Called from another fzf-win most likely
utils.feed_keys_termcodes("i")
else
vim.cmd [[startinsert]]
end
utils.ensure_startinsert()
end

return coroutine.yield()
Expand Down
22 changes: 22 additions & 0 deletions lua/fzf-lua/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,28 @@ function M.setmetatable__gc(t, mt)
return setmetatable(t, mt)
end

---@param bufnr integer?
---@param retry integer?
---@param timeout integer?
function M.ensure_startinsert(bufnr, retry, timeout)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local function ensure_startinsert(_retry, _timeout)
if _retry == 0 then return end
-- abort for some reason we switch to another buffer
if vim.api.nvim_get_current_buf() ~= bufnr then return end
if vim.api.nvim_get_mode().mode ~= "t" then
vim.cmd [[startinsert]]
return
end
-- Called from another fzf-win most likely
-- don't startinsert until we enter new terminal mode
return vim.defer_fn(function()
return ensure_startinsert(_retry - 1, math.min(100, _timeout * 2))
end, _timeout)
end
return ensure_startinsert(retry or 5, timeout or 10)
end

--- Checks if treesitter parser for language is installed
---@param lang string
function M.has_ts_parser(lang)
Expand Down
21 changes: 21 additions & 0 deletions tests/file/ui_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,25 @@ T["files()"]["preview should work after chdir #1864"] = function()
child.expect_screen_lines(screen_opts)
end

T["files()"]["perioldly reset mode"] = function()
child.cmd [[exe 'au TermOpen * startinsert' | term]]
sleep(10)
child.lua [=[
FzfLua.files {
cwd_prompt = false,
fzf_opts = { ["--no-info"] = "", ["--info"] = false },
query = "foo",
}
]=]
child.wait_until(function() return child.lua_get([[_G._fzf_load_called]]) == true end)
-- child.expect_screen_lines({ start_line = 1, end_line = 3 })
-- print("\n")
-- print(child.get_screen_lines({ start_line = 1, end_line = 3 }))
child.assert_screen_lines([[
╭─────────────────── Files h ────────────────────╮
│> foo │
│──────────────────────────────────────────────── │
]], { start_line = 3, end_line = 5 })
end

return T
Loading