From 604f1fe8f9def9cc4598ec4cbd32afbbc71ef1bb Mon Sep 17 00:00:00 2001 From: git-bruh Date: Sat, 6 Apr 2024 15:38:59 +0530 Subject: [PATCH 1/2] vis_pipe*: take a Text object, vis-lua: add pipe_buffer --- sam.c | 4 ++-- vis-cmds.c | 2 +- vis-lua.c | 44 +++++++++++++++++++++++++++++++++++++++++++- vis-registers.c | 4 ++-- vis.c | 15 +++++++-------- vis.h | 4 ++-- 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/sam.c b/sam.c index 5f9e8f9c5..be1bf9229 100644 --- a/sam.c +++ b/sam.c @@ -1767,7 +1767,7 @@ static bool cmd_filter(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel buffer_init(&bufout); buffer_init(&buferr); - int status = vis_pipe(vis, win->file, range, &argv[1], &bufout, read_buffer, &buferr, read_buffer, false); + int status = vis_pipe(vis, win->file->text, win->file->name, range, &argv[1], &bufout, read_buffer, &buferr, read_buffer, false); if (vis->interrupted) { vis_info_show(vis, "Command cancelled"); @@ -1807,7 +1807,7 @@ static bool cmd_pipeout(Vis *vis, Win *win, Command *cmd, const char *argv[], Se Buffer buferr; buffer_init(&buferr); - int status = vis_pipe(vis, win->file, range, (const char*[]){ argv[1], NULL }, NULL, NULL, &buferr, read_buffer, false); + int status = vis_pipe(vis, win->file->text, win->file->name, range, (const char*[]){ argv[1], NULL }, NULL, NULL, &buferr, read_buffer, false); if (vis->interrupted) vis_info_show(vis, "Command cancelled"); diff --git a/vis-cmds.c b/vis-cmds.c index 05b18a5bb..80ca0ed28 100644 --- a/vis-cmds.c +++ b/vis-cmds.c @@ -414,7 +414,7 @@ static const char *file_open_dialog(Vis *vis, const char *pattern) { return NULL; Filerange empty = text_range_new(0,0); - int status = vis_pipe(vis, vis->win->file, &empty, + int status = vis_pipe(vis, vis->win->file->text, vis->win->file->name, &empty, (const char*[]){ buffer_content0(&bufcmd), NULL }, &bufout, read_buffer, &buferr, read_buffer, false); diff --git a/vis-lua.c b/vis-lua.c index 98a524993..75436f895 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -1358,7 +1358,48 @@ static int pipe_func(lua_State *L) { if (!file) return luaL_error(L, "vis:pipe(cmd = '%s'): win not open, file can't be nil", cmd); - int status = vis_pipe_collect(vis, file, &range, (const char*[]){ cmd, NULL }, &out, &err, fullscreen); + int status = vis_pipe_collect(vis, file->text, file->name, &range, (const char*[]){ cmd, NULL }, &out, &err, fullscreen); + lua_pushinteger(L, status); + if (out) + lua_pushstring(L, out); + else + lua_pushnil(L); + free(out); + if (err) + lua_pushstring(L, err); + else + lua_pushnil(L); + free(err); + vis_draw(vis); + return 3; +} + +/*** + * Pipe a buffer to external process and collect output. + * + * The editor core will be blocked while the external process is running. + * File and Range can be omitted or nil to indicate empty input. + * + * @function pipe + * @tparam string Buffer to pipe + * @tparam string command the command to execute + * @tparam[opt] bool fullscreen whether command is a fullscreen program (e.g. curses based) + * @treturn int code the exit status of the executed command + * @treturn string stdout the data written to stdout + * @treturn string stderr the data written to stderr + */ +static int pipe_buffer_func(lua_State *L) { + Vis *vis = obj_ref_check(L, 1, "vis"); + char *out = NULL, *err = NULL; + const char *buffer = luaL_checkstring(L, 2); + const char *cmd = luaL_checkstring(L, 3); + bool fullscreen = lua_isboolean(L, 4) && lua_toboolean(L, 4); + + Text *text = text_load(NULL); + text_insert(text, 0, buffer, strlen(buffer)); + Filerange range = text_range_new(0, text_size(text)); + int status = vis_pipe_collect(vis, text, NULL, &range, (const char*[]){ cmd, NULL }, &out, &err, fullscreen); + text_free(text); lua_pushinteger(L, status); if (out) lua_pushstring(L, out); @@ -1644,6 +1685,7 @@ static const struct luaL_Reg vis_lua[] = { { "action_register", action_register }, { "exit", exit_func }, { "pipe", pipe_func }, + { "pipe_buffer", pipe_buffer_func }, { "redraw", redraw }, { "communicate", communicate_func }, { "__index", vis_index }, diff --git a/vis-registers.c b/vis-registers.c index 1875da95d..4d68a9fe3 100644 --- a/vis-registers.c +++ b/vis-registers.c @@ -81,7 +81,7 @@ const char *register_slot_get(Vis *vis, Register *reg, size_t slot, size_t *len) cmd[3] = "primary"; else cmd[3] = "clipboard"; - int status = vis_pipe(vis, vis->win->file, + int status = vis_pipe(vis, vis->win->file->text, vis->win->file->name, &(Filerange){ .start = 0, .end = 0 }, cmd, buf, read_buffer, &buferr, read_buffer, false); @@ -166,7 +166,7 @@ bool register_slot_put_range(Vis *vis, Register *reg, size_t slot, Text *txt, Fi else cmd[3] = "clipboard"; - int status = vis_pipe(vis, vis->win->file, range, + int status = vis_pipe(vis, vis->win->file->text, vis->win->file->name, range, cmd, NULL, NULL, &buferr, read_buffer, false); if (status != 0) diff --git a/vis.c b/vis.c index e28740539..85b830b08 100644 --- a/vis.c +++ b/vis.c @@ -1708,14 +1708,13 @@ Regex *vis_regex(Vis *vis, const char *pattern) { return regex; } -int vis_pipe(Vis *vis, File *file, Filerange *range, const char *argv[], +int vis_pipe(Vis *vis, Text *text, const char *file_name, Filerange *range, const char *argv[], void *stdout_context, ssize_t (*read_stdout)(void *stdout_context, char *data, size_t len), void *stderr_context, ssize_t (*read_stderr)(void *stderr_context, char *data, size_t len), bool fullscreen) { /* if an invalid range was given, stdin (i.e. key board input) is passed * through the external command. */ - Text *text = file->text; int pin[2], pout[2], perr[2], status = -1; bool interactive = !text_range_valid(range); Filerange rout = interactive ? text_range_new(0, 0) : *range; @@ -1803,10 +1802,10 @@ int vis_pipe(Vis *vis, File *file, Filerange *range, const char *argv[], close(perr[1]); close(null); - if (file->name) { - char *name = strrchr(file->name, '/'); - setenv("vis_filepath", file->name, 1); - setenv("vis_filename", name ? name+1 : file->name, 1); + if (file_name) { + char *name = strrchr(file_name, '/'); + setenv("vis_filepath", file_name, 1); + setenv("vis_filename", name ? name+1 : file_name, 1); } if (!argv[1]) @@ -1943,11 +1942,11 @@ static ssize_t read_buffer(void *context, char *data, size_t len) { return len; } -int vis_pipe_collect(Vis *vis, File *file, Filerange *range, const char *argv[], char **out, char **err, bool fullscreen) { +int vis_pipe_collect(Vis *vis, Text *text, const char *file_name, Filerange *range, const char *argv[], char **out, char **err, bool fullscreen) { Buffer bufout, buferr; buffer_init(&bufout); buffer_init(&buferr); - int status = vis_pipe(vis, file, range, argv, + int status = vis_pipe(vis, text, file_name, range, argv, &bufout, out ? read_buffer : NULL, &buferr, err ? read_buffer : NULL, fullscreen); diff --git a/vis.h b/vis.h index b67d3c5e0..aa2e3b1ea 100644 --- a/vis.h +++ b/vis.h @@ -920,7 +920,7 @@ bool vis_prompt_cmd(Vis*, const char *cmd); * * @return The exit status of the forked process. */ -int vis_pipe(Vis*, File*, Filerange*, const char *argv[], +int vis_pipe(Vis*, Text*, const char *, Filerange*, const char *argv[], void *stdout_context, ssize_t (*read_stdout)(void *stdout_context, char *data, size_t len), void *stderr_context, ssize_t (*read_stderr)(void *stderr_context, char *data, size_t len), bool fullscreen); @@ -937,7 +937,7 @@ int vis_pipe(Vis*, File*, Filerange*, const char *argv[], * by the caller. * @endrst */ -int vis_pipe_collect(Vis*, File*, Filerange*, const char *argv[], char **out, char **err, bool fullscreen); +int vis_pipe_collect(Vis*, Text*, const char *, Filerange*, const char *argv[], char **out, char **err, bool fullscreen); /** * @} From 72b28021117a35d0e24af06c58814b6d7bc3d664 Mon Sep 17 00:00:00 2001 From: git-bruh Date: Sat, 6 Apr 2024 15:46:20 +0530 Subject: [PATCH 2/2] complete-word: use pipe_buffer --- lua/plugins/complete-word.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lua/plugins/complete-word.lua b/lua/plugins/complete-word.lua index 5e355e87e..520cc9439 100644 --- a/lua/plugins/complete-word.lua +++ b/lua/plugins/complete-word.lua @@ -24,8 +24,7 @@ vis:map(vis.modes.INSERT, "", function() if #candidates == 1 and candidates[1] == "\n" then return end candidates = table.concat(candidates, "\n") - local cmd = "printf '" .. candidates .. "' | sort -u | vis-menu" - local status, out, err = vis:pipe(cmd) + local status, out, err = vis:pipe_buffer(candidates, "sort -u | vis-menu") if status ~= 0 or not out then if err then vis:info(err) end return