diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-08-27 05:19:32 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-08-27 23:37:15 +0200 |
commit | 46aa254bf30d567bd2da4fbfab33bbdcbb111a37 (patch) | |
tree | 27fc87ef16e1b55c014a67dfe09bdab254086f3a | |
parent | 87389c6a57cf9fa91746503c479cdbea348030b9 (diff) | |
download | rneovim-46aa254bf30d567bd2da4fbfab33bbdcbb111a37.tar.gz rneovim-46aa254bf30d567bd2da4fbfab33bbdcbb111a37.tar.bz2 rneovim-46aa254bf30d567bd2da4fbfab33bbdcbb111a37.zip |
paste: handle 'nomodifiable'
- nvim_paste(): Marshal through luaeval() instead of nvim_execute_lua()
because the latter seems to hide some errors.
- Handle 'nomodifiable' in `nvim_put()` explicitly.
- Require explicit `false` from `vim.paste()` in order to "cancel",
otherwise assume true ("continue").
-rw-r--r-- | src/nvim/api/vim.c | 21 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 5 | ||||
-rw-r--r-- | test/functional/terminal/tui_spec.lua | 61 |
3 files changed, 75 insertions, 12 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 4f132ddbae..bf73a721fb 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1211,6 +1211,11 @@ Dictionary nvim_get_namespaces(void) /// Invokes the `vim.paste` handler, which handles each mode appropriately. /// Sets redo/undo. Faster than |nvim_input()|. /// +/// Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err` +/// but do not affect the return value (which is strictly decided by +/// `vim.paste()`). On error, subsequent calls are ignored ("drained") until +/// the next paste is initiated (phase 1 or -1). +/// /// @param data Multiline input. May be binary (containing NUL bytes). /// @param phase -1: paste in a single call (i.e. without streaming). /// To "stream" a paste, call `nvim_paste` sequentially with @@ -1233,6 +1238,7 @@ Boolean nvim_paste(String data, Integer phase, Error *err) return false; } Array args = ARRAY_DICT_INIT; + Array args2 = ARRAY_DICT_INIT; Object rv = OBJECT_INIT; if (phase == -1 || phase == 1) { // Start of paste-stream. draining = false; @@ -1243,8 +1249,9 @@ Boolean nvim_paste(String data, Integer phase, Error *err) Array lines = string_to_array(data); ADD(args, ARRAY_OBJ(lines)); ADD(args, INTEGER_OBJ(phase)); - rv = nvim_execute_lua(STATIC_CSTR_AS_STRING("return vim.paste(...)"), args, - err); + ADD(args2, STRING_OBJ(cstr_to_string("vim.paste(_A[1], _A[2])"))); + ADD(args2, ARRAY_OBJ(args2)); + rv = nvim_call_function(STATIC_CSTR_AS_STRING("luaeval"), args2, err); if (ERROR_SET(err)) { draining = true; goto theend; @@ -1255,7 +1262,7 @@ Boolean nvim_paste(String data, Integer phase, Error *err) } // vim.paste() decides if client should cancel. Errors do NOT cancel: we // want to drain remaining chunks (rather than divert them to main input). - cancel = (rv.type != kObjectTypeBoolean || !rv.data.boolean); + cancel = (rv.type == kObjectTypeBoolean && !rv.data.boolean); if (!cancel && !(State & CMDLINE)) { // Dot-repeat. for (size_t i = 0; i < lines.size; i++) { String s = lines.items[i].data.string; @@ -1271,9 +1278,9 @@ Boolean nvim_paste(String data, Integer phase, Error *err) AppendCharToRedobuff(ESC); // Dot-repeat. } theend: - api_free_object(rv); - api_free_array(args); + api_free_array(args2); if (cancel || phase == -1 || phase == 3) { // End of paste-stream. + draining = false; // XXX: Tickle main loop to ensure cursor is updated. loop_schedule_deferred(&main_loop, event_create(loop_dummy_event, 0)); } @@ -1303,6 +1310,10 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, api_set_error(err, kErrorTypeValidation, "Invalid type: '%s'", type.data); goto cleanup; } + if (!MODIFIABLE(curbuf)) { + api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'"); + goto cleanup; + } if (lines.size == 0) { goto cleanup; // Nothing to do. } diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 47a04795f8..884e07e2c5 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -409,6 +409,11 @@ describe('API', function() expect_err("Invalid type: 'x'", request, 'nvim_put', {'foo'}, 'x', false, false) end) + it("fails if 'nomodifiable'", function() + command('set nomodifiable') + expect_err([[Buffer is not 'modifiable']], request, + 'nvim_put', {'a','b'}, 'l', true, true) + end) it('inserts text', function() -- linewise nvim('put', {'line 1','line 2','line 3'}, 'l', true, true) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index aafbbc04b1..7435b293fd 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -329,14 +329,27 @@ describe('TUI', function() _G.save_paste_fn = vim.paste vim.paste = function(lines, phase) error("fake fail") end ]], {}) + -- Prepare something for dot-repeat/redo. + feed_data('ifoo\n\027\000') + wait_for_mode('n') + screen:expect{grid=[[ + foo | + {1: } | + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]} + wait_for_mode('n') -- Start pasting... feed_data('\027[200~line 1\nline 2\n') screen:expect{grid=[[ + foo | | {4:~ }| - {4:~ }| {5: }| - {8:paste: Error executing lua: [string "<nvim>"]:2: f}| + {8:paste: Vim:E5108: Error while calling lua chunk fo}| {10:Press ENTER or type command to continue}{1: } | {3:-- TERMINAL --} | ]]} @@ -347,13 +360,24 @@ describe('TUI', function() -- Stop paste. feed_data('\027[201~') feed_data('\n') -- <Enter> + --Dot-repeat/redo is not modified by failed paste. + feed_data('.') + screen:expect{grid=[[ + foo | + foo | + {1: } | + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]} -- Editor should still work after failed/drained paste. feed_data('ityped input...\027\000') screen:expect{grid=[[ + foo | + foo | typed input..{1:.} | {4:~ }| - {4:~ }| - {4:~ }| {5:[No Name] [+] }| | {3:-- TERMINAL --} | @@ -365,9 +389,35 @@ describe('TUI', function() feed_data('\027[200~line A\nline B\n\027[201~') feed_data('\n') -- <Enter> screen:expect{grid=[[ + foo | typed input...line A | line B | {1: } | + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]} + end) + + it("paste: 'nomodifiable' buffer", function() + child_session:request('nvim_command', 'set nomodifiable') + feed_data('\027[200~fail 1\nfail 2\n\027[201~') + screen:expect{grid=[[ + | + {5: }| + {8:paste: Vim:E5108: Error while calling lua chunk fo}| + {8:r luaeval(): [string "-- Nvim-Lua stdlib: the `vim}| + {8:` module (:help l..."]:193: Buffer is not 'modifia}| + {10:Press ENTER or type command to continue}{1: } | + {3:-- TERMINAL --} | + ]]} + feed_data('\n') -- <Enter> + child_session:request('nvim_command', 'set modifiable') + feed_data('\027[200~success 1\nsuccess 2\n\027[201~') + screen:expect{grid=[[ + success 1 | + success 2 | + {1: } | {4:~ }| {5:[No Name] [+] }| | @@ -380,9 +430,6 @@ describe('TUI', function() -- Other modes act like CTRL-C + paste. end) - it("paste: in 'nomodifiable' buffer", function() - end) - it('paste: exactly 64 bytes #10311', function() local expected = string.rep('z', 64) feed_data('i') |