On Tue, Jun 7, 2022 at 3:23 PM Tom Lane <t...@sss.pgh.pa.us> wrote: > The code needs a comment about why it's emitting a newline, though. > In particular, it had better explain why that should be conditional > on !pagerpipe, because that makes no sense to me.
Yeah. OK, here's my take: + /* + * If the terminal driver echoed "^C", libedit/libreadline might be + * confused about the cursor position. Therefore, inject a newline + * before the next prompt is displayed. We only do this when not using + * a pager, because pagers are expected to restore the screen to a sane + * state on exit. + */ AFAIK pagers conventionally use something like termcap ti/te[1] to restore the screen, or equivalents in tinfo etc (likely via curses). If we were to inject an extra newline we'd just have a blank line for nothing. I suppose there could be a hypothetical pager that doesn't follow that convention, and in fact both less and pspg have a -X option to preserve last output, but in any case I expect that pagers disable echoing, so I don't think the ^C will make it to the screen, and furthermore ^C isn't used for exit anyway. Rather than speculate about the precise details, I just said "... sane state on exit". Pavel, do you agree? Here's how it looks after I enter and then exit Pavel's streaming pager: $ PSQL_WATCH_PAGER='pspg --stream' ~/install/bin/psql postgres psql (15beta1) Type "help" for help. postgres=# select; -- (1 row) postgres=# \watch 1 postgres=# FWIW it's the same with PSQL_WATCH_PAGER='less'. [1] https://www.gnu.org/software/termutils/manual/termcap-1.3/html_node/termcap_39.html
From a9389a8755379d4df2c52eb760d355aa5cf0ff96 Mon Sep 17 00:00:00 2001 From: Thomas Munro <thomas.mu...@gmail.com> Date: Tue, 7 Jun 2022 14:18:51 +1200 Subject: [PATCH v2] Fix \watch's interaction with libedit/libreadline. When you hit ^C, the terminal driver in Unix-like systems echos "^C" as well as sending an interrupt signal (depending on stty settings). The line editing library (libedit/libreadline) is then confused about the current cursor location, and might corrupt the display. Fix, by moving to a new line before the next prompt is displayed. Author: Pavel Stehule <pavel.steh...@gmail.com> Reported-by: Tom Lane <t...@sss.pgh.pa.us> Discussion: https://postgr.es/m/3278793.1626198638%40sss.pgh.pa.us --- src/bin/psql/command.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index b51d28780b..7f366c80e9 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -5169,6 +5169,18 @@ do_watch(PQExpBuffer query_buf, double sleep) pclose(pagerpipe); restore_sigpipe_trap(); } + else + { + /* + * If the terminal driver echoed "^C", libedit/libreadline might be + * confused about the cursor position. Therefore, inject a newline + * before the next prompt is displayed. We only do this when not using + * a pager, because pagers are expected to restore the screen to a sane + * state on exit. + */ + fprintf(stdout, "\n"); + fflush(stdout); + } #ifdef HAVE_POSIX_DECL_SIGWAIT /* Disable the interval timer. */ -- 2.35.1