commit - 187eb2bac384268766bd53c86b3584d5effeee0c
commit + 0548291a79ee63a4ee88dab9574c1def724c3a01
blob - 53f52a7e82ab528e0782e67d60d2c5fa23e50afe
blob + 9709b0427066e78d52e1e9f03dd66506a9ef828f
--- Makefile.am
+++ Makefile.am
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
#include "compat.h"
#include <limits.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include "compl.h"
#include "defaults.h"
#include "ev.h"
+#include "exec.h"
#include "hist.h"
#include "keymap.h"
#include "mcache.h"
{
message("Zzz...");
ui_suspend();
+ kill(getpid(), SIGSTOP);
+ ui_resume();
}
void
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
+/*
+ * Copyright (c) 2024 Omar Polo <op@omarpolo.com>
+ *
+ * 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 <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#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
+/*
+ * Copyright (c) 2024 Omar Polo <op@omarpolo.com>
+ *
+ * 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
#include <curses.h>
#include <errno.h>
-#include <fcntl.h>
#include <locale.h>
#include <signal.h>
#include <stdarg.h>
#include "cmd.h"
#include "defaults.h"
#include "ev.h"
+#include "exec.h"
#include "hist.h"
#include "keymap.h"
#include "mailcap.h"
#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 *);
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;
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
ui_suspend(void)
{
endwin();
+}
- kill(getpid(), SIGSTOP);
-
+void
+ui_resume(void)
+{
refresh();
clear();
rearrange_windows();
{
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
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