aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui/term_input.inl
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/tui/term_input.inl')
-rw-r--r--src/nvim/tui/term_input.inl62
1 files changed, 54 insertions, 8 deletions
diff --git a/src/nvim/tui/term_input.inl b/src/nvim/tui/term_input.inl
index 0c0e6c07c9..dba970e8f2 100644
--- a/src/nvim/tui/term_input.inl
+++ b/src/nvim/tui/term_input.inl
@@ -1,10 +1,12 @@
#include <termkey.h>
#include "nvim/ascii.h"
+#include "nvim/misc2.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
#include "nvim/os/rstream.h"
+#define PASTETOGGLE_KEY "<f37>"
struct term_input {
int in_fd;
@@ -113,7 +115,7 @@ static int get_key_code_timeout(void)
bool timeout = false;
// Check 'timeout' and 'ttimeout' to determine if we should send ESC
// after 'ttimeoutlen'. See :help 'ttimeout' for more information
- Error err;
+ Error err = ERROR_INIT;
timeout = vim_get_option(cstr_as_string("timeout"), &err).data.boolean;
if (!timeout) {
timeout = vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean;
@@ -164,6 +166,49 @@ static void timer_cb(uv_timer_t *handle)
tk_getkeys(handle->data, true);
}
+static bool handle_bracketed_paste(TermInput *input)
+{
+ char *ptr = rbuffer_read_ptr(input->read_buffer);
+ size_t len = rbuffer_pending(input->read_buffer);
+ if (len > 5 && (!strncmp(ptr, "\x1b[200~", 6)
+ || !strncmp(ptr, "\x1b[201~", 6))) {
+ bool enable = ptr[4] == '0';
+ // Advance past the sequence
+ rbuffer_consumed(input->read_buffer, 6);
+ if (enable) {
+ // Get the current mode
+ int state = get_real_state();
+ if (state & NORMAL) {
+ // Enter insert mode
+ input_enqueue(cstr_as_string("i"));
+ } else if (state & VISUAL) {
+ // Remove the selected text and enter insert mode
+ input_enqueue(cstr_as_string("c"));
+ } else if (!(state & INSERT)) {
+ // Don't mess with the paste option
+ return true;
+ }
+ }
+ input_enqueue(cstr_as_string(PASTETOGGLE_KEY));
+ return true;
+ }
+ return false;
+}
+
+static bool handle_forced_escape(TermInput *input)
+{
+ char *ptr = rbuffer_read_ptr(input->read_buffer);
+ size_t len = rbuffer_pending(input->read_buffer);
+ if (len > 1 && ptr[0] == ESC && ptr[1] == NUL) {
+ // skip the ESC and NUL and push one <esc> to the input buffer
+ termkey_push_bytes(input->tk, ptr, 1);
+ rbuffer_consumed(input->read_buffer, 2);
+ tk_getkeys(input, true);
+ return true;
+ }
+ return false;
+}
+
static void read_cb(RStream *rstream, void *rstream_data, bool eof)
{
if (eof) {
@@ -174,15 +219,11 @@ static void read_cb(RStream *rstream, void *rstream_data, bool eof)
TermInput *input = rstream_data;
do {
- char *ptr = rbuffer_read_ptr(input->read_buffer);
- size_t len = rbuffer_pending(input->read_buffer);
- if (len > 1 && ptr[0] == ESC && ptr[1] == NUL) {
- // skip the ESC and NUL and push one <esc> to the input buffer
- termkey_push_bytes(input->tk, ptr, 1);
- rbuffer_consumed(input->read_buffer, 2);
- tk_getkeys(input, true);
+ if (handle_bracketed_paste(input) || handle_forced_escape(input)) {
continue;
}
+ char *ptr = rbuffer_read_ptr(input->read_buffer);
+ size_t len = rbuffer_pending(input->read_buffer);
// Find the next 'esc' and push everything up to it(excluding)
size_t i;
for (i = ptr[0] == ESC ? 1 : 0; i < len; i++) {
@@ -228,6 +269,11 @@ static TermInput *term_input_new(void)
// initialize a timer handle for handling ESC with libtermkey
uv_timer_init(uv_default_loop(), &rv->timer_handle);
rv->timer_handle.data = rv;
+ // Set the pastetoggle option to a special key that will be sent when
+ // \e[20{0,1}~/ are received
+ Error err = ERROR_INIT;
+ vim_set_option(cstr_as_string("pastetoggle"),
+ STRING_OBJ(cstr_as_string(PASTETOGGLE_KEY)), &err);
return rv;
}