commit 0548291a79ee63a4ee88dab9574c1def724c3a01 from: Omar Polo date: Tue Jun 25 22:20:35 2024 UTC move exec routines to their own file This leaves the room open to further improvements and tries to keep it apart from the UI itself. commit - 187eb2bac384268766bd53c86b3584d5effeee0c commit + 0548291a79ee63a4ee88dab9574c1def724c3a01 blob - 53f52a7e82ab528e0782e67d60d2c5fa23e50afe blob + 9709b0427066e78d52e1e9f03dd66506a9ef828f --- Makefile.am +++ Makefile.am @@ -23,6 +23,8 @@ telescope_SOURCES = bufio.c \ emoji-matcher.c \ ev.c \ ev.h \ + exec.c \ + exec.h \ fs.c \ fs.h \ gencmd.awk \ blob - d936a6e02a54c4fec85e5167dc1a6bdb232632c1 blob + 9160ec21b281348fd105492b3993ca5466acef89 --- cmd.c +++ cmd.c @@ -17,6 +17,7 @@ #include "compat.h" #include +#include #include #include @@ -25,6 +26,7 @@ #include "compl.h" #include "defaults.h" #include "ev.h" +#include "exec.h" #include "hist.h" #include "keymap.h" #include "mcache.h" @@ -926,6 +928,8 @@ cmd_suspend_telescope(struct buffer *buffer) { message("Zzz..."); ui_suspend(); + kill(getpid(), SIGSTOP); + ui_resume(); } void @@ -1217,7 +1221,35 @@ cmd_search(struct buffer *buffer) void cmd_mini_edit_external(struct buffer *buffer) { + FILE *fp; + char buf[1024 + 1]; + size_t r, len = 0; + GUARD_READ_ONLY(); - ui_edit_externally(); + if (ministate.compl.must_select || ministate.donefn == NULL) { + message("Can't use an external editor to complete"); + return; + } + + if ((fp = exec_editor(ministate.buf, strlen(ministate.buf))) == NULL) + return; + + while (len < sizeof(buf) - 1) { + r = fread(buf + len, 1, sizeof(buf) - 1 - len, fp); + len += r; + if (r == 0) + break; + } + buf[len] = '\0'; + while (len > 0 && buf[len-1] == '\n') + buf[--len] = '\0'; + + /* + * XXX: do not use minibuffer_confirm() since the text could + * have multiple lines and we are not prepared to render them + * in the history navigation. + */ + ministate.donefn(buf); + exit_minibuffer(); } blob - /dev/null blob + 501ec4ee118c97555dc053114e3459fc08c01c3a (mode 644) --- /dev/null +++ exec.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 Omar Polo + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "compat.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "exec.h" +#include "minibuffer.h" +#include "ui.h" + +#define TMPFILE "/tmp/telescope.XXXXXXXXXX" + +int +exec_cmd(char **argv, enum exec_mode mode) +{ + char **t; + int s, fd, ret; + pid_t pid; + + if (argv == NULL) + return (-1); + + if (mode == EXEC_FOREGROUND) { + ui_suspend(); + + fprintf(stderr, "%s: running", getprogname()); + for (t = argv; *t; ++t) + fprintf(stderr, " %s", *t); + fprintf(stderr, "\n"); + fflush(NULL); + } + + switch (pid = fork()) { + case -1: + message("failed to fork: %s", strerror(errno)); + return (-1); + case 0: + if (mode == EXEC_BACKGROUND) { + if ((fd = open("/dev/null", O_RDWR)) == -1) { + warn("can't open /dev/null"); + _exit(1); + } + (void)dup2(fd, 0); + (void)dup2(fd, 1); + (void)dup2(fd, 2); + if (fd > 2) + close(fd); + } + execvp(argv[0], argv); + if (mode == EXEC_FOREGROUND) { + warn("can't exec \"%s\"", argv[0]); + fprintf(stderr, "Press enter to continue"); + fflush(stderr); + read(0, &s, 1); + } + _exit(1); + } + + if (mode == EXEC_BACKGROUND) + return (0); + + do { + ret = waitpid(pid, &s, 0); + } while (ret == -1 && errno == EINTR); + + ui_resume(); + + if (WIFSIGNALED(s) || WEXITSTATUS(s) != 0) { + message("%s failed", *argv); + return (-1); + } + + return (0); +} + +FILE * +exec_editor(void *data, size_t len) +{ + FILE *fp; + char *editor; + char sfn[sizeof(TMPFILE)]; + char *argv[3]; + int fd; + + strlcpy(sfn, TMPFILE, sizeof(sfn)); + if ((fd = mkstemp(sfn)) == -1) { + message("failed to create a temp file: %s", strerror(errno)); + return (NULL); + } + (void) write(fd, data, len); + close(fd); + + if ((editor = getenv("VISUAL")) == NULL && + (editor = getenv("EDITOR")) == NULL) + editor = (char *)DEFAULT_EDITOR; + + argv[0] = editor; + argv[1] = sfn; + argv[2] = NULL; + + if (exec_cmd(argv, EXEC_FOREGROUND) == -1) { + (void) unlink(sfn); + return (NULL); + } + + if ((fp = fopen(sfn, "r")) == NULL) { + message("can't open temp file!"); + (void) unlink(sfn); + return (NULL); + } + (void) unlink(sfn); + + return (fp); +} blob - /dev/null blob + 8e5b732f701d990013457bd56e2d7a10d6e54370 (mode 644) --- /dev/null +++ exec.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Omar Polo + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +enum exec_mode { + EXEC_FOREGROUND, + EXEC_BACKGROUND, +}; + +int exec_cmd(char **argv, enum exec_mode); +FILE *exec_editor(void *, size_t); blob - e3a15d11da80e60b502dfb0956ba463bd3dc7120 blob + 0152ef4bdc9fb43ce9bad789accab285430b9c26 --- ui.c +++ ui.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -48,6 +47,7 @@ #include "cmd.h" #include "defaults.h" #include "ev.h" +#include "exec.h" #include "hist.h" #include "keymap.h" #include "mailcap.h" @@ -57,11 +57,6 @@ #include "ui.h" #include "utf8.h" -enum exec_mode { - EXEC_FOREGROUND, - EXEC_BACKGROUND, -}; - static void set_scroll_position(struct tab *, size_t, size_t); static void restore_curs_x(struct buffer *); @@ -88,7 +83,6 @@ static void place_cursor(int); static void redraw_tab(struct tab*); static void update_loading_anim(int, int, void*); static void stop_loading_anim(struct tab*); -static int exec_external_cmd(char **, enum exec_mode); static int should_rearrange_windows; static int show_tab_bar; @@ -1274,7 +1268,7 @@ open_download(int res, void *data) mode = EXEC_FOREGROUND; message("Loaded %s with %s", d->mime_type, mc->cmd_argv[0]); - exec_external_cmd(mc->cmd_argv, mode); + exec_cmd(mc->cmd_argv, mode); } void @@ -1396,9 +1390,11 @@ void ui_suspend(void) { endwin(); +} - kill(getpid(), SIGSTOP); - +void +ui_resume(void) +{ refresh(); clear(); rearrange_windows(); @@ -1409,138 +1405,3 @@ ui_end(void) { endwin(); } - -static int -exec_external_cmd(char **argv, enum exec_mode mode) -{ - char **t; - int s, fd, ret; - pid_t pid; - - if (argv == NULL) - return (-1); - - if (mode == EXEC_FOREGROUND) { - endwin(); - - fprintf(stderr, "%s: running", getprogname()); - for (t = argv; *t; ++t) - fprintf(stderr, " %s", *t); - fprintf(stderr, "\n"); - fflush(NULL); - } - - switch (pid = fork()) { - case -1: - message("failed to fork: %s", strerror(errno)); - return (-1); - case 0: - if (mode == EXEC_BACKGROUND) { - if ((fd = open("/dev/null", O_RDWR)) == -1) { - warn("can't open /dev/null"); - _exit(1); - } - (void)dup2(fd, 0); - (void)dup2(fd, 1); - (void)dup2(fd, 2); - if (fd > 2) - close(fd); - } - execvp(argv[0], argv); - if (mode == EXEC_FOREGROUND) { - warn("can't exec \"%s\"", argv[0]); - fprintf(stderr, "Press enter to continue"); - fflush(stderr); - read(0, &s, 1); - } - _exit(1); - } - - if (mode == EXEC_BACKGROUND) - return (0); - - do { - ret = waitpid(pid, &s, 0); - } while (ret == -1 && errno == EINTR); - - refresh(); - clear(); - ui_schedule_redraw(); - - if (WIFSIGNALED(s) || WEXITSTATUS(s) != 0) { - message("%s failed", *argv); - return (-1); - } - - return (0); -} - -#define TMPFILE "/tmp/telescope.XXXXXXXXXX" - -void -ui_edit_externally(void) -{ - FILE *fp; - char buf[1024 + 1]; - size_t r, len = 0; - char *editor; - char sfn[sizeof(TMPFILE)]; - char *argv[3]; - int fd; - - if (!in_minibuffer) { - message("Not in minibuffer!"); - return; - } - - if (ministate.compl.must_select || ministate.donefn == NULL) { - message("Can't use an external editor to complete"); - return; - } - - strlcpy(sfn, TMPFILE, sizeof(sfn)); - if ((fd = mkstemp(sfn)) == -1) { - message("failed to create a temp file: %s", strerror(errno)); - return; - } - (void) write(fd, ministate.buf, strlen(ministate.buf)); - close(fd); - - if ((editor = getenv("VISUAL")) == NULL && - (editor = getenv("EDITOR")) == NULL) - editor = (char *)DEFAULT_EDITOR; - - argv[0] = editor; - argv[1] = sfn; - argv[2] = NULL; - - if (exec_external_cmd(argv, EXEC_FOREGROUND) == -1) { - (void) unlink(sfn); - return; - } - - if ((fp = fopen(sfn, "r")) == NULL) { - message("can't open temp file!"); - (void) unlink(sfn); - return; - } - (void) unlink(sfn); - - while (len < sizeof(buf) - 1) { - r = fread(buf + len, 1, sizeof(buf) - 1 - len, fp); - len += r; - if (r == 0) - break; - } - buf[len] = '\0'; - while (len > 0 && buf[len-1] == '\n') - buf[--len] = '\0'; - - /* - * XXX: do not use minibuffer_confirm() since the text could - * have multiple lines and we are not prepared to render them - * in the history navigation. - */ - ministate.donefn(buf); - exit_minibuffer(); -} blob - 455b6a9408c7281563c1328d29f58ce38f0fe0d7 blob + 045a2712523fc2f2729b7404174da25a8da3616b --- ui.h +++ ui.h @@ -157,7 +157,7 @@ void ui_yornp(const char *, void (*)(int, void *), v void ui_read(const char *, void (*)(const char *, struct tab *), struct tab *, const char *); void ui_other_window(void); void ui_suspend(void); +void ui_resume(void); void ui_end(void); -void ui_edit_externally(void); #endif