mirror of
https://github.com/neovim/neovim.git
synced 2025-11-08 19:45:12 +00:00
Merge pull request #29114 from bfredl/key_buffer
refactor(tui): use a linear buffer for buffered keys
This commit is contained in:
@@ -28,7 +28,6 @@
|
|||||||
#include "nvim/msgpack_rpc/channel.h"
|
#include "nvim/msgpack_rpc/channel.h"
|
||||||
|
|
||||||
#define READ_STREAM_SIZE 0xfff
|
#define READ_STREAM_SIZE 0xfff
|
||||||
#define KEY_BUFFER_SIZE 0xfff
|
|
||||||
|
|
||||||
/// Size of libtermkey's internal input buffer. The buffer may grow larger than
|
/// Size of libtermkey's internal input buffer. The buffer may grow larger than
|
||||||
/// this when processing very long escape sequences, but will shrink back to
|
/// this when processing very long escape sequences, but will shrink back to
|
||||||
@@ -132,7 +131,6 @@ void tinput_init(TermInput *input, Loop *loop)
|
|||||||
input->key_encoding = kKeyEncodingLegacy;
|
input->key_encoding = kKeyEncodingLegacy;
|
||||||
input->ttimeout = (bool)p_ttimeout;
|
input->ttimeout = (bool)p_ttimeout;
|
||||||
input->ttimeoutlen = p_ttm;
|
input->ttimeoutlen = p_ttm;
|
||||||
input->key_buffer = rbuffer_new(KEY_BUFFER_SIZE);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) {
|
for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) {
|
||||||
pmap_put(int)(&kitty_key_map, kitty_key_map_entry[i].key, (ptr_t)kitty_key_map_entry[i].name);
|
pmap_put(int)(&kitty_key_map, kitty_key_map_entry[i].key, (ptr_t)kitty_key_map_entry[i].name);
|
||||||
@@ -165,7 +163,6 @@ void tinput_init(TermInput *input, Loop *loop)
|
|||||||
void tinput_destroy(TermInput *input)
|
void tinput_destroy(TermInput *input)
|
||||||
{
|
{
|
||||||
map_destroy(int, &kitty_key_map);
|
map_destroy(int, &kitty_key_map);
|
||||||
rbuffer_free(input->key_buffer);
|
|
||||||
uv_close((uv_handle_t *)&input->timer_handle, NULL);
|
uv_close((uv_handle_t *)&input->timer_handle, NULL);
|
||||||
rstream_may_close(&input->read_stream);
|
rstream_may_close(&input->read_stream);
|
||||||
termkey_destroy(input->tk);
|
termkey_destroy(input->tk);
|
||||||
@@ -191,44 +188,38 @@ static void tinput_done_event(void **argv)
|
|||||||
/// Send all pending input in key buffer to Nvim server.
|
/// Send all pending input in key buffer to Nvim server.
|
||||||
static void tinput_flush(TermInput *input)
|
static void tinput_flush(TermInput *input)
|
||||||
{
|
{
|
||||||
|
String keys = { .data = input->key_buffer, .size = input->key_buffer_len };
|
||||||
if (input->paste) { // produce exactly one paste event
|
if (input->paste) { // produce exactly one paste event
|
||||||
const size_t len = rbuffer_size(input->key_buffer);
|
|
||||||
String keys = { .data = xmallocz(len), .size = len };
|
|
||||||
rbuffer_read(input->key_buffer, keys.data, len);
|
|
||||||
MAXSIZE_TEMP_ARRAY(args, 3);
|
MAXSIZE_TEMP_ARRAY(args, 3);
|
||||||
ADD_C(args, STRING_OBJ(keys)); // 'data'
|
ADD_C(args, STRING_OBJ(keys)); // 'data'
|
||||||
ADD_C(args, BOOLEAN_OBJ(true)); // 'crlf'
|
ADD_C(args, BOOLEAN_OBJ(true)); // 'crlf'
|
||||||
ADD_C(args, INTEGER_OBJ(input->paste)); // 'phase'
|
ADD_C(args, INTEGER_OBJ(input->paste)); // 'phase'
|
||||||
rpc_send_event(ui_client_channel_id, "nvim_paste", args);
|
rpc_send_event(ui_client_channel_id, "nvim_paste", args);
|
||||||
api_free_string(keys);
|
|
||||||
if (input->paste == 1) {
|
if (input->paste == 1) {
|
||||||
// Paste phase: "continue"
|
// Paste phase: "continue"
|
||||||
input->paste = 2;
|
input->paste = 2;
|
||||||
}
|
}
|
||||||
rbuffer_reset(input->key_buffer);
|
|
||||||
} else { // enqueue input
|
} else { // enqueue input
|
||||||
RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) {
|
if (input->key_buffer_len > 0) {
|
||||||
const String keys = { .data = buf, .size = len };
|
|
||||||
MAXSIZE_TEMP_ARRAY(args, 1);
|
MAXSIZE_TEMP_ARRAY(args, 1);
|
||||||
ADD_C(args, STRING_OBJ(keys));
|
ADD_C(args, STRING_OBJ(keys));
|
||||||
// NOTE: This is non-blocking and won't check partially processed input,
|
// NOTE: This is non-blocking and won't check partially processed input,
|
||||||
// but should be fine as all big sends are handled with nvim_paste, not nvim_input
|
// but should be fine as all big sends are handled with nvim_paste, not nvim_input
|
||||||
rpc_send_event(ui_client_channel_id, "nvim_input", args);
|
rpc_send_event(ui_client_channel_id, "nvim_input", args);
|
||||||
rbuffer_consumed(input->key_buffer, len);
|
|
||||||
rbuffer_reset(input->key_buffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
input->key_buffer_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tinput_enqueue(TermInput *input, char *buf, size_t size)
|
static void tinput_enqueue(TermInput *input, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
if (rbuffer_size(input->key_buffer) >
|
if (input->key_buffer_len > KEY_BUFFER_SIZE - 0xff) {
|
||||||
rbuffer_capacity(input->key_buffer) - 0xff) {
|
// don't ever let the buffer get too full or we risk putting incomplete keys into it
|
||||||
// don't ever let the buffer get too full or we risk putting incomplete keys
|
|
||||||
// into it
|
|
||||||
tinput_flush(input);
|
tinput_flush(input);
|
||||||
}
|
}
|
||||||
rbuffer_write(input->key_buffer, buf, size);
|
size_t to_copy = MIN(size, KEY_BUFFER_SIZE - input->key_buffer_len);
|
||||||
|
memcpy(input->key_buffer + input->key_buffer_len, buf, to_copy);
|
||||||
|
input->key_buffer_len += to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle TERMKEY_KEYMOD_* modifiers, i.e. Shift, Alt and Ctrl.
|
/// Handle TERMKEY_KEYMOD_* modifiers, i.e. Shift, Alt and Ctrl.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ typedef enum {
|
|||||||
kKeyEncodingXterm, ///< Xterm's modifyOtherKeys encoding (XTMODKEYS)
|
kKeyEncodingXterm, ///< Xterm's modifyOtherKeys encoding (XTMODKEYS)
|
||||||
} KeyEncoding;
|
} KeyEncoding;
|
||||||
|
|
||||||
|
#define KEY_BUFFER_SIZE 0xfff
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int in_fd;
|
int in_fd;
|
||||||
// Phases: -1=all 0=disabled 1=first-chunk 2=continue 3=last-chunk
|
// Phases: -1=all 0=disabled 1=first-chunk 2=continue 3=last-chunk
|
||||||
@@ -34,8 +35,9 @@ typedef struct {
|
|||||||
uv_timer_t timer_handle;
|
uv_timer_t timer_handle;
|
||||||
Loop *loop;
|
Loop *loop;
|
||||||
RStream read_stream;
|
RStream read_stream;
|
||||||
RBuffer *key_buffer;
|
|
||||||
TUIData *tui_data;
|
TUIData *tui_data;
|
||||||
|
char key_buffer[KEY_BUFFER_SIZE];
|
||||||
|
size_t key_buffer_len;
|
||||||
} TermInput;
|
} TermInput;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
Reference in New Issue
Block a user