From a415f6a2591a785abac22ac9bddebb0caefa9d49 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 18 Nov 2019 09:49:16 +1300 Subject: [PATCH] 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. Discussion: https://postgr.es/m/CA%2BhUKG%2BzGd7RigjWbxwhzGW59gUpf76ydQECeGdEdodH6nd__A%40mail.gmail.com --- doc/src/sgml/ref/psql-ref.sgml | 12 ++++++++++++ src/bin/psql/prompt.c | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 7789fc6177..e9fde65d72 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 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 195192a95d..8013b329ac 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; 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,32 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) strlcat(destination, buf, sizeof(destination)); } + if (prompt_string == pset.prompt1) + { + char *p = destination; + bool visible = true; + char c; + + /* Count the visible characters, for use by %w in PROMPT2. */ + last_prompt1_width = 0; + while ((c = *p++)) + { +#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE) + if (c == RL_PROMPT_START_IGNORE) + { + visible = false; + continue; + } + else if (c == RL_PROMPT_END_IGNORE) + { + visible = true; + continue; + } +#endif + if (visible) + ++last_prompt1_width; + } + } + return destination; } -- 2.23.0