mirror of
https://github.com/neovim/neovim.git
synced 2026-03-30 20:32:08 +00:00
fix(terminal): handle opening terminal on unloaded buffer (#37894)
Problem: Strange behavior when opening terminal on unloaded buffer.
Solution: For nvim_open_term() ensure the buffer is loaded as it needs
to be read into the terminal. For jobstart() just open the
memfile as the file content isn't needed.
Not going to make nvim_open_term() pass stdin to the terminal when stdin
isn't read into a buffer yet, as other APIs don't read stdin on unloaded
buffer either. There are also other problems with loading buffer before
reading stdin, so it's better to address those in another PR.
This commit is contained in:
@@ -49,7 +49,7 @@
|
||||
#include "api/buffer.c.generated.h"
|
||||
|
||||
/// Ensures that a buffer is loaded.
|
||||
static buf_T *api_buf_ensure_loaded(Buffer buffer, Error *err)
|
||||
buf_T *api_buf_ensure_loaded(Buffer buffer, Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
if (!buf) {
|
||||
|
||||
@@ -1106,7 +1106,7 @@ Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
buf_T *buf = api_buf_ensure_loaded(buffer, err);
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3611,6 +3611,15 @@ void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
const int pid = chan->stream.pty.proc.pid;
|
||||
buf_T *const buf = curbuf;
|
||||
|
||||
// If the buffer isn't loaded, open a memfile here to avoid spurious autocommands
|
||||
// from open_buffer() when updating the terminal buffer later.
|
||||
if (buf->b_ml.ml_mfp == NULL && ml_open(buf) == FAIL) {
|
||||
// Internal error in ml_open(): stop the job.
|
||||
proc_stop(&chan->stream.proc);
|
||||
channel_decref(chan);
|
||||
return;
|
||||
}
|
||||
|
||||
channel_incref(chan);
|
||||
channel_terminal_alloc(buf, chan);
|
||||
|
||||
|
||||
@@ -936,6 +936,61 @@ describe('startup', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
describe('opening a terminal before buffers are loaded #30765', function()
|
||||
local lines = {} --- @type string[]
|
||||
for i = 1, 50 do
|
||||
lines[#lines + 1] = ('line%d'):format(i)
|
||||
end
|
||||
|
||||
setup(function()
|
||||
write_file('Xsomefile', table.concat(lines, '\n') .. '\n')
|
||||
end)
|
||||
|
||||
teardown(function()
|
||||
os.remove('Xsomefile')
|
||||
end)
|
||||
|
||||
it('sends buffer content to terminal with nvim_open_term()', function()
|
||||
clear({
|
||||
args_rm = { '--headless' },
|
||||
args = {
|
||||
'Xsomefile',
|
||||
'--cmd',
|
||||
'let g:chan = nvim_open_term(0, {}) | startinsert',
|
||||
'--cmd',
|
||||
'call chansend(g:chan, "new_line1\nnew_line2\nnew_line3")',
|
||||
},
|
||||
})
|
||||
local screen = Screen.new(50, 7)
|
||||
screen:expect([[
|
||||
line48 |
|
||||
line49 |
|
||||
line50 |
|
||||
new_line1 |
|
||||
new_line2 |
|
||||
new_line3^ |
|
||||
{5:-- TERMINAL --} |
|
||||
]])
|
||||
eq(lines, api.nvim_buf_get_lines(0, 0, #lines, true))
|
||||
end)
|
||||
|
||||
it('does not error with jobstart(…,{term=true})', function()
|
||||
clear({
|
||||
args_rm = { '--headless' },
|
||||
args = {
|
||||
'Xsomefile',
|
||||
'--cmd',
|
||||
('lua vim.fn.jobstart({%q}, {term = true})'):format(n.testprg('tty-test')),
|
||||
},
|
||||
})
|
||||
local screen = Screen.new(50, 7)
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
|*6
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('startup', function()
|
||||
|
||||
Reference in New Issue
Block a user