From 80fbb7e1ead4d16f1f4d511d30df18eeb65ceafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Bakker?= Date: Fri, 16 Jun 2023 11:59:25 +0200 Subject: Add fullscreen param to vis_pipe_collect() and Lua API vis:pipe() This enables restoring the terminal from a fullscreen command like curses based program. Use cases are e.g. a file picker based on some external program like nnn (https://github.com/jarun/nnn). --- sam.c | 4 ++-- ui-terminal-curses.c | 9 +++++++-- ui-terminal-vt100.c | 2 +- ui-terminal.c | 4 ++-- ui.h | 2 +- vis-cmds.c | 2 +- vis-lua.c | 5 ++++- vis-registers.c | 4 ++-- vis.c | 10 ++++++---- vis.h | 10 ++++++++-- 10 files changed, 34 insertions(+), 18 deletions(-) diff --git a/sam.c b/sam.c index d088e9c..5a8a0b1 100644 --- a/sam.c +++ b/sam.c @@ -1739,7 +1739,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); + int status = vis_pipe(vis, win->file, range, &argv[1], &bufout, read_buffer, &buferr, read_buffer, false); if (vis->interrupted) { vis_info_show(vis, "Command cancelled"); @@ -1779,7 +1779,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); + int status = vis_pipe(vis, win->file, range, (const char*[]){ argv[1], NULL }, NULL, NULL, &buferr, read_buffer, false); if (vis->interrupted) vis_info_show(vis, "Command cancelled"); diff --git a/ui-terminal-curses.c b/ui-terminal-curses.c index e5ab853..93f729e 100644 --- a/ui-terminal-curses.c +++ b/ui-terminal-curses.c @@ -242,9 +242,14 @@ static bool ui_curses_resize(UiTerm *tui, int width, int height) { wresize(stdscr, height, width) == OK; } -static void ui_curses_save(UiTerm *tui) { +static void ui_curses_save(UiTerm *tui, bool fscr) { curs_set(1); - reset_shell_mode(); + if (fscr) { + def_prog_mode(); + endwin(); + } else { + reset_shell_mode(); + } } static void ui_curses_restore(UiTerm *tui) { diff --git a/ui-terminal-vt100.c b/ui-terminal-vt100.c index 8ba8a1a..33ad7fb 100644 --- a/ui-terminal-vt100.c +++ b/ui-terminal-vt100.c @@ -172,7 +172,7 @@ static bool ui_vt100_resize(UiTerm *tui, int width, int height) { return true; } -static void ui_vt100_save(UiTerm *tui) { +static void ui_vt100_save(UiTerm *tui, bool fscr) { cursor_visible(true); } diff --git a/ui-terminal.c b/ui-terminal.c index 9cdfd7e..f3b9f04 100644 --- a/ui-terminal.c +++ b/ui-terminal.c @@ -627,9 +627,9 @@ static bool ui_getkey(Ui *ui, TermKeyKey *key) { return ret == TERMKEY_RES_KEY; } -static void ui_terminal_save(Ui *ui) { +static void ui_terminal_save(Ui *ui, bool fscr) { UiTerm *tui = (UiTerm*)ui; - ui_term_backend_save(tui); + ui_term_backend_save(tui, fscr); termkey_stop(tui->termkey); } diff --git a/ui.h b/ui.h index d87384a..94b45f5 100644 --- a/ui.h +++ b/ui.h @@ -99,7 +99,7 @@ struct Ui { void (*suspend)(Ui*); void (*resume)(Ui*); bool (*getkey)(Ui*, TermKeyKey*); - void (*terminal_save)(Ui*); + void (*terminal_save)(Ui*, bool fscr); void (*terminal_restore)(Ui*); TermKey* (*termkey_get)(Ui*); int (*colors)(Ui*); diff --git a/vis-cmds.c b/vis-cmds.c index 2993267..fe1ab77 100644 --- a/vis-cmds.c +++ b/vis-cmds.c @@ -408,7 +408,7 @@ static const char *file_open_dialog(Vis *vis, const char *pattern) { Filerange empty = text_range_new(0,0); int status = vis_pipe(vis, vis->win->file, &empty, (const char*[]){ buffer_content0(&bufcmd), NULL }, - &bufout, read_buffer, &buferr, read_buffer); + &bufout, read_buffer, &buferr, read_buffer, false); if (status == 0) strncpy(name, buffer_content0(&bufout), sizeof(name)-1); diff --git a/vis-lua.c b/vis-lua.c index 735445b..e304dd7 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -1331,6 +1331,7 @@ static int exit_func(lua_State *L) { * @tparam[opt] File file the file to which the range applies * @tparam[opt] Range range the range 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 @@ -1348,7 +1349,8 @@ static int pipe_func(lua_State *L) { range = getrange(L, 3); } const char *cmd = luaL_checkstring(L, cmd_idx); - int status = vis_pipe_collect(vis, file, &range, (const char*[]){ cmd, NULL }, &out, &err); + bool fullscreen = lua_isboolean(L, cmd_idx + 1) && lua_toboolean(L, cmd_idx + 1); + int status = vis_pipe_collect(vis, file, &range, (const char*[]){ cmd, NULL }, &out, &err, fullscreen); lua_pushinteger(L, status); if (out) lua_pushstring(L, out); @@ -1363,6 +1365,7 @@ static int pipe_func(lua_State *L) { vis_draw(vis); return 3; } + /*** * Redraw complete user interface. * diff --git a/vis-registers.c b/vis-registers.c index 6de3374..1875da9 100644 --- a/vis-registers.c +++ b/vis-registers.c @@ -83,7 +83,7 @@ const char *register_slot_get(Vis *vis, Register *reg, size_t slot, size_t *len) cmd[3] = "clipboard"; int status = vis_pipe(vis, vis->win->file, &(Filerange){ .start = 0, .end = 0 }, - cmd, buf, read_buffer, &buferr, read_buffer); + cmd, buf, read_buffer, &buferr, read_buffer, false); if (status != 0) vis_info_show(vis, "Command failed %s", buffer_content0(&buferr)); @@ -167,7 +167,7 @@ bool register_slot_put_range(Vis *vis, Register *reg, size_t slot, Text *txt, Fi cmd[3] = "clipboard"; int status = vis_pipe(vis, vis->win->file, range, - cmd, NULL, NULL, &buferr, read_buffer); + cmd, NULL, NULL, &buferr, read_buffer, false); if (status != 0) vis_info_show(vis, "Command failed %s", buffer_content0(&buferr)); diff --git a/vis.c b/vis.c index f21efa8..0ffbd39 100644 --- a/vis.c +++ b/vis.c @@ -1729,7 +1729,8 @@ Regex *vis_regex(Vis *vis, const char *pattern) { int vis_pipe(Vis *vis, File *file, 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)) { + 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. */ @@ -1754,7 +1755,7 @@ int vis_pipe(Vis *vis, File *file, Filerange *range, const char *argv[], return -1; } - vis->ui->terminal_save(vis->ui); + vis->ui->terminal_save(vis->ui, fullscreen); pid_t pid = fork(); if (pid == -1) { @@ -1958,13 +1959,14 @@ 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) { +int vis_pipe_collect(Vis *vis, File *file, 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, &bufout, out ? read_buffer : NULL, - &buferr, err ? read_buffer : NULL); + &buferr, err ? read_buffer : NULL, + fullscreen); buffer_terminate(&bufout); buffer_terminate(&buferr); if (out) diff --git a/vis.h b/vis.h index 85a458a..f8c5680 100644 --- a/vis.h +++ b/vis.h @@ -898,6 +898,10 @@ bool vis_prompt_cmd(Vis*, const char *cmd); * If the ``read_stdout`` and ``read_stderr`` callbacks are non-NULL they * will be invoked when output from the forked process is available. * + * If ``fullscreen`` is set to ``true`` the external process is assumed to + * be a fullscreen program (e.g. curses based) and the ui context is + * restored accordingly. + * * @rst * .. warning:: The editor core is blocked until this function returns. * @endrst @@ -906,7 +910,8 @@ bool vis_prompt_cmd(Vis*, const char *cmd); */ int vis_pipe(Vis*, File*, 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)); + void *stderr_context, ssize_t (*read_stderr)(void *stderr_context, char *data, size_t len), + bool fullscreen); /** * Pipe a Filerange to an external process, return its exit status and capture @@ -914,12 +919,13 @@ int vis_pipe(Vis*, File*, Filerange*, const char *argv[], * @param argv Argument list, must be ``NULL`` terminated. * @param out Data written to ``stdout``, will be ``NUL`` terminated. * @param err Data written to ``stderr``, will be ``NUL`` terminated. + * @param fullscreen Whether the external process is a fullscreen program (e.g. curses based) * @rst * .. warning:: The pointers stored in ``out`` and ``err`` need to be `free(3)`-ed * by the caller. * @endrst */ -int vis_pipe_collect(Vis*, File*, Filerange*, const char *argv[], char **out, char **err); +int vis_pipe_collect(Vis*, File*, Filerange*, const char *argv[], char **out, char **err, bool fullscreen); /** * @} -- cgit v1.2.3