diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2016-05-18 12:31:33 +0200 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2016-05-18 15:07:02 +0200 |
| commit | 0d1152340ccb3c6a0a8b4160fda34cc6687b236e (patch) | |
| tree | 054c0110c76227e8aae96e1fec3a5a2a37aa9e99 | |
| parent | ffe11d4cd4a4c81395b3272706cf696b93710c61 (diff) | |
| download | vis-0d1152340ccb3c6a0a8b4160fda34cc6687b236e.tar.gz vis-0d1152340ccb3c6a0a8b4160fda34cc6687b236e.tar.xz | |
vis: add an interactive mode to vis_pipe{,_collect}(...)
Previously the interactive mode was implicitly enabled by passing
an invalid range. However for some use cases (e.g. completion) we
need to be able to pipe a given text range to an external process
without also redirecting stderr (which is used to draw the slmenu
interface on top of vis).
| -rw-r--r-- | register.c | 4 | ||||
| -rw-r--r-- | sam.c | 4 | ||||
| -rw-r--r-- | vis-cmds.c | 2 | ||||
| -rw-r--r-- | vis.c | 18 | ||||
| -rw-r--r-- | vis.h | 8 |
5 files changed, 19 insertions, 17 deletions
@@ -33,7 +33,7 @@ const char *register_get(Vis *vis, Register *reg, size_t *len) { buffer_init(&buferr); buffer_clear(®->buf); - int status = vis_pipe(vis, &(Filerange){ .start = 0, .end = 0 }, + int status = vis_pipe(vis, &(Filerange){ .start = 0, .end = 0 }, false, (const char*[]){ VIS_CLIPBOARD, "--paste", NULL }, ®->buf, read_buffer, &buferr, read_buffer); @@ -74,7 +74,7 @@ bool register_put_range(Vis *vis, Register *reg, Text *txt, Filerange *range) { Buffer buferr; buffer_init(&buferr); - int status = vis_pipe(vis, range, (const char*[]){ VIS_CLIPBOARD, "--copy", NULL }, + int status = vis_pipe(vis, range, false, (const char*[]){ VIS_CLIPBOARD, "--copy", NULL }, NULL, NULL, &buferr, read_buffer); if (status != 0) @@ -1150,7 +1150,7 @@ static bool cmd_filter(Vis *vis, Win *win, Command *cmd, const char *argv[], Cur Buffer buferr; buffer_init(&buferr); - int status = vis_pipe(vis, range, &argv[1], &filter, read_text, &buferr, read_buffer); + int status = vis_pipe(vis, range, false, &argv[1], &filter, read_text, &buferr, read_buffer); if (status == 0) { text_delete_range(txt, range); @@ -1198,7 +1198,7 @@ static bool cmd_pipeout(Vis *vis, Win *win, Command *cmd, const char *argv[], Cu Buffer buferr; buffer_init(&buferr); - int status = vis_pipe(vis, range, (const char*[]){ argv[1], NULL }, NULL, NULL, &buferr, read_buffer); + int status = vis_pipe(vis, range, false, (const char*[]){ argv[1], NULL }, NULL, NULL, &buferr, read_buffer); if (status == 0 && cur) view_cursors_to(cur, range->start); @@ -331,7 +331,7 @@ static const char *file_open_dialog(Vis *vis, const char *pattern) { return NULL; Filerange empty = text_range_empty(); - int status = vis_pipe(vis, &empty, (const char*[]){ buffer_content0(&bufcmd), NULL }, + int status = vis_pipe(vis, &empty, true, (const char*[]){ buffer_content0(&bufcmd), NULL }, &bufout, read_buffer, &buferr, read_buffer); if (status == 0) @@ -1161,20 +1161,18 @@ Regex *vis_regex(Vis *vis, const char *pattern) { return regex; } -int vis_pipe(Vis *vis, Filerange *range, const char *argv[], +int vis_pipe(Vis *vis, Filerange *range, bool interactive, 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)) { /* if an invalid range was given, stdin (i.e. key board input) is passed * through the external command. */ Text *text = vis->win->file->text; - View *view = vis->win->view; int pin[2], pout[2], perr[2], status = -1; - bool interactive = !text_range_valid(range); - size_t pos = view_cursor_get(view); - Filerange rout = *range; - if (interactive) - rout = (Filerange){ .start = pos, .end = pos }; + bool valid_range = text_range_valid(range); + if (!valid_range) + interactive = true; + Filerange rout = valid_range ? *range : text_range_new(0, 0); if (pipe(pin) == -1) return -1; @@ -1205,7 +1203,7 @@ int vis_pipe(Vis *vis, Filerange *range, const char *argv[], vis_info_show(vis, "fork failure: %s", strerror(errno)); return -1; } else if (pid == 0) { /* child i.e filter */ - if (!interactive) + if (!interactive || valid_range) dup2(pin[0], STDIN_FILENO); close(pin[0]); close(pin[1]); @@ -1330,11 +1328,11 @@ static ssize_t read_buffer(void *context, char *data, size_t len) { return len; } -int vis_pipe_collect(Vis *vis, Filerange *range, const char *argv[], char **out, char **err) { +int vis_pipe_collect(Vis *vis, Filerange *range, bool interactive, const char *argv[], char **out, char **err) { Buffer bufout, buferr; buffer_init(&bufout); buffer_init(&buferr); - int status = vis_pipe(vis, range, argv, &bufout, read_buffer, &buferr, read_buffer); + int status = vis_pipe(vis, range, interactive, argv, &bufout, read_buffer, &buferr, read_buffer); buffer_terminate(&bufout); buffer_terminate(&buferr); if (out) @@ -410,6 +410,10 @@ bool vis_prompt_cmd(Vis*, const char *cmd); /* pipe a given file range to an external process * + * in interactive mode stdin and stderr are not redirected, hence they + * can be used to read keyboard input and draw a user interface on top + * of vis. Attempting to pipe an invalid range enables interactive mode. + * * if argv contains only one non-NULL element the command is executed using * /bin/sh -c (i.e. argument expansion is performed by the shell). In contrast * if argv contains more than one non-NULL element execvp(argv[0], argv); will @@ -418,14 +422,14 @@ bool vis_prompt_cmd(Vis*, const char *cmd); * if read_std{out,err} are non-NULL they will be called when output from * the forked process is available. */ -int vis_pipe(Vis *vis, Filerange *range, const char *argv[], +int vis_pipe(Vis *vis, Filerange *range, bool interactive, 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)); /* pipe a range to an external application, return its exit status and store * everything that is written to stdout/stderr in the gitven char pointers * which have to be free(3)-ed by the caller */ -int vis_pipe_collect(Vis *vis, Filerange *range, const char *argv[], char **out, char **err); +int vis_pipe_collect(Vis *vis, Filerange *range, bool interactive, const char *argv[], char **out, char **err); /* given the start of a key, returns a pointer to the start of the one immediately * following as will be processed by the input system. skips over special keys |
