diff options
author | Thomas Munro <tmunro@postgresql.org> | 2019-11-19 15:17:15 +1300 |
---|---|---|
committer | Thomas Munro <tmunro@postgresql.org> | 2019-11-19 15:56:21 +1300 |
commit | 7f338369ca624ca6c2e4f579623274c88d325bce (patch) | |
tree | e0e1d252b29972dc72b6cbe0a11817f7eeed8da5 /src/bin/psql/prompt.c | |
parent | cec2edfa7859279f36d2374770ca920c59c73dd8 (diff) |
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
Diffstat (limited to 'src/bin/psql/prompt.c')
-rw-r--r-- | src/bin/psql/prompt.c | 52 |
1 files changed, 52 insertions, 0 deletions
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; } |