aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVikram Pal <vikrampal659@gmail.com>2019-10-09 18:34:37 +0530
committerJustin M. Keyes <justinkz@gmail.com>2019-12-01 19:07:57 -0800
commitbd43e011b5b0feba644ec5feae6c174def31a9e4 (patch)
tree98bbbfed1b18d9f58bb7a29122bc37651139661c /src
parent276c2da28616d7a4f504c328dbb8857d38ab7a4a (diff)
downloadrneovim-bd43e011b5b0feba644ec5feae6c174def31a9e4.tar.gz
rneovim-bd43e011b5b0feba644ec5feae6c174def31a9e4.tar.bz2
rneovim-bd43e011b5b0feba644ec5feae6c174def31a9e4.zip
API: nvim_source_output
- Similar to nvim_source but will capture the output - Add meaningful VimL tracebacks for nvim_source - Handle got_int - Add error reporting
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c55
-rw-r--r--src/nvim/ex_cmds2.c36
2 files changed, 80 insertions, 11 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 10ece6bc22..bf722b4f4e 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -73,14 +73,63 @@ void api_vim_free_all_mem(void)
map_free(String, handle_T)(namespace_ids);
}
-void nvim_source(String command, Error *err)
- FUNC_API_SINCE(7)
+/// Executes a multiline block of ex-commands from a string.
+///
+/// On execution error: fails with VimL error, does not update v:errmsg.
+///
+/// @param src String containing the ex-commands
+/// @param[out] err Error details (Vim error), if any
+void nvim_source(String src, Error *err) FUNC_API_SINCE(7)
{
try_start();
- do_source_str(command.data);
+ do_source_str(src.data, "nvim_source(..)");
try_end(err);
}
+/// Executes a multiline block of ex-commands from a string and returns its
+/// (non-error) output. Shell |:!| output is not captured.
+///
+/// On execution error: fails with VimL error, does not update v:errmsg.
+///
+/// @param src String containing the ex-commands
+/// @param[out] err Error details (Vim error), if any
+String nvim_source_output(String src, Error *err) FUNC_API_SINCE(7)
+{
+ 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_source_str(src.data, "nvim_source_output(..)");
+ capture_ga = save_capture_ga;
+ msg_silent = save_msg_silent;
+ try_end(err);
+
+ if (ERROR_SET(err)) {
+ goto theend;
+ }
+
+ if (capture_local.ga_len > 1) {
+ String s = (String){
+ .data = capture_local.ga_data,
+ .size = (size_t)capture_local.ga_len,
+ };
+ // redir usually (except :echon) prepends a newline.
+ if (s.data[0] == '\n') {
+ memmove(s.data, s.data + 1, s.size - 1);
+ s.data[s.size - 1] = '\0';
+ s.size = s.size - 1;
+ }
+ return s; // Caller will free the memory.
+ }
+theend:
+ ga_clear(&capture_local);
+ return (String)STRING_INIT;
+}
+
/// Executes an ex-command.
///
/// On execution error: fails with VimL error, does not update v:errmsg.
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index eec689a28d..bda7b4e8b5 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -3025,7 +3025,7 @@ typedef struct {
///
/// @return pointer to allocated line, or NULL for end-of-file or
/// some error.
-static char_u *get_str_line(int c, void *cookie, int ident)
+static char_u *get_str_line(int c, void *cookie, int indent, bool do_concat)
{
GetStrLineCookie *p = cookie;
size_t i = p->offset;
@@ -3037,19 +3037,31 @@ static char_u *get_str_line(int c, void *cookie, int ident)
}
char buf[2046];
char *dst;
- dst = xstpncpy(buf, (char *)p->buf+p->offset, i - p->offset);
+ dst = xstpncpy(buf, (char *)p->buf + p->offset, i - p->offset);
if ((uint32_t)(dst - buf) != i - p->offset) {
smsg(_(":source error parsing command %s"), p->buf);
return NULL;
}
- buf[i-p->offset]='\0';
+ buf[i - p->offset] = '\0';
p->offset = i + 1;
return (char_u *)xstrdup(buf);
}
-int do_source_str(const char *cmd)
+int do_source_str(const char *cmd, const char *traceback_name)
{
- int retval;
+ char_u *save_sourcing_name = sourcing_name;
+ linenr_T save_sourcing_lnum = sourcing_lnum;
+ char_u sourcing_name_buf[256];
+ if (save_sourcing_name == NULL) {
+ sourcing_name = (char_u *)traceback_name;
+ } else {
+ snprintf((char *)sourcing_name_buf, sizeof sourcing_name_buf,
+ "%s called at %s:%"PRIdLINENR, traceback_name, save_sourcing_name,
+ save_sourcing_lnum);
+ sourcing_name = sourcing_name_buf;
+ }
+ sourcing_lnum = 0;
+
GetStrLineCookie cookie = {
.buf = (char_u *)cmd,
.offset = 0,
@@ -3057,10 +3069,18 @@ int do_source_str(const char *cmd)
const sctx_T save_current_sctx = current_sctx;
current_sctx.sc_sid = SID_STR;
current_sctx.sc_seq = 0;
- current_sctx.sc_lnum = 0;
- retval = do_cmdline(NULL, get_str_line, (void *)&cookie,
- DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
+ current_sctx.sc_lnum = save_sourcing_lnum;
+ int retval = FAIL;
+ do_cmdline(NULL, get_str_line, (void *)&cookie,
+ DOCMD_VERBOSE | DOCMD_NOWAIT | DOCMD_REPEAT);
+ retval = OK;
+ if (got_int) {
+ EMSG(_(e_interr));
+ }
+
current_sctx = save_current_sctx;
+ sourcing_lnum = save_sourcing_lnum;
+ sourcing_name = save_sourcing_name;
return retval;
}