diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 7789fc6..c8f9cb7 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1831,9 +1831,10 @@ testdb=&gt;
         the normal rules of <application>psql</application>, treating the
         whole buffer as a single line.  Any complete queries are immediately
         executed; that is, if the query buffer contains or ends with a
-        semicolon, everything up to that point is executed.  Whatever remains
-        will wait in the query buffer; type semicolon or <literal>\g</literal> to
-        send it, or <literal>\r</literal> to cancel it by clearing the query buffer.
+        semicolon, everything up to that point is executed and removed from
+        the query buffer.  Whatever remains in the query buffer is
+        redisplayed.  Type semicolon or <literal>\g</literal> to send it,
+        or <literal>\r</literal> to cancel it by clearing the query buffer.
         Treating the buffer as a single line primarily affects meta-commands:
         whatever is in the buffer after a meta-command will be taken as
         argument(s) to the meta-command, even if it spans multiple lines.
@@ -1893,7 +1894,8 @@ Tue Oct 26 21:40:57 CEST 1999
          in the form of a <command>CREATE OR REPLACE FUNCTION</command> or
          <command>CREATE OR REPLACE PROCEDURE</command> command.
          Editing is done in the same way as for <literal>\edit</literal>.
-         After the editor exits, the updated command waits in the query buffer;
+         After the editor exits, the updated command is executed immediately
+         if you added a semicolon to it.  Otherwise it is redisplayed;
          type semicolon or <literal>\g</literal> to send it, or <literal>\r</literal>
          to cancel.
         </para>
@@ -1969,7 +1971,8 @@ Tue Oct 26 21:40:57 CEST 1999
          This command fetches and edits the definition of the named view,
          in the form of a <command>CREATE OR REPLACE VIEW</command> command.
          Editing is done in the same way as for <literal>\edit</literal>.
-         After the editor exits, the updated command waits in the query buffer;
+         After the editor exits, the updated command is executed immediately
+         if you added a semicolon to it.  Otherwise it is redisplayed;
          type semicolon or <literal>\g</literal> to send it, or <literal>\r</literal>
          to cancel.
         </para>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index b981ae8..7f57da8 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3508,7 +3508,8 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
 		{
 			unsigned int ql = query_buf->len;
 
-			if (ql == 0 || query_buf->data[ql - 1] != '\n')
+			/* force newline-termination of what we send to editor */
+			if (ql > 0 && query_buf->data[ql - 1] != '\n')
 			{
 				appendPQExpBufferChar(query_buf, '\n');
 				ql++;
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index b3a8407..f7b1b94 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -47,6 +47,7 @@ MainLoop(FILE *source)
 	volatile int successResult = EXIT_SUCCESS;
 	volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
 	volatile promptStatus_t prompt_status = PROMPT_READY;
+	volatile bool need_redisplay = false;
 	volatile int count_eof = 0;
 	volatile bool die_on_error = false;
 	FILE	   *prev_cmd_source;
@@ -118,6 +119,7 @@ MainLoop(FILE *source)
 			count_eof = 0;
 			slashCmdStatus = PSQL_CMD_UNKNOWN;
 			prompt_status = PROMPT_READY;
+			need_redisplay = false;
 			pset.stmt_lineno = 1;
 			cancel_pressed = false;
 
@@ -152,6 +154,18 @@ MainLoop(FILE *source)
 			/* May need to reset prompt, eg after \r command */
 			if (query_buf->len == 0)
 				prompt_status = PROMPT_READY;
+			/* If query buffer came from \e, redisplay it with a prompt */
+			if (need_redisplay)
+			{
+				if (query_buf->len > 0)
+				{
+					fputs(get_prompt(PROMPT_READY, cond_stack), stdout);
+					fputs(query_buf->data, stdout);
+					fflush(stdout);
+				}
+				need_redisplay = false;
+			}
+			/* Now we can fetch a line */
 			line = gets_interactive(get_prompt(prompt_status, cond_stack),
 									query_buf);
 		}
@@ -518,6 +532,10 @@ MainLoop(FILE *source)
 				{
 					/* should not see this in inactive branch */
 					Assert(conditional_active(cond_stack));
+					/* ensure what came back from editing ends in a newline */
+					if (query_buf->len > 0 &&
+						query_buf->data[query_buf->len - 1] != '\n')
+						appendPQExpBufferChar(query_buf, '\n');
 					/* rescan query_buf as new input */
 					psql_scan_finish(scan_state);
 					free(line);
@@ -529,6 +547,8 @@ MainLoop(FILE *source)
 									pset.encoding, standard_strings());
 					line_saved_in_history = false;
 					prompt_status = PROMPT_READY;
+					/* we'll want to redisplay after parsing what we have */
+					need_redisplay = true;
 				}
 				else if (slashCmdStatus == PSQL_CMD_TERMINATE)
 					break;
