From: Thomas Munro Date: Tue, 19 Nov 2019 02:17:15 +0000 (+1300) Subject: Allow invisible PROMPT2 in psql. X-Git-Tag: REL_13_BETA1~1161 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7f338369ca624ca6c2e4f579623274c88d325bce;p=thirdparty%2Fpostgresql.git Allow invisible PROMPT2 in psql. Keep track of the visible width of PROMPT1, and provide %w as a way for PROMPT2 to generate the same number of spaces. Author: Thomas Munro, with ideas from others Reviewed-by: Tom Lane (earlier version) Discussion: https://postgr.es/m/CA%2BhUKG%2BzGd7RigjWbxwhzGW59gUpf76ydQECeGdEdodH6nd__A%40mail.gmail.com --- diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 7789fc61776..a55ca6a2666 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -4310,6 +4310,18 @@ testdb=> \set PROMPT1 '%[%033[1;33;40m%]%n@%/%R%[%033[0m%]%# ' + + %w + + + Whitespace of the same width as the most recent output of + PROMPT1. This can be used as a + PROMPT2 setting, so that multi-line statements are + aligned with the first line, but there is no visible secondary prompt. + + + + To insert a percent sign into your prompt, write diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index 195192a95d6..41c6f21ecfc 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -39,6 +39,7 @@ * %n - database user name * %/ - current database * %~ - like %/ but "~" when database name equals user name + * %w - whitespace of the same width as the most recent output of PROMPT1 * %# - "#" if superuser, ">" otherwise * %R - in prompt1 normally =, or ^ if single line mode, * or a ! if session is not connected to a database; @@ -74,6 +75,7 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) bool esc = false; const char *p; const char *prompt_string = "? "; + static size_t last_prompt1_width = 0; switch (status) { @@ -124,6 +126,13 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) } break; + /* Whitespace of the same width as the last PROMPT1 */ + case 'w': + if (pset.db) + memset(buf, ' ', + Min(last_prompt1_width, sizeof(buf) - 1)); + break; + /* DB server hostname (long/short) */ case 'M': case 'm': @@ -336,5 +345,48 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) strlcat(destination, buf, sizeof(destination)); } + /* Compute the visible width of PROMPT1, for PROMPT2's %w */ + if (prompt_string == pset.prompt1) + { + char *p = destination; + char *end = p + strlen(p); + bool visible = true; + + last_prompt1_width = 0; + while (*p) + { +#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE) + if (*p == RL_PROMPT_START_IGNORE) + { + visible = false; + ++p; + } + else if (*p == RL_PROMPT_END_IGNORE) + { + visible = true; + ++p; + } + else +#endif + { + int chlen, + chwidth; + + chlen = PQmblen(p, pset.encoding); + if (p + chlen > end) + break; /* Invalid string */ + + if (visible) + { + chwidth = PQdsplen(p, pset.encoding); + if (chwidth > 0) + last_prompt1_width += chwidth; + } + + p += chlen; + } + } + } + return destination; }