mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
feat(nvim_open_term): convert LF => CRLF (#26384)
Problem: Unlike termopen(), nvim_open_term() PTYs do not carriage-return the cursor on newline ("\n") input. nvim --clean :let chan_id = nvim_open_term(1, {}) :call chansend(chan_id, ["here", "are", "some", "lines"]) Actual behavior: here are some lines Expected behaviour: here are some lines Solution: Add `force_crlf` option, and enable it by default.
This commit is contained in:
parent
36552adb39
commit
619407eb54
@ -1231,6 +1231,8 @@ nvim_open_term({buffer}, {*opts}) *nvim_open_term()*
|
||||
is sent as a "\r", not as a "\n". |textlock| applies. It
|
||||
is possible to call |nvim_chan_send()| directly in the
|
||||
callback however. ["input", term, bufnr, data]
|
||||
• force_crlf: (boolean, default true) Convert "\n" to
|
||||
"\r\n".
|
||||
|
||||
Return: ~
|
||||
Channel id, or 0 on error
|
||||
|
@ -344,6 +344,8 @@ The following changes to existing APIs or features add new behavior.
|
||||
• Diagnostic sign text is no longer configured with |sign_define()|.
|
||||
Use |vim.diagnostic.config()| instead.
|
||||
|
||||
• Added "force_crlf" option field in |nvim_open_term()|.
|
||||
|
||||
==============================================================================
|
||||
REMOVED FEATURES *news-removed*
|
||||
|
||||
|
2
runtime/lua/vim/_meta/api.lua
generated
2
runtime/lua/vim/_meta/api.lua
generated
@ -1446,6 +1446,8 @@ function vim.api.nvim_notify(msg, log_level, opts) end
|
||||
--- is sent as a "\r", not as a "\n". `textlock` applies. It
|
||||
--- is possible to call `nvim_chan_send()` directly in the
|
||||
--- callback however. ["input", term, bufnr, data]
|
||||
--- • force_crlf: (boolean, default true) Convert "\n" to
|
||||
--- "\r\n".
|
||||
--- @return integer
|
||||
function vim.api.nvim_open_term(buffer, opts) end
|
||||
|
||||
|
1
runtime/lua/vim/_meta/api_keysets.lua
generated
1
runtime/lua/vim/_meta/api_keysets.lua
generated
@ -217,6 +217,7 @@ error('Cannot require a meta file')
|
||||
|
||||
--- @class vim.api.keyset.open_term
|
||||
--- @field on_input? function
|
||||
--- @field force_crlf? boolean
|
||||
|
||||
--- @class vim.api.keyset.option
|
||||
--- @field scope? string
|
||||
|
@ -344,4 +344,5 @@ typedef struct {
|
||||
typedef struct {
|
||||
OptionalKeys is_set__open_term_;
|
||||
LuaRef on_input;
|
||||
Boolean force_crlf;
|
||||
} Dict(open_term);
|
||||
|
@ -985,6 +985,7 @@ fail:
|
||||
/// as a "\r", not as a "\n". |textlock| applies. It is possible
|
||||
/// to call |nvim_chan_send()| directly in the callback however.
|
||||
/// ["input", term, bufnr, data]
|
||||
/// - force_crlf: (boolean, default true) Convert "\n" to "\r\n".
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Channel id, or 0 on error
|
||||
Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
|
||||
@ -1002,7 +1003,6 @@ Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
|
||||
}
|
||||
|
||||
LuaRef cb = LUA_NOREF;
|
||||
|
||||
if (HAS_KEY(opts, open_term, on_input)) {
|
||||
cb = opts->on_input;
|
||||
opts->on_input = LUA_NOREF;
|
||||
@ -1020,6 +1020,7 @@ Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
|
||||
.write_cb = term_write,
|
||||
.resize_cb = term_resize,
|
||||
.close_cb = term_close,
|
||||
.force_crlf = GET_BOOL_OR_TRUE(opts, open_term, force_crlf),
|
||||
};
|
||||
channel_incref(chan);
|
||||
terminal_open(&chan->term, buf, topts);
|
||||
|
@ -801,6 +801,7 @@ void channel_terminal_open(buf_T *buf, Channel *chan)
|
||||
.write_cb = term_write,
|
||||
.resize_cb = term_resize,
|
||||
.close_cb = term_close,
|
||||
.force_crlf = false,
|
||||
};
|
||||
buf->b_p_channel = (OptInt)chan->id; // 'channel' option
|
||||
channel_incref(chan);
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <vterm.h>
|
||||
#include <vterm_keycodes.h>
|
||||
|
||||
#include "klib/kvec.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/ascii_defs.h"
|
||||
@ -80,6 +81,7 @@
|
||||
#include "nvim/optionstr.h"
|
||||
#include "nvim/pos_defs.h"
|
||||
#include "nvim/state.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/terminal.h"
|
||||
#include "nvim/types_defs.h"
|
||||
#include "nvim/ui.h"
|
||||
@ -786,7 +788,21 @@ void terminal_receive(Terminal *term, const char *data, size_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
vterm_input_write(term->vt, data, len);
|
||||
if (term->opts.force_crlf) {
|
||||
StringBuilder crlf_data = KV_INITIAL_VALUE;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (data[i] == '\n' && (i == 0 || (i > 0 && data[i - 1] != '\r'))) {
|
||||
kv_push(crlf_data, '\r');
|
||||
}
|
||||
kv_push(crlf_data, data[i]);
|
||||
}
|
||||
|
||||
vterm_input_write(term->vt, crlf_data.items, kv_size(crlf_data));
|
||||
kv_destroy(crlf_data);
|
||||
} else {
|
||||
vterm_input_write(term->vt, data, len);
|
||||
}
|
||||
vterm_screen_flush_damage(term->vts);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ typedef struct {
|
||||
terminal_write_cb write_cb;
|
||||
terminal_resize_cb resize_cb;
|
||||
terminal_close_cb close_cb;
|
||||
bool force_crlf;
|
||||
} TerminalOptions;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
|
@ -192,4 +192,55 @@ describe('no crash when TermOpen autocommand', function()
|
||||
]]}
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it('nvim_open_term({force_crlf=true}) converts newlines', function()
|
||||
local buf = meths.create_buf(false, true)
|
||||
local win = meths.get_current_win()
|
||||
local term = meths.open_term(buf, {force_crlf = true})
|
||||
screen:try_resize(8, 10)
|
||||
meths.win_set_buf(win, buf)
|
||||
meths.chan_send(term, 'here\nthere\nfoo\r\nbar\n\ntest')
|
||||
screen:expect{grid=[[
|
||||
^here |
|
||||
there |
|
||||
foo |
|
||||
bar |
|
||||
|
|
||||
test |
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
|
|
||||
]]}
|
||||
meths.chan_send(term, '\nfirst')
|
||||
screen:expect{grid=[[
|
||||
^here |
|
||||
there |
|
||||
foo |
|
||||
bar |
|
||||
|
|
||||
test |
|
||||
first |
|
||||
{0:~ }|
|
||||
{0:~ }|
|
||||
|
|
||||
]]}
|
||||
meths.buf_delete(buf, {force = true})
|
||||
buf = meths.create_buf(false, true)
|
||||
term = meths.open_term(buf, {force_crlf = false})
|
||||
meths.win_set_buf(win, buf)
|
||||
meths.chan_send(term, 'here\nthere')
|
||||
screen:expect{grid=[[
|
||||
^here |
|
||||
there |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
]]}
|
||||
end)
|
||||
end)
|
||||
|
@ -576,21 +576,21 @@ describe("pending scrollback line handling", function()
|
||||
]]
|
||||
screen:expect [[
|
||||
{1: 1 }^a |
|
||||
{1: 2 } a |
|
||||
{1: 3 } a |
|
||||
{1: 4 } a |
|
||||
{1: 5 } a |
|
||||
{1: 6 } a |
|
||||
{1: 2 }a |
|
||||
{1: 3 }a |
|
||||
{1: 4 }a |
|
||||
{1: 5 }a |
|
||||
{1: 6 }a |
|
||||
|
|
||||
]]
|
||||
feed('G')
|
||||
screen:expect [[
|
||||
{1: 7 } a |
|
||||
{1: 8 } a |
|
||||
{1: 9 } a |
|
||||
{1: 10 } a |
|
||||
{1: 11 } a |
|
||||
{1: 12 } ^a |
|
||||
{1: 7 }a |
|
||||
{1: 8 }a |
|
||||
{1: 9 }a |
|
||||
{1: 10 }a |
|
||||
{1: 11 }a |
|
||||
{1: 12 }^a |
|
||||
|
|
||||
]]
|
||||
assert_alive()
|
||||
|
Loading…
Reference in New Issue
Block a user