summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-11-26 19:33:22 +0100
committerBram Moolenaar <Bram@vim.org>2019-11-26 19:33:22 +0100
commitfc4ea2a72d36de1196a3ce17352e72f8fe90f4bb (patch)
treed5d681840040dc4e36b94bb94cef2cb972c052b0
parentcc4423ae13d78367a3d0b5756783523d3b3a1d31 (diff)
downloadvim-git-fc4ea2a72d36de1196a3ce17352e72f8fe90f4bb.tar.gz
patch 8.1.2350: other text for CTRL-V in Insert mode with modifyOtherKeysv8.1.2350
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)
-rw-r--r--runtime/doc/cmdline.txt7
-rw-r--r--runtime/doc/insert.txt9
-rw-r--r--src/edit.c60
-rw-r--r--src/ex_getln.c33
-rw-r--r--src/getchar.c55
-rw-r--r--src/proto/edit.pro1
-rw-r--r--src/proto/getchar.pro1
-rw-r--r--src/proto/term.pro1
-rw-r--r--src/term.c2
-rw-r--r--src/testdir/test_termcodes.vim45
-rw-r--r--src/version.c2
11 files changed, 182 insertions, 34 deletions
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 092757a2b..ab0e68253 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -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|).
Note: Under Windows CTRL-V is often mapped to paste text.
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*
CTRL-Q Same as CTRL-V. But with some terminals it is used for
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*
<Left> cursor left
*c_<Right>* *c_Right*
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index d28bf5998..eac301aba 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -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
@@ -196,6 +196,13 @@ CTRL-V Insert next non-digit literally. For special keys, the
mapping.
Note: When CTRL-V is mapped (e.g., to paste text) you can
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*
CTRL-Q Same as CTRL-V.
diff --git a/src/edit.c b/src/edit.c
index c74f1bb36..e1bf63db9 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -1531,6 +1531,7 @@ ins_ctrl_v(void)
{
int c;
int did_putchar = FALSE;
+ int prev_mod_mask = mod_mask;
/* may need to redraw when no more chars available now */
ins_redraw(FALSE);
@@ -1554,6 +1555,12 @@ ins_ctrl_v(void)
#ifdef FEAT_CMDL_INFO
clear_showcmd();
#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);
#ifdef FEAT_RIGHTLEFT
revins_chars++;
@@ -1562,6 +1569,59 @@ ins_ctrl_v(void)
}
/*
+ * 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.
* Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
*/
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 683215874..4a4d76ec9 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -2208,18 +2208,31 @@ getcmdline_int(
case Ctrl_V:
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);
- msg_putchar(' ');
- cursorcmd();
+ int prev_mod_mask = mod_mask;
+
+ 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;
#ifdef FEAT_DIGRAPHS
diff --git a/src/getchar.c b/src/getchar.c
index b086126d9..a3af87999 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1525,6 +1525,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.
* Can return a special key or a multi-byte character.
* Can return NUL when called recursively, use safe_vgetc() if that's not
@@ -1765,30 +1797,9 @@ vgetc(void)
}
if (!no_reduce_keys)
- {
// A modifier was not used for a mapping, apply it to ASCII
// keys. Shift would already have been applied.
- 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);
- }
- }
+ c = merge_modifyOtherKeys(c);
break;
}
diff --git a/src/proto/edit.pro b/src/proto/edit.pro
index bc69b41e8..49b9f4cff 100644
--- a/src/proto/edit.pro
+++ b/src/proto/edit.pro
@@ -2,6 +2,7 @@
int edit(int cmdchar, int startln, long count);
int ins_need_undo_get(void);
void ins_redraw(int ready);
+int decodeModifyOtherKeys(int c);
void edit_putchar(int c, int highlight);
char_u *prompt_text(void);
int prompt_curpos_editable(void);
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index cfb3ab4ab..0e24bd392 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -37,6 +37,7 @@ void openscript(char_u *name, int directly);
void close_all_scripts(void);
int using_script(void);
void before_blocking(void);
+int merge_modifyOtherKeys(int c_arg);
int vgetc(void);
int safe_vgetc(void);
int plain_vgetc(void);
diff --git a/src/proto/term.pro b/src/proto/term.pro
index 5af199614..8f1d33c4e 100644
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -65,6 +65,7 @@ int get_termcode_len(int idx);
void del_termcode(char_u *name);
void set_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);
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);
diff --git a/src/term.c b/src/term.c
index 83268c71c..c7ac81c9c 100644
--- a/src/term.c
+++ b/src/term.c
@@ -4277,7 +4277,7 @@ put_string_in_typebuf(
/*
* Decode a modifier number as xterm provides it into MOD_MASK bits.
*/
- static int
+ int
decode_modifiers(int n)
{
int code = n - 1;
diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim
index 05f0d18df..298244e43 100644
--- a/src/testdir/test_termcodes.vim
+++ b/src/testdir/test_termcodes.vim
@@ -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('GetEscCodeCSIu'), 'C-S-A', 8)
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
diff --git a/src/version.c b/src/version.c
index 36e43a849..6c9ac2295 100644
--- a/src/version.c
+++ b/src/version.c
@@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2350,
+/**/
2349,
/**/
2348,