mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 01:08:20 +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();
|
input_enable_events();
|
||||||
do {
|
do {
|
||||||
c = safe_vgetc();
|
c = safe_vgetc();
|
||||||
} while (c == K_IGNORE);
|
} while (c == K_IGNORE || c == K_PASTE);
|
||||||
input_disable_events();
|
input_disable_events();
|
||||||
|
|
||||||
if (c == K_EVENT) {
|
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 char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */
|
||||||
|
|
||||||
static int last_recorded_len = 0; /* number of last recorded chars */
|
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
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "getchar.c.generated.h"
|
# include "getchar.c.generated.h"
|
||||||
@@ -1873,14 +1874,15 @@ static int vgetorpeek(int advance)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for match with 'pastetoggle' */
|
// Check for a key that can toggle the 'paste' option
|
||||||
if (*p_pt != NUL && mp == NULL && (State & (INSERT|NORMAL))) {
|
if (mp == NULL && (State & (INSERT|NORMAL))) {
|
||||||
for (mlen = 0; mlen < typebuf.tb_len && p_pt[mlen];
|
bool match = typebuf_match_len(ui_toggle, &mlen);
|
||||||
++mlen)
|
if (!match && mlen != typebuf.tb_len && *p_pt != NUL) {
|
||||||
if (p_pt[mlen] != typebuf.tb_buf[typebuf.tb_off
|
// didn't match ui_toggle_key and didn't try the whole typebuf,
|
||||||
+ mlen])
|
// check the 'pastetoggle'
|
||||||
break;
|
match = typebuf_match_len(p_pt, &mlen);
|
||||||
if (p_pt[mlen] == NUL) { /* match */
|
}
|
||||||
|
if (match) {
|
||||||
/* write chars to script file(s) */
|
/* write chars to script file(s) */
|
||||||
if (mlen > typebuf.tb_maplen)
|
if (mlen > typebuf.tb_maplen)
|
||||||
gotchars(typebuf.tb_buf + typebuf.tb_off
|
gotchars(typebuf.tb_buf + typebuf.tb_off
|
||||||
@@ -4238,3 +4240,14 @@ static char_u * translate_mapping (
|
|||||||
ga_append(&ga, NUL);
|
ga_append(&ga, NUL);
|
||||||
return (char_u *)(ga.ga_data);
|
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_SNR, (char_u *)"SNR"},
|
||||||
{K_PLUG, (char_u *)"Plug"},
|
{K_PLUG, (char_u *)"Plug"},
|
||||||
{K_CURSORHOLD, (char_u *)"CursorHold"},
|
{K_CURSORHOLD, (char_u *)"CursorHold"},
|
||||||
|
{K_PASTE, (char_u *)"Paste"},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -247,6 +247,8 @@ enum key_extra {
|
|||||||
, KE_FOCUSGAINED /* focus gained */
|
, KE_FOCUSGAINED /* focus gained */
|
||||||
, KE_FOCUSLOST /* focus lost */
|
, KE_FOCUSLOST /* focus lost */
|
||||||
, KE_EVENT // event
|
, 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_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
|
||||||
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
||||||
|
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE)
|
||||||
|
|
||||||
/* Bits for modifier mask */
|
/* Bits for modifier mask */
|
||||||
/* 0x01 cannot be used, because the modifier must be 0x02 or higher */
|
/* 0x01 cannot be used, because the modifier must be 0x02 or higher */
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/event/rstream.h"
|
#include "nvim/event/rstream.h"
|
||||||
|
|
||||||
#define PASTETOGGLE_KEY "<f37>"
|
#define PASTETOGGLE_KEY "<Paste>"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "tui/input.c.generated.h"
|
# 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);
|
rstream_init_fd(loop, &input->read_stream, input->in_fd, 0xfff, input);
|
||||||
// initialize a timer handle for handling ESC with libtermkey
|
// initialize a timer handle for handling ESC with libtermkey
|
||||||
time_watcher_init(loop, &input->timer_handle, input);
|
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)
|
void term_input_destroy(TermInput *input)
|
||||||
@@ -230,20 +225,6 @@ static bool handle_bracketed_paste(TermInput *input)
|
|||||||
if (input->paste_enabled == enable) {
|
if (input->paste_enabled == enable) {
|
||||||
return true;
|
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);
|
enqueue_input(PASTETOGGLE_KEY, sizeof(PASTETOGGLE_KEY) - 1);
|
||||||
input->paste_enabled = enable;
|
input->paste_enabled = enable;
|
||||||
return true;
|
return true;
|
||||||
|
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')
|
|||||||
local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim
|
local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim
|
||||||
local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq
|
local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq
|
||||||
local expect = helpers.expect
|
local expect = helpers.expect
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
|
||||||
describe('mappings', function()
|
describe('mappings', function()
|
||||||
local cid
|
local cid
|
||||||
@@ -40,7 +41,76 @@ describe('mappings', function()
|
|||||||
end)
|
end)
|
||||||
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()
|
describe('input utf sequences that contain CSI/K_SPECIAL', function()
|
||||||
|
before_each(clear)
|
||||||
it('ok', function()
|
it('ok', function()
|
||||||
feed('i…<esc>')
|
feed('i…<esc>')
|
||||||
expect('…')
|
expect('…')
|
||||||
|
Reference in New Issue
Block a user