mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 8.1.2350: other text for CTRL-V in Insert mode with modifyOtherKeys
Problem: Other text for CTRL-V in Insert mode with modifyOtherKeys. Solution: Convert the Escape sequence back to key as if modifyOtherKeys is not set, and use CTRL-SHIFT-V to get the Escape sequence itself. (closes #5254)
This commit is contained in:
@@ -77,10 +77,17 @@ CTRL-V Insert next non-digit literally. Up to three digits form the
|
|||||||
way as in Insert mode (see above, |i_CTRL-V|).
|
way as in Insert mode (see above, |i_CTRL-V|).
|
||||||
Note: Under Windows CTRL-V is often mapped to paste text.
|
Note: Under Windows CTRL-V is often mapped to paste text.
|
||||||
Use CTRL-Q instead then.
|
Use CTRL-Q instead then.
|
||||||
|
When |modifyOtherKeys| is enabled then special Escape sequence
|
||||||
|
is converted back to what it was without |modifyOtherKeys|,
|
||||||
|
unless the Shift key is also pressed.
|
||||||
*c_CTRL-Q*
|
*c_CTRL-Q*
|
||||||
CTRL-Q Same as CTRL-V. But with some terminals it is used for
|
CTRL-Q Same as CTRL-V. But with some terminals it is used for
|
||||||
control flow, it doesn't work then.
|
control flow, it doesn't work then.
|
||||||
|
|
||||||
|
CTRL-SHIFT-V *c_CTRL-SHIFT-V* *c_CTRL-SHIFT-Q*
|
||||||
|
CTRL-SHIFT-Q Works just like CTRL-V, unless |modifyOtherKeys| is active,
|
||||||
|
then it inserts the Escape sequence for a key with modifiers.
|
||||||
|
|
||||||
*c_<Left>* *c_Left*
|
*c_<Left>* *c_Left*
|
||||||
<Left> cursor left
|
<Left> cursor left
|
||||||
*c_<Right>* *c_Right*
|
*c_<Right>* *c_Right*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
*insert.txt* For Vim version 8.1. Last change: 2019 Oct 20
|
*insert.txt* For Vim version 8.1. Last change: 2019 Nov 26
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -196,6 +196,13 @@ CTRL-V Insert next non-digit literally. For special keys, the
|
|||||||
mapping.
|
mapping.
|
||||||
Note: When CTRL-V is mapped (e.g., to paste text) you can
|
Note: When CTRL-V is mapped (e.g., to paste text) you can
|
||||||
often use CTRL-Q instead |i_CTRL-Q|.
|
often use CTRL-Q instead |i_CTRL-Q|.
|
||||||
|
When |modifyOtherKeys| is enabled then special Escape sequence
|
||||||
|
is converted back to what it was without |modifyOtherKeys|,
|
||||||
|
unless the Shift key is also pressed.
|
||||||
|
|
||||||
|
*i_CTRL-SHIFT-V*
|
||||||
|
CTRL-SHIFT-V Works just like CTRL-V, unless |modifyOtherKeys| is active,
|
||||||
|
then it inserts the Escape sequence for a key with modifiers.
|
||||||
|
|
||||||
*i_CTRL-Q*
|
*i_CTRL-Q*
|
||||||
CTRL-Q Same as CTRL-V.
|
CTRL-Q Same as CTRL-V.
|
||||||
|
60
src/edit.c
60
src/edit.c
@@ -1531,6 +1531,7 @@ ins_ctrl_v(void)
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int did_putchar = FALSE;
|
int did_putchar = FALSE;
|
||||||
|
int prev_mod_mask = mod_mask;
|
||||||
|
|
||||||
/* may need to redraw when no more chars available now */
|
/* may need to redraw when no more chars available now */
|
||||||
ins_redraw(FALSE);
|
ins_redraw(FALSE);
|
||||||
@@ -1554,6 +1555,12 @@ ins_ctrl_v(void)
|
|||||||
#ifdef FEAT_CMDL_INFO
|
#ifdef FEAT_CMDL_INFO
|
||||||
clear_showcmd();
|
clear_showcmd();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ((c == ESC || c == CSI) && !(prev_mod_mask & MOD_MASK_SHIFT))
|
||||||
|
// Using CTRL-V: Change any modifyOtherKeys ESC sequence to a normal
|
||||||
|
// key. Don't do this for CTRL-SHIFT-V.
|
||||||
|
c = decodeModifyOtherKeys(c);
|
||||||
|
|
||||||
insert_special(c, FALSE, TRUE);
|
insert_special(c, FALSE, TRUE);
|
||||||
#ifdef FEAT_RIGHTLEFT
|
#ifdef FEAT_RIGHTLEFT
|
||||||
revins_chars++;
|
revins_chars++;
|
||||||
@@ -1561,6 +1568,59 @@ ins_ctrl_v(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After getting an ESC or CSI for a literal key: If the typeahead buffer
|
||||||
|
* contains a modifyOtherKeys sequence then decode it and return the result.
|
||||||
|
* Otherwise return "c".
|
||||||
|
* Note that this doesn't wait for characters, they must be in the typeahead
|
||||||
|
* buffer already.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
decodeModifyOtherKeys(int c)
|
||||||
|
{
|
||||||
|
char_u *p = typebuf.tb_buf + typebuf.tb_off;
|
||||||
|
int idx;
|
||||||
|
int form = 0;
|
||||||
|
int argidx = 0;
|
||||||
|
int arg[2] = {0, 0};
|
||||||
|
|
||||||
|
// Recognize:
|
||||||
|
// form 0: {lead}{key};{modifier}u
|
||||||
|
// form 1: {lead}27;{modifier};{key}~
|
||||||
|
if ((c == CSI || (c == ESC && *p == '[')) && typebuf.tb_len >= 4)
|
||||||
|
{
|
||||||
|
idx = (*p == '[');
|
||||||
|
if (p[idx] == '2' && p[idx + 1] == '7' && p[idx + 2] == ';')
|
||||||
|
{
|
||||||
|
form = 1;
|
||||||
|
idx += 3;
|
||||||
|
}
|
||||||
|
while (idx < typebuf.tb_len && argidx < 2)
|
||||||
|
{
|
||||||
|
if (p[idx] == ';')
|
||||||
|
++argidx;
|
||||||
|
else if (VIM_ISDIGIT(p[idx]))
|
||||||
|
arg[argidx] = arg[argidx] * 10 + (p[idx] - '0');
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
if (idx < typebuf.tb_len
|
||||||
|
&& p[idx] == (form == 1 ? '~' : 'u')
|
||||||
|
&& argidx == 1)
|
||||||
|
{
|
||||||
|
// Match, consume the code.
|
||||||
|
typebuf.tb_off += idx + 1;
|
||||||
|
typebuf.tb_len -= idx + 1;
|
||||||
|
|
||||||
|
mod_mask = decode_modifiers(arg[!form]);
|
||||||
|
c = merge_modifyOtherKeys(arg[form]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put a character directly onto the screen. It's not stored in a buffer.
|
* Put a character directly onto the screen. It's not stored in a buffer.
|
||||||
* Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
|
* Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
|
||||||
|
@@ -2208,18 +2208,31 @@ getcmdline_int(
|
|||||||
|
|
||||||
case Ctrl_V:
|
case Ctrl_V:
|
||||||
case Ctrl_Q:
|
case Ctrl_Q:
|
||||||
ignore_drag_release = TRUE;
|
|
||||||
putcmdline('^', TRUE);
|
|
||||||
c = get_literal(); /* get next (two) character(s) */
|
|
||||||
do_abbr = FALSE; /* don't do abbreviation now */
|
|
||||||
extra_char = NUL;
|
|
||||||
/* may need to remove ^ when composing char was typed */
|
|
||||||
if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
|
|
||||||
{
|
{
|
||||||
draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
|
int prev_mod_mask = mod_mask;
|
||||||
msg_putchar(' ');
|
|
||||||
cursorcmd();
|
ignore_drag_release = TRUE;
|
||||||
|
putcmdline('^', TRUE);
|
||||||
|
c = get_literal(); // get next (two) character(s)
|
||||||
|
do_abbr = FALSE; // don't do abbreviation now
|
||||||
|
extra_char = NUL;
|
||||||
|
// may need to remove ^ when composing char was typed
|
||||||
|
if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
|
||||||
|
{
|
||||||
|
draw_cmdline(ccline.cmdpos,
|
||||||
|
ccline.cmdlen - ccline.cmdpos);
|
||||||
|
msg_putchar(' ');
|
||||||
|
cursorcmd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c == ESC || c == CSI)
|
||||||
|
&& !(prev_mod_mask & MOD_MASK_SHIFT))
|
||||||
|
// Using CTRL-V: Change any modifyOtherKeys ESC
|
||||||
|
// sequence to a normal key. Don't do this for
|
||||||
|
// CTRL-SHIFT-V.
|
||||||
|
c = decodeModifyOtherKeys(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef FEAT_DIGRAPHS
|
#ifdef FEAT_DIGRAPHS
|
||||||
|
@@ -1524,6 +1524,38 @@ updatescript(int c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert "c" plus "mod_mask" to merge the effect of modifyOtherKeys into the
|
||||||
|
* character.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
merge_modifyOtherKeys(int c_arg)
|
||||||
|
{
|
||||||
|
int c = c_arg;
|
||||||
|
|
||||||
|
if (mod_mask & MOD_MASK_CTRL)
|
||||||
|
{
|
||||||
|
if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
|
||||||
|
{
|
||||||
|
c &= 0x1f;
|
||||||
|
mod_mask &= ~MOD_MASK_CTRL;
|
||||||
|
}
|
||||||
|
else if (c == '6')
|
||||||
|
{
|
||||||
|
// CTRL-6 is equivalent to CTRL-^
|
||||||
|
c = 0x1e;
|
||||||
|
mod_mask &= ~MOD_MASK_CTRL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
|
||||||
|
&& c >= 0 && c <= 127)
|
||||||
|
{
|
||||||
|
c += 0x80;
|
||||||
|
mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the next input character.
|
* Get the next input character.
|
||||||
* Can return a special key or a multi-byte character.
|
* Can return a special key or a multi-byte character.
|
||||||
@@ -1765,30 +1797,9 @@ vgetc(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!no_reduce_keys)
|
if (!no_reduce_keys)
|
||||||
{
|
|
||||||
// A modifier was not used for a mapping, apply it to ASCII
|
// A modifier was not used for a mapping, apply it to ASCII
|
||||||
// keys. Shift would already have been applied.
|
// keys. Shift would already have been applied.
|
||||||
if (mod_mask & MOD_MASK_CTRL)
|
c = merge_modifyOtherKeys(c);
|
||||||
{
|
|
||||||
if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
|
|
||||||
{
|
|
||||||
c &= 0x1f;
|
|
||||||
mod_mask &= ~MOD_MASK_CTRL;
|
|
||||||
}
|
|
||||||
else if (c == '6')
|
|
||||||
{
|
|
||||||
// CTRL-6 is equivalent to CTRL-^
|
|
||||||
c = 0x1e;
|
|
||||||
mod_mask &= ~MOD_MASK_CTRL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
|
|
||||||
&& c >= 0 && c <= 127)
|
|
||||||
{
|
|
||||||
c += 0x80;
|
|
||||||
mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
int edit(int cmdchar, int startln, long count);
|
int edit(int cmdchar, int startln, long count);
|
||||||
int ins_need_undo_get(void);
|
int ins_need_undo_get(void);
|
||||||
void ins_redraw(int ready);
|
void ins_redraw(int ready);
|
||||||
|
int decodeModifyOtherKeys(int c);
|
||||||
void edit_putchar(int c, int highlight);
|
void edit_putchar(int c, int highlight);
|
||||||
char_u *prompt_text(void);
|
char_u *prompt_text(void);
|
||||||
int prompt_curpos_editable(void);
|
int prompt_curpos_editable(void);
|
||||||
|
@@ -37,6 +37,7 @@ void openscript(char_u *name, int directly);
|
|||||||
void close_all_scripts(void);
|
void close_all_scripts(void);
|
||||||
int using_script(void);
|
int using_script(void);
|
||||||
void before_blocking(void);
|
void before_blocking(void);
|
||||||
|
int merge_modifyOtherKeys(int c_arg);
|
||||||
int vgetc(void);
|
int vgetc(void);
|
||||||
int safe_vgetc(void);
|
int safe_vgetc(void);
|
||||||
int plain_vgetc(void);
|
int plain_vgetc(void);
|
||||||
|
@@ -65,6 +65,7 @@ int get_termcode_len(int idx);
|
|||||||
void del_termcode(char_u *name);
|
void del_termcode(char_u *name);
|
||||||
void set_mouse_topline(win_T *wp);
|
void set_mouse_topline(win_T *wp);
|
||||||
int is_mouse_topline(win_T *wp);
|
int is_mouse_topline(win_T *wp);
|
||||||
|
int decode_modifiers(int n);
|
||||||
int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen);
|
int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen);
|
||||||
void term_get_fg_color(char_u *r, char_u *g, char_u *b);
|
void term_get_fg_color(char_u *r, char_u *g, char_u *b);
|
||||||
void term_get_bg_color(char_u *r, char_u *g, char_u *b);
|
void term_get_bg_color(char_u *r, char_u *g, char_u *b);
|
||||||
|
@@ -4277,7 +4277,7 @@ put_string_in_typebuf(
|
|||||||
/*
|
/*
|
||||||
* Decode a modifier number as xterm provides it into MOD_MASK bits.
|
* Decode a modifier number as xterm provides it into MOD_MASK bits.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
decode_modifiers(int n)
|
decode_modifiers(int n)
|
||||||
{
|
{
|
||||||
int code = n - 1;
|
int code = n - 1;
|
||||||
|
@@ -1349,3 +1349,48 @@ func Test_mapping_works_with_shift_ctrl_alt()
|
|||||||
call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
|
call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
|
||||||
call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
|
call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_insert_literal()
|
||||||
|
set timeoutlen=10
|
||||||
|
new
|
||||||
|
" CTRL-V CTRL-X inserts a ^X
|
||||||
|
call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
|
||||||
|
call assert_equal("\<C-X>", getline(1))
|
||||||
|
|
||||||
|
call setline(1, '')
|
||||||
|
call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
|
||||||
|
call assert_equal("\<C-X>", getline(1))
|
||||||
|
|
||||||
|
" CTRL-SHIFT-V CTRL-X inserts escape sequencd
|
||||||
|
call setline(1, '')
|
||||||
|
call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
|
||||||
|
call assert_equal("\<Esc>[88;5u", getline(1))
|
||||||
|
|
||||||
|
call setline(1, '')
|
||||||
|
call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
|
||||||
|
call assert_equal("\<Esc>[27;5;88~", getline(1))
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
set timeoutlen&
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_cmdline_literal()
|
||||||
|
set timeoutlen=10
|
||||||
|
|
||||||
|
" CTRL-V CTRL-Y inserts a ^Y
|
||||||
|
call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
|
||||||
|
call assert_equal("\"\<C-Y>", @:)
|
||||||
|
|
||||||
|
call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
|
||||||
|
call assert_equal("\"\<C-Y>", @:)
|
||||||
|
|
||||||
|
" CTRL-SHIFT-V CTRL-Y inserts escape sequencd
|
||||||
|
call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
|
||||||
|
call assert_equal("\"\<Esc>[89;5u", @:)
|
||||||
|
|
||||||
|
call setline(1, '')
|
||||||
|
call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
|
||||||
|
call assert_equal("\"\<Esc>[27;5;89~", @:)
|
||||||
|
|
||||||
|
set timeoutlen&
|
||||||
|
endfunc
|
||||||
|
@@ -737,6 +737,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2350,
|
||||||
/**/
|
/**/
|
||||||
2349,
|
2349,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user