mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
TUI/paste: collect data, invoke user callback #4448
This commit is contained in:
parent
21f0f7bca5
commit
75663aaf0f
@ -102,17 +102,65 @@ static void tinput_done_event(void **argv)
|
|||||||
input_done();
|
input_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Array string_to_array(const String input)
|
||||||
|
{
|
||||||
|
Array ret = { .size = 0, .items = NULL };
|
||||||
|
for (size_t i = 0; i < input.size; i++) {
|
||||||
|
const char *const start = input.data + i;
|
||||||
|
const char *const end = xmemscan(start, NL, input.size - i);
|
||||||
|
i += (size_t) (end - start);
|
||||||
|
ret.size++;
|
||||||
|
}
|
||||||
|
ret.items = xmalloc(ret.size * sizeof(*ret.items));
|
||||||
|
size_t array_idx = 0;
|
||||||
|
for (size_t i = 0; i < input.size; i++) {
|
||||||
|
const char *const start = input.data + i;
|
||||||
|
const size_t line_len
|
||||||
|
= (size_t) ((char *) xmemscan(start, NL, input.size - i)
|
||||||
|
- start);
|
||||||
|
i += line_len;
|
||||||
|
|
||||||
|
String item = {
|
||||||
|
.size = line_len,
|
||||||
|
.data = xmemdupz(start, line_len),
|
||||||
|
};
|
||||||
|
memchrsub(item.data, NUL, NL, line_len);
|
||||||
|
ret.items[array_idx++] = STRING_OBJ(item);
|
||||||
|
}
|
||||||
|
ret.capacity = ret.size;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void tinput_wait_enqueue(void **argv)
|
static void tinput_wait_enqueue(void **argv)
|
||||||
{
|
{
|
||||||
TermInput *input = argv[0];
|
TermInput *input = argv[0];
|
||||||
RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) {
|
RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) {
|
||||||
size_t consumed = input_enqueue((String){.data = buf, .size = len});
|
const String keys = { .data = buf, .size = len };
|
||||||
if (consumed) {
|
if (input->paste_enabled) {
|
||||||
rbuffer_consumed(input->key_buffer, consumed);
|
Object keys_array = ARRAY_OBJ(string_to_array(keys));
|
||||||
}
|
Array args = { .capacity = 1, .size = 1, .items = &keys_array };
|
||||||
rbuffer_reset(input->key_buffer);
|
Error err = ERROR_INIT;
|
||||||
if (consumed < len) {
|
Object fret = nvim_call_function(STATIC_CSTR_AS_STRING("PasteCallback"),
|
||||||
break;
|
args, &err);
|
||||||
|
if ((fret.type == kObjectTypeInteger && fret.data.integer)
|
||||||
|
|| (fret.type == kObjectTypeBoolean && fret.data.boolean)
|
||||||
|
|| (fret.type == kObjectTypeString && fret.data.string.size)) {
|
||||||
|
input->paste_enabled = false;
|
||||||
|
}
|
||||||
|
api_free_object(fret);
|
||||||
|
api_free_object(keys_array);
|
||||||
|
rbuffer_consumed(input->key_buffer, len);
|
||||||
|
rbuffer_reset(input->key_buffer);
|
||||||
|
} else {
|
||||||
|
const size_t consumed = input_enqueue(keys);
|
||||||
|
if (consumed) {
|
||||||
|
rbuffer_consumed(input->key_buffer, consumed);
|
||||||
|
}
|
||||||
|
rbuffer_reset(input->key_buffer);
|
||||||
|
if (consumed < len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uv_mutex_lock(&input->key_buffer_mutex);
|
uv_mutex_lock(&input->key_buffer_mutex);
|
||||||
@ -293,7 +341,7 @@ static void tk_getkeys(TermInput *input, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != TERMKEY_RES_AGAIN) {
|
if (result != TERMKEY_RES_AGAIN || input->paste_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// else: Partial keypress event was found in the buffer, but it does not
|
// else: Partial keypress event was found in the buffer, but it does not
|
||||||
@ -345,33 +393,25 @@ static bool handle_bracketed_paste(TermInput *input)
|
|||||||
&& (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6)
|
&& (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6)
|
||||||
|| !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
|
|| !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
|
||||||
bool enable = *rbuffer_get(input->read_stream.buffer, 4) == '0';
|
bool enable = *rbuffer_get(input->read_stream.buffer, 4) == '0';
|
||||||
|
if (input->paste_enabled && enable) {
|
||||||
|
// Pasting "enable paste" code literally.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Advance past the sequence
|
// Advance past the sequence
|
||||||
rbuffer_consumed(input->read_stream.buffer, 6);
|
rbuffer_consumed(input->read_stream.buffer, 6);
|
||||||
if (enable && input->paste_enabled) {
|
if (input->paste_enabled == enable) {
|
||||||
// Bogus "paste start"; forward it.
|
|
||||||
tinput_enqueue(input, "<C-v><Esc>200~", sizeof("<C-v><Esc>200~") - 1);
|
|
||||||
return true;
|
|
||||||
} else if (!enable && !input->paste_enabled) {
|
|
||||||
// Bogus "paste stop"; ignore it.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
input->paste_enabled = enable;
|
if (!enable) {
|
||||||
if (enable) {
|
tinput_flush(input, true);
|
||||||
loop_schedule(&main_loop, event_create(apply_pastepre, 0));
|
|
||||||
} else {
|
|
||||||
tinput_enqueue(input, PASTEPOST_KEY, sizeof(PASTEPOST_KEY) - 1);
|
|
||||||
}
|
}
|
||||||
|
input->paste_enabled = enable;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_pastepre(void **argv) // MAIN thread
|
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool handle_forced_escape(TermInput *input)
|
static bool handle_forced_escape(TermInput *input)
|
||||||
{
|
{
|
||||||
if (rbuffer_size(input->read_stream.buffer) > 1
|
if (rbuffer_size(input->read_stream.buffer) > 1
|
||||||
|
Loading…
Reference in New Issue
Block a user