diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2018-01-15 23:14:20 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2018-01-15 23:50:40 +0100 |
commit | f8f7f9d5f5aead86541ffcd12e291b6dfb6811e5 (patch) | |
tree | 99368a7984c80d4b48a2a6dfba085ba05c73b280 | |
parent | de0a9548f7bf55bdf0202a2dcebb86a92f2d989d (diff) | |
download | rneovim-f8f7f9d5f5aead86541ffcd12e291b6dfb6811e5.tar.gz rneovim-f8f7f9d5f5aead86541ffcd12e291b6dfb6811e5.tar.bz2 rneovim-f8f7f9d5f5aead86541ffcd12e291b6dfb6811e5.zip |
vim-patch:8.0.0151,3,4 #7389
vim-patch:8.0.0151
Problem: To pass buffer content to system() and systemlist() one has to
first create a string or list.
Solution: Allow passing a buffer number. (LemonBoy,
closes vim/vim#1240)
https://github.com/vim/vim/commit/12c4492dd35e0cd83c8816be2ec849b836109882
vim-patch:8.0.0153
Problem: system() test fails on MS-Windows.
Solution: Deal when extra space and CR.
https://github.com/vim/vim/commit/9d9c35651712b88c81f1ae11091de1fd0bbbd35c
vim-patch:8.0.0154
Problem: system() test fails on OS/X.
Solution: Deal with leading spaces.
https://github.com/vim/vim/commit/31f19ce0a052f7c76d44a9a190e468c79cf5d56d
-rw-r--r-- | runtime/doc/eval.txt | 3 | ||||
-rw-r--r-- | src/nvim/eval.c | 46 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_system.vim | 48 | ||||
-rw-r--r-- | src/nvim/version.c | 6 | ||||
-rw-r--r-- | test/functional/eval/system_spec.lua | 10 |
6 files changed, 101 insertions, 13 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ae62498d35..7820b85bf4 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -7645,6 +7645,9 @@ system({cmd} [, {input}]) *system()* *E677* |writefile()| does with {binary} set to "b" (i.e. with a newline between each list item, and newlines inside list items converted to NULs). + When {input} is given and is a valid buffer id, the content of + the buffer is written to the file line by line, each line + terminated by a NL (and NUL where the text has NL). *E5677* Note: system() cannot write to or read from backgrounded ("&") shell commands, e.g.: > diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 0d84957ac5..9de6a7c464 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -17482,24 +17482,24 @@ write_list_error: /// Saves a typval_T as a string. /// -/// For lists, replaces NLs with NUL and separates items with NLs. +/// For lists or buffers, replaces NLs with NUL and separates items with NLs. /// -/// @param[in] tv A value to store as a string. -/// @param[out] len The length of the resulting string or -1 on error. +/// @param[in] tv Value to store as a string. +/// @param[out] len Length of the resulting string or -1 on error. /// @param[in] endnl If true, the output will end in a newline (if a list). /// @returns an allocated string if `tv` represents a VimL string, list, or /// number; NULL otherwise. static char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl) FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { + *len = 0; if (tv->v_type == VAR_UNKNOWN) { - *len = 0; return NULL; } - // For types other than list, let tv_get_string_buf_chk() get the value or + // For other types, let tv_get_string_buf_chk() get the value or // print an error. - if (tv->v_type != VAR_LIST) { + if (tv->v_type != VAR_LIST && tv->v_type != VAR_NUMBER) { const char *ret = tv_get_string_chk(tv); if (ret && (*len = strlen(ret))) { return xmemdupz(ret, (size_t)(*len)); @@ -17509,8 +17509,40 @@ static char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl) } } + if (tv->v_type == VAR_NUMBER) { // Treat number as a buffer-id. + buf_T *buf = buflist_findnr(tv->vval.v_number); + if (buf) { + for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { + for (char_u *p = ml_get_buf(buf, lnum, false); *p != NUL; p++) { + *len += 1; + } + *len += 1; + } + } else { + EMSGN(_(e_nobufnr), tv->vval.v_number); + *len = -1; + return NULL; + } + + if (*len == 0) { + return NULL; + } + + char *ret = xmalloc(*len + 1); + char *end = ret; + for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { + for (char_u *p = ml_get_buf(buf, lnum, false); *p != NUL; p++) { + *end++ = (*p == '\n') ? NUL : *p; + } + *end++ = '\n'; + } + *end = NUL; + *len = end - ret; + return ret; + } + + assert(tv->v_type == VAR_LIST); // Pre-calculate the resulting length. - *len = 0; list_T *list = tv->vval.v_list; TV_LIST_ITER_CONST(list, li, { *len += strlen(tv_get_string(TV_LIST_ITEM_TV(li))) + 1; diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 0c25945274..c1e6eedf94 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -88,6 +88,7 @@ NEW_TESTS ?= \ test_startup_utf8.res \ test_substitute.res \ test_syntax.res \ + test_system.res \ test_tabpage.res \ test_textobjects.res \ test_timers.res \ diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim new file mode 100644 index 0000000000..0446bd9105 --- /dev/null +++ b/src/nvim/testdir/test_system.vim @@ -0,0 +1,48 @@ +" Tests for system() and systemlist() + +function! Test_System() + if !executable('echo') || !executable('cat') || !executable('wc') + return + endif + let out = system('echo 123') + " On Windows we may get a trailing space. + if out != "123 \n" + call assert_equal("123\n", out) + endif + + let out = systemlist('echo 123') + " On Windows we may get a trailing space and CR. + if out != ["123 \r"] + call assert_equal(['123'], out) + endif + + call assert_equal('123', system('cat', '123')) + call assert_equal(['123'], systemlist('cat', '123')) + call assert_equal(["as\<NL>df"], systemlist('cat', ["as\<NL>df"])) + + new Xdummy + call setline(1, ['asdf', "pw\<NL>er", 'xxxx']) + let out = system('wc -l', bufnr('%')) + " On OS/X we get leading spaces + let out = substitute(out, '^ *', '', '') + call assert_equal("3\n", out) + + let out = systemlist('wc -l', bufnr('%')) + " On Windows we may get a trailing CR. + if out != ["3\r"] + " On OS/X we get leading spaces + if type(out) == v:t_list + let out[0] = substitute(out[0], '^ *', '', '') + endif + call assert_equal(['3'], out) + endif + + let out = systemlist('cat', bufnr('%')) + " On Windows we may get a trailing CR. + if out != ["asdf\r", "pw\<NL>er\r", "xxxx\r"] + call assert_equal(['asdf', "pw\<NL>er", 'xxxx'], out) + endif + bwipe! + + call assert_fails('call system("wc -l", 99999)', 'E86:') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index 996c06c902..2181f13c41 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -1281,10 +1281,10 @@ static const int included_patches[] = { 157, 156, 155, - // 154, - // 153, + 154, + 153, 152, - // 151, + 151, 150, 149, 148, diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index e2b12b6bc9..4d1630042b 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -5,6 +5,7 @@ local eq, call, clear, eval, feed_command, feed, nvim = helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command, helpers.feed, helpers.nvim local command = helpers.command +local exc_exec = helpers.exc_exec local iswin = helpers.iswin local Screen = require('test.functional.ui.screen') @@ -274,9 +275,12 @@ describe('system()', function() end) end) - describe('input passed as Number', function() - it('stringifies the input', function() - eq('1', eval('system("cat", 1)')) + describe('Number input', function() + it('is treated as a buffer id', function() + command("put ='text in buffer 1'") + eq('\ntext in buffer 1\n', eval('system("cat", 1)')) + eq('Vim(echo):E86: Buffer 42 does not exist', + exc_exec('echo system("cat", 42)')) end) end) |