From c095f83116eb8ef87983ca5fea61053755fbc4e5 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 5 Jan 2018 11:17:21 +0100 Subject: api: change nvim_command_output behavior Implement nvim_command_output with `execute({cmd},"silent")`. Behavior changes: - does not provoke any hit-enter prompt - no longer prepends a newline char - does not capture some noise (like the "[New File]" message, see the change to tabnewentered_spec.lua) Technically ("bug-for-bug") this a breaking change. But the previous behavior of nvim_command_output meant that it probably wasn't used for anything outside of tests. Also remove the undocumented `v:command_output` variable which was a hack introduced only for the purposes of nvim_command_output. closes #7726 --- src/nvim/api/vim.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'src/nvim/api/vim.c') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 172f2ce18e..8929bc5b9b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -43,14 +43,15 @@ #endif /// Executes an ex-command. -/// On VimL error: Returns the VimL error; v:errmsg is not updated. +/// +/// On parse error: forwards the Vim error; does not update v:errmsg. +/// On runtime error: forwards the Vim error; does not update v:errmsg. /// /// @param command Ex-command string -/// @param[out] err Error details (including actual VimL error), if any +/// @param[out] err Error details (Vim error), if any void nvim_command(String command, Error *err) FUNC_API_SINCE(1) { - // Run the command try_start(); do_cmdline_cmd(command.data); update_screen(VALID); @@ -207,18 +208,39 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, return cstr_as_string(ptr); } -String nvim_command_output(String str, Error *err) +/// Executes an ex-command and returns its (non-error) output. +/// Shell |:!| output is not captured. +/// +/// On parse error: forwards the Vim error; does not update v:errmsg. +/// On runtime error: forwards the Vim error; does not update v:errmsg. +/// +/// @param command Ex-command string +/// @param[out] err Error details (Vim error), if any +String nvim_command_output(String command, Error *err) FUNC_API_SINCE(1) { - do_cmdline_cmd("redir => v:command_output"); - nvim_command(str, err); - do_cmdline_cmd("redir END"); - + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(copy_string(command))); + ADD(args, STRING_OBJ(cstr_to_string("silent"))); + String fn = cstr_to_string("execute"); + Object rv = nvim_call_function(fn, args, err); + api_free_string(fn); + api_free_array(args); if (ERROR_SET(err)) { + assert(rv.type == kObjectTypeNil); return (String)STRING_INIT; } - return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT)); + assert(rv.type == kObjectTypeString); + // execute() always(?) prepends a newline; remove it. + if (rv.data.string.size > 1) { + assert(rv.data.string.data[0] == '\n'); + String *s = &rv.data.string; + s->size--; + memmove(s->data, s->data + 1, s->size); + s->data[s->size] = '\0'; + } + return rv.data.string; } /// Evaluates a VimL expression (:help expression). -- cgit From 5055d4a755d3c100cddf51bded77abca04beb971 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 9 Jan 2018 10:36:25 +0100 Subject: api: nvim_command_output: direct impl --- src/nvim/api/vim.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'src/nvim/api/vim.c') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 8929bc5b9b..0e7cc428d4 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -219,28 +219,38 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, String nvim_command_output(String command, Error *err) FUNC_API_SINCE(1) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(copy_string(command))); - ADD(args, STRING_OBJ(cstr_to_string("silent"))); - String fn = cstr_to_string("execute"); - Object rv = nvim_call_function(fn, args, err); - api_free_string(fn); - api_free_array(args); + const int save_msg_silent = msg_silent; + garray_T *const save_capture_ga = capture_ga; + garray_T capture_local; + ga_init(&capture_local, 1, 80); + + try_start(); + msg_silent++; + capture_ga = &capture_local; + do_cmdline_cmd(command.data); + capture_ga = save_capture_ga; + msg_silent = save_msg_silent; + try_end(err); + if (ERROR_SET(err)) { - assert(rv.type == kObjectTypeNil); - return (String)STRING_INIT; + goto theend; } - assert(rv.type == kObjectTypeString); - // execute() always(?) prepends a newline; remove it. - if (rv.data.string.size > 1) { - assert(rv.data.string.data[0] == '\n'); - String *s = &rv.data.string; - s->size--; - memmove(s->data, s->data + 1, s->size); - s->data[s->size] = '\0'; + if (capture_local.ga_len > 1) { + // redir always(?) prepends a newline; remove it. + char *s = capture_local.ga_data; + assert(s[0] == '\n'); + memmove(s, s + 1, (size_t)capture_local.ga_len); + s[capture_local.ga_len - 1] = '\0'; + return (String) { // Caller will free the memory. + .data = s, + .size = (size_t)(capture_local.ga_len - 1), + }; } - return rv.data.string; + +theend: + ga_clear(&capture_local); + return (String)STRING_INIT; } /// Evaluates a VimL expression (:help expression). -- cgit