Commit Diff


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 <limits.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -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 <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
@@ -0,0 +1,23 @@
+/*
+ * 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
@@ -37,7 +37,6 @@
 
 #include <curses.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <locale.h>
 #include <signal.h>
 #include <stdarg.h>
@@ -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