Skip to content

Commit

Permalink
Merge 599923d into 911b1e4
Browse files Browse the repository at this point in the history
  • Loading branch information
ckelsel committed Jan 12, 2018
2 parents 911b1e4 + 599923d commit 1a80ea5
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 33 deletions.
4 changes: 4 additions & 0 deletions runtime/doc/eval.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7645,6 +7645,10 @@ 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 number that is a valid id for
an existing buffer then the content of the buffer is written
to the file line by line, each line terminated by a NL and
NULs characters where the text has a NL.
*E5677*
Note: system() cannot write to or read from backgrounded ("&")
shell commands, e.g.: >
Expand Down
88 changes: 60 additions & 28 deletions src/nvim/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -17476,6 +17476,7 @@ static bool write_list(FileDescriptor *const fp, const list_T *const list,
/// Saves a typval_T as a string.
///
/// For lists, replaces NLs with NUL and separates items with NLs.
/// For numbers, 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.
Expand All @@ -17485,14 +17486,68 @@ static bool write_list(FileDescriptor *const fp, const list_T *const list,
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
// print an error.
if (tv->v_type != VAR_LIST) {
if (tv->v_type == VAR_LIST) {
// Pre-calculate the resulting length.
list_T *list = tv->vval.v_list;
TV_LIST_ITER_CONST(list, li, {
*len += strlen(tv_get_string(TV_LIST_ITEM_TV(li))) + 1;
});

if (*len == 0) {
return NULL;
}

char *ret = xmalloc(*len + endnl);
char *end = ret;
TV_LIST_ITER_CONST(list, li, {
for (const char *s = tv_get_string(TV_LIST_ITEM_TV(li)); *s != NUL; s++) {
*end++ = (*s == '\n') ? NUL : *s;
}
if (endnl || TV_LIST_ITEM_NEXT(list, li) != NULL) {
*end++ = '\n';
}
});
*end = NUL;
*len = end - ret;
return ret;
} else if (tv->v_type == VAR_NUMBER) {
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;
} else {
// For types other than list and number, let tv_get_string_buf_chk()
// get the value or print an error.
const char *ret = tv_get_string_chk(tv);
if (ret && (*len = strlen(ret))) {
return xmemdupz(ret, (size_t)(*len));
Expand All @@ -17502,30 +17557,7 @@ static char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl)
}
}

// 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;
});

if (*len == 0) {
return NULL;
}

char *ret = xmalloc(*len + endnl);
char *end = ret;
TV_LIST_ITER_CONST(list, li, {
for (const char *s = tv_get_string(TV_LIST_ITEM_TV(li)); *s != NUL; s++) {
*end++ = (*s == '\n') ? NUL : *s;
}
if (endnl || TV_LIST_ITEM_NEXT(list, li) != NULL) {
*end++ = '\n';
}
});
*end = NUL;
*len = end - ret;
return ret;
return NULL;
}

/*
Expand Down
1 change: 1 addition & 0 deletions src/nvim/testdir/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,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 \
Expand Down
48 changes: 48 additions & 0 deletions src/nvim/testdir/test_system.vim
Original file line number Diff line number Diff line change
@@ -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
6 changes: 3 additions & 3 deletions src/nvim/version.c
Original file line number Diff line number Diff line change
Expand Up @@ -1281,10 +1281,10 @@ static const int included_patches[] = {
157,
156,
155,
// 154,
// 153,
154,
153,
152,
// 151,
151,
150,
149,
148,
Expand Down
4 changes: 2 additions & 2 deletions test/functional/eval/system_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ describe('system()', function()
end)
end)

describe('input passed as Number', function()
describe('treated as a buffer number', function()
it('stringifies the input', function()
eq('1', eval('system("cat", 1)'))
eq('\n', eval('system("cat", 1)'))
end)
end)

Expand Down

0 comments on commit 1a80ea5

Please sign in to comment.