tui: Don't use 'pastetoggle' for automatic pasting

Add a new special key that can be used by UIs to toggle the 'paste' option and
use it in the TUI instead of the user's 'pastetoggle' value.

Close #2843 #2092
This commit is contained in:
Thiago de Arruda
2015-09-25 10:30:20 -03:00
parent c1edd07990
commit 1143b416ab
6 changed files with 97 additions and 29 deletions

View File

@@ -302,7 +302,7 @@ getcmdline (
input_enable_events();
do {
c = safe_vgetc();
} while (c == K_IGNORE);
} while (c == K_IGNORE || c == K_PASTE);
input_disable_events();
if (c == K_EVENT) {

View File

@@ -153,6 +153,7 @@ static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf.tb_buf */
static char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */
static int last_recorded_len = 0; /* number of last recorded chars */
static const uint8_t ui_toggle[] = { K_SPECIAL, KS_EXTRA, KE_PASTE, 0 };
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "getchar.c.generated.h"
@@ -1873,14 +1874,15 @@ static int vgetorpeek(int advance)
}
}
/* Check for match with 'pastetoggle' */
if (*p_pt != NUL && mp == NULL && (State & (INSERT|NORMAL))) {
for (mlen = 0; mlen < typebuf.tb_len && p_pt[mlen];
++mlen)
if (p_pt[mlen] != typebuf.tb_buf[typebuf.tb_off
+ mlen])
break;
if (p_pt[mlen] == NUL) { /* match */
// Check for a key that can toggle the 'paste' option
if (mp == NULL && (State & (INSERT|NORMAL))) {
bool match = typebuf_match_len(ui_toggle, &mlen);
if (!match && mlen != typebuf.tb_len && *p_pt != NUL) {
// didn't match ui_toggle_key and didn't try the whole typebuf,
// check the 'pastetoggle'
match = typebuf_match_len(p_pt, &mlen);
}
if (match) {
/* write chars to script file(s) */
if (mlen > typebuf.tb_maplen)
gotchars(typebuf.tb_buf + typebuf.tb_off
@@ -4238,3 +4240,14 @@ static char_u * translate_mapping (
ga_append(&ga, NUL);
return (char_u *)(ga.ga_data);
}
static bool typebuf_match_len(const uint8_t *str, int *mlen)
{
int i;
for (i = 0; i < typebuf.tb_len && str[i]; i++) {
if (str[i] != typebuf.tb_buf[typebuf.tb_off + i])
break;
}
*mlen = i;
return str[i] == NUL; // matched the whole string
}

View File

@@ -284,6 +284,7 @@ static struct key_name_entry {
{K_SNR, (char_u *)"SNR"},
{K_PLUG, (char_u *)"Plug"},
{K_CURSORHOLD, (char_u *)"CursorHold"},
{K_PASTE, (char_u *)"Paste"},
{0, NULL}
};

View File

@@ -247,6 +247,8 @@ enum key_extra {
, KE_FOCUSGAINED /* focus gained */
, KE_FOCUSLOST /* focus lost */
, KE_EVENT // event
, KE_PASTE // special key to toggle the 'paste' option.
// sent only by UIs
};
/*
@@ -437,6 +439,7 @@ enum key_extra {
#define K_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE)
/* Bits for modifier mask */
/* 0x01 cannot be used, because the modifier must be 0x02 or higher */

View File

@@ -9,7 +9,7 @@
#include "nvim/os/input.h"
#include "nvim/event/rstream.h"
#define PASTETOGGLE_KEY "<f37>"
#define PASTETOGGLE_KEY "<Paste>"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/input.c.generated.h"
@@ -34,11 +34,6 @@ void term_input_init(TermInput *input, Loop *loop)
rstream_init_fd(loop, &input->read_stream, input->in_fd, 0xfff, input);
// initialize a timer handle for handling ESC with libtermkey
time_watcher_init(loop, &input->timer_handle, input);
// 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);
}
void term_input_destroy(TermInput *input)
@@ -230,20 +225,6 @@ static bool handle_bracketed_paste(TermInput *input)
if (input->paste_enabled == enable) {
return true;
}
if (enable) {
// Get the current mode
int state = get_real_state();
if (state & NORMAL) {
// Enter insert mode
enqueue_input("i", 1);
} else if (state & VISUAL) {
// Remove the selected text and enter insert mode
enqueue_input("c", 1);
} else if (!(state & INSERT)) {
// Don't mess with the paste option
return true;
}
}
enqueue_input(PASTETOGGLE_KEY, sizeof(PASTETOGGLE_KEY) - 1);
input->paste_enabled = enable;
return true;

View File

@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')
local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim
local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq
local expect = helpers.expect
local Screen = require('test.functional.ui.screen')
describe('mappings', function()
local cid
@@ -40,7 +41,76 @@ describe('mappings', function()
end)
end)
describe('feeding large chunks of input with <Paste>', function()
local screen
before_each(function()
clear()
screen = Screen.new()
screen:attach()
execute('set ruler')
end)
it('ok', function()
local t = {}
for i = 1, 20000 do
t[i] = 'item ' .. tostring(i)
end
feed('i<Paste>')
screen:expect([[
^ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
-- INSERT (paste) -- |
]])
feed(table.concat(t, '<Enter>'))
screen:expect([[
item 19988 |
item 19989 |
item 19990 |
item 19991 |
item 19992 |
item 19993 |
item 19994 |
item 19995 |
item 19996 |
item 19997 |
item 19998 |
item 19999 |
item 20000^ |
-- INSERT (paste) -- |
]])
feed('<Paste>')
screen:expect([[
item 19988 |
item 19989 |
item 19990 |
item 19991 |
item 19992 |
item 19993 |
item 19994 |
item 19995 |
item 19996 |
item 19997 |
item 19998 |
item 19999 |
item 20000^ |
-- INSERT -- 20000,11 Bot |
]])
end)
end)
describe('input utf sequences that contain CSI/K_SPECIAL', function()
before_each(clear)
it('ok', function()
feed('i…<esc>')
expect('')