commit 4e32d3a6c187dd9646ba4aa80a69082adf3b3c46 from: Thomas Adam date: Tue Jun 04 11:18:04 2024 UTC ui: add capability to run external cmds When telescope encounters a file type which it cannot display it prompts the user whether they wish to save the file, or not. This patch extends this idea -- if the file is saved, then the user is prompted to run a command against that downloaded file. This controllable via the 'external-cmd' setting. It defaults to 'xdg-open'. This is based off work originally started by op@. commit - b9a64d45f6bf202e384c314e9e8b2b303e5d4f49 commit + 4e32d3a6c187dd9646ba4aa80a69082adf3b3c46 blob - f137ba2586ebfbe7c474fbb7bb5b47c357206b4e blob + 57d01ea586adb3381066c9342720bcb3642f4165 --- cmd.c +++ cmd.c @@ -287,43 +287,6 @@ void cmd_kill_telescope(struct buffer *buffer) { yornp("really quit?", kill_telescope_cb, NULL); -} - -#include -#include -#include -#include -static void -do_exec_command(const char *cmd, struct tab *t) -{ - int s; - pid_t p; - - if (cmd == NULL) - return; - - endwin(); - - switch (p = fork()) { - case -1: - message("failed to fork: %s", strerror(errno)); - return; - case 0: - execl("/bin/sh", "sh", "-c", cmd, NULL); - warn("exec \"%s\" failed", cmd); - _exit(1); - } - -again: - if (waitpid(p, &s, 0) == -1) { - if (errno == EINTR) - goto again; - } - - refresh(); - clear(); - ui_schedule_redraw(); - /* rearrange_windows(); */ } void @@ -353,13 +316,6 @@ cmd_push_button(struct buffer *buffer) else buffer->line_max++; } - break; - case LINE_DOWNLOAD: - case LINE_DOWNLOAD_DONE: - minibuffer_read("Execute: ", do_exec_command, - NULL); - snprintf(ministate.buf, sizeof(ministate.buf), - "xdg-open %s", vl->parent->alt); break; default: break; blob - a38bc8415b1dc64af1c6a14e701604bae142a54e blob + ab7dfac0e780c559474ab835780372a9a766a5fe --- defaults.c +++ defaults.c @@ -31,6 +31,7 @@ char *default_protocol = NULL; char *download_path = NULL; +char *external_cmd = NULL; char *new_tab_url = NULL; char *default_search_engine = NULL; @@ -640,6 +641,17 @@ config_setvars(const char *var, char *val) free(download_path); if (asprintf(&download_path, "%s%s%s", prfx, v, sufx) == -1) { download_path = NULL; + return 0; + } + + free(val); + return 1; + } + + if (!strcmp(var, "external-cmd")) { + free(external_cmd); + if (asprintf(&external_cmd, "%s", val) == -1) { + external_cmd = NULL; return 0; } blob - b860d8acb7d1d179cdbbb5ca9afaee909897795b blob + 7e92fa6f65721da39557a0eb7ff0d2a60ddf7659 --- defaults.h +++ defaults.h @@ -20,6 +20,7 @@ extern char *default_protocol; extern char *default_search_engine; extern char *download_path; +extern char *external_cmd; extern char *new_tab_url; extern int autosave; blob - dc784197db4eb51e31bdc315d3c7535d9233e4bf blob + e09140d922a771d979ee481e4eb31352c4c44407 --- downloads.c +++ downloads.c @@ -18,6 +18,7 @@ #include #include +#include #include "telescope.h" #include "ui.h" @@ -108,3 +109,16 @@ download_by_id(uint32_t id) return NULL; } + +void +download_finished(struct download *d) +{ + if (d == NULL) + return; + + close(d->fd); + d->fd = -1; + + ui_on_download_refresh(); + ui_prompt_download_cmd(d->path); +} blob - dd3d8b9e6504a40177f2f4496cf52b0c61532078 blob + 8be25419f42f2e68c711fad7150e00c61acc1ff8 --- telescope.c +++ telescope.c @@ -532,7 +532,12 @@ handle_dispatch_imsg(int fd, int event, void *data) case IMSG_EOF: if ((tab = tab_by_id(imsg_get_id(&imsg))) == NULL && ((d = download_by_id(imsg_get_id(&imsg)))) == NULL) + return; + + if (tab == NULL && d != NULL) { + download_finished(d); return; + } if (tab != NULL) { if (!parser_free(tab)) @@ -553,10 +558,6 @@ handle_dispatch_imsg(int fd, int event, void *data) ui_on_tab_refresh(tab); ui_on_tab_loaded(tab); - } else { - close(d->fd); - d->fd = -1; - ui_on_download_refresh(); } break; default: @@ -1145,6 +1146,10 @@ main(int argc, char * const *argv) if (download_path == NULL && (download_path = strdup("/tmp/")) == NULL) + errx(1, "strdup"); + + if (external_cmd == NULL && + (external_cmd = strdup("xdg-open")) == NULL) errx(1, "strdup"); if (argc != 0) { blob - a099c7f70b13aef4d6ea62cf11276bf5f31af07d blob + 92616f9dee3cedae427c719c0139cf370e7c09f0 --- telescope.h +++ telescope.h @@ -222,6 +222,7 @@ struct download { void recompute_downloads(void); struct download *enqueue_download(uint32_t, const char *); struct download *download_by_id(uint32_t); +void download_finished(struct download *); /* help.c */ void recompute_help(void); blob - 48370bf48558b0666a827c6e7a7a0fda37ce158e blob + 544bdc943f403061887766c3145a424ba3a818d2 --- ui.c +++ ui.c @@ -33,9 +33,11 @@ #include "compat.h" #include +#include #include #include +#include #include #include #include @@ -80,6 +82,7 @@ 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 void exec_external_cmd(const char *, struct tab *); static int should_rearrange_windows; static int show_tab_bar; @@ -1236,6 +1239,16 @@ ui_on_download_refresh(void) } void +ui_prompt_download_cmd(char *path) +{ + char cmd[8192]; + + snprintf(cmd, sizeof(cmd), "%s %s", external_cmd, path); + + ui_read("Execute", exec_external_cmd, current_tab, cmd); +} + +void ui_remotely_open_link(const char *uri) { new_tab(uri, NULL, NULL); @@ -1360,5 +1373,38 @@ ui_suspend(void) void ui_end(void) { + endwin(); +} + +static void +exec_external_cmd(const char *cmd, struct tab *tab) +{ + int s; + pid_t p; + + if (cmd == NULL) + return; + endwin(); + + switch (p = fork()) { + case -1: + message("failed to fork: %s", strerror(errno)); + return; + case 0: + execl("/bin/sh", "sh", "-c", cmd, NULL); + warn("exec \"%s\" failed", cmd); + _exit(1); + } + +again: + if (waitpid(p, &s, 0) == -1) { + if (errno == EINTR) + goto again; + } + + refresh(); + clear(); + ui_schedule_redraw(); } + blob - 417738236a3ca7b6c5a51481129087f66e2ae84e blob + 912098a047c9ce38fd2047bfc3de08577b33b6f3 --- ui.h +++ ui.h @@ -145,6 +145,7 @@ void ui_main_loop(void); void ui_on_tab_loaded(struct tab *); void ui_on_tab_refresh(struct tab *); void ui_on_download_refresh(void); +void ui_prompt_download_cmd(char *); void ui_remotely_open_link(const char *); const char *ui_keyname(int); void ui_toggle_side_window(int);