From e644369f6e67b6520e9c55026f8671985d70c166 Mon Sep 17 00:00:00 2001 From: Rui Abreu Ferreira Date: Wed, 8 Oct 2014 14:04:27 +0100 Subject: [PATCH 1/2] Add Boolean argument escape_csi to vim_feedkeys - By default vim_feedkeys escaped all input for CSI/K_SPECIAL bytes before using it. However since vim_replace_termcodes() also escapes the input string chaining these functions together escapes input twice - vim_feedkeys() now takes a third Boolean argument to enable/disable escaping - Breaks API compatibility --- src/nvim/api/vim.c | 20 +++++++++++++++----- src/nvim/eval.c | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index addcbf62e9..fc1307090d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -49,8 +49,10 @@ void vim_command(String str, Error *err) /// /// @param keys to be typed /// @param mode specifies the mapping options +/// @param escape_csi the string needs escaping for K_SPECIAL/CSI bytes /// @see feedkeys() -void vim_feedkeys(String keys, String mode) +/// @see vim_strsave_escape_csi +void vim_feedkeys(String keys, String mode, Boolean escape_csi) FUNC_ATTR_DEFERRED { bool remap = true; @@ -68,12 +70,20 @@ void vim_feedkeys(String keys, String mode) } } - /* Need to escape K_SPECIAL and CSI before putting the string in the - * typeahead buffer. */ - char *keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); + char *keys_esc; + if (escape_csi) { + // Need to escape K_SPECIAL and CSI before putting the string in the + // typeahead buffer. + keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); + } else { + keys_esc = keys.data; + } ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE), typebuf.tb_len, !typed, false); - free(keys_esc); + + if (escape_csi) { + free(keys_esc); + } if (vgetc_busy) typebuf_was_filled = true; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 5975777261..4a77bcd3c5 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8414,7 +8414,7 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv) } vim_feedkeys(cstr_as_string((char *)keys), - cstr_as_string((char *)flags)); + cstr_as_string((char *)flags), true); } } From 84eb118f62126c67092a6aa2585da51c824013d0 Mon Sep 17 00:00:00 2001 From: Rui Abreu Ferreira Date: Mon, 20 Oct 2014 10:21:24 +0100 Subject: [PATCH 2/2] Functional tests for feedkeys CSI escaping - tests for vim_feedkeys and replace_termcodes --- test/functional/api/vim_spec.lua | 43 +++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index abf9c9efcd..f34df8cefb 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,6 +1,6 @@ -- Sanity checks for vim_* API calls via msgpack-rpc local helpers = require('test.functional.helpers') -local clear, nvim, eq, ok = helpers.clear, helpers.nvim, helpers.eq, helpers.ok +local clear, nvim, eq, neq, ok = helpers.clear, helpers.nvim, helpers.eq, helpers.neq, helpers.ok describe('vim_* functions', function() @@ -106,6 +106,47 @@ describe('vim_* functions', function() end) end) + describe('replace_termcodes', function() + it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() + eq(helpers.nvim('replace_termcodes', '\x80', true, true, true), '\x80\xfeX') + end) + + it('leaves non K_SPECIAL string unchanged', function() + eq(helpers.nvim('replace_termcodes', 'abc', true, true, true), 'abc') + end) + + it('converts ', function() + eq(helpers.nvim('replace_termcodes', '', true, true, true), '\\') + end) + end) + + describe('feedkeys', function() + it('CSI escaping', function() + local function on_setup() + -- notice the special char(…) \xe2\80\xa6 + nvim('feedkeys', ':let x1="…"\n', '', true) + + -- Both replace_termcodes and feedkeys escape \x80 + local inp = helpers.nvim('replace_termcodes', ':let x2="…"', true, true, true) + nvim('feedkeys', inp, '', true) + + -- Disabling CSI escaping in feedkeys + inp = helpers.nvim('replace_termcodes', ':let x3="…"', true, true, true) + nvim('feedkeys', inp, '', false) + + helpers.stop() + end + + -- spin the loop a bit + helpers.run(nil, nil, on_setup) + + eq(nvim('get_var', 'x1'), '…') + -- Because of the double escaping this is neq + neq(nvim('get_var', 'x2'), '…') + eq(nvim('get_var', 'x3'), '…') + end) + end) + it('can throw exceptions', function() local status, err = pcall(nvim, 'get_option', 'invalid-option') eq(false, status)