mirror of
https://github.com/neovim/neovim.git
synced 2025-09-17 16:58:17 +00:00
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:
@@ -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) {
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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}
|
||||
};
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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('…')
|
||||
|
Reference in New Issue
Block a user