Commit Diff


commit - 3c7ed8d83ed06a3b7f30ceb6ba692e515f91e980
commit + e1bf3d6e8c8b52e910473d62f747176f22e206b1
blob - b2d69256bdb2e6b0a75dff773828e3988045022f
blob + f98e328499a42678d5e82a73dfc56a7126464d7c
--- cmd.c
+++ cmd.c
@@ -1176,4 +1176,12 @@ cmd_search(struct buffer *buffer)
 	enter_minibuffer(sensible_self_insert, search_select, exit_minibuffer, NULL,
 	    NULL, NULL, 0);
 	strlcpy(ministate.prompt, "Search: ", sizeof(ministate.prompt));
+}
+
+void
+cmd_mini_edit_external(struct buffer *buffer)
+{
+	GUARD_READ_ONLY();
+
+	ui_edit_externally();
 }
blob - bb81e7198c325db75faf09ebfbca2e3a5f86d316
blob + 6031a71966db32d3279e35426e334c79e5d776b1
--- cmd.h
+++ cmd.h
@@ -42,6 +42,7 @@ CMD(cmd_mini_abort,		"Abort the current minibuffer act
 CMD(cmd_mini_complete_and_exit,	"Complete the current minibuffer action.");
 CMD(cmd_mini_delete_backward_char, "Delete the character before the point.");
 CMD(cmd_mini_delete_char,	"Delete the character after the point.");
+CMD(cmd_mini_edit_external,	"Use an external editor to compose the text.");
 CMD(cmd_mini_goto_beginning,	"Select the first completion.");
 CMD(cmd_mini_goto_end,		"Select the last completion.");
 CMD(cmd_mini_kill_line,		"Delete from point until the end of the line.");
blob - ab7dfac0e780c559474ab835780372a9a766a5fe
blob + 13220c95e1ac0c13dc33f87674639ee5752ef16f
--- defaults.c
+++ defaults.c
@@ -502,6 +502,7 @@ load_default_keys(void)
 	minibuffer_set_key("del",	cmd_mini_delete_backward_char);
 	minibuffer_set_key("backspace",	cmd_mini_delete_backward_char);
 	minibuffer_set_key("C-h",	cmd_mini_delete_backward_char);
+	minibuffer_set_key("C-x",	cmd_mini_edit_external);
 
 	minibuffer_set_key("C-b",	cmd_backward_char);
 	minibuffer_set_key("C-f",	cmd_forward_char);
blob - 519753fc89a5c9e6738d0786725f9815c5668644
blob + 7ffc4801c3f0d75961f0597e18289164fe3aeb19
--- ui.c
+++ ui.c
@@ -1407,4 +1407,87 @@ again:
 	clear();
 	ui_schedule_redraw();
 }
+
+#define TMPFILE "/tmp/telescope.XXXXXXXXXX"
+
+void
+ui_edit_externally(void)
+{
+	FILE		*fp;
+	char		 buf[1024 + 1];
+	size_t		 r, len = 0;
+	const char	*editor;
+	char		 sfn[sizeof(TMPFILE)];
+	pid_t		 pid;
+	int		 fd, ret, s;
 
+	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 = "ed";
+
+	endwin();
+	fprintf(stderr, "%s: running %s %s\n", getprogname(), editor, sfn);
+
+	switch (pid = fork()) {
+	case -1:
+		message("failed to fork: %s", strerror(errno));
+		(void) unlink(sfn);
+		return;
+	case 0:
+		execlp(editor, editor, sfn, NULL);
+		warn("exec \"%s\" failed", editor);
+		_exit(1);
+	}
+
+	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", editor);
+		(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';
+
+	ministate.donefn(buf);
+	exit_minibuffer();
+}
blob - faa3c3ec05175a95c64bbbe4cf3be10c56e78e86
blob + fbcce36ac69ef321f6dbbeed10e560f77d5cb8c4
--- ui.h
+++ ui.h
@@ -158,5 +158,6 @@ void		 ui_read(const char *, void (*)(const char *, st
 void		 ui_other_window(void);
 void		 ui_suspend(void);
 void		 ui_end(void);
+void		 ui_edit_externally(void);
 
 #endif