Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7f33836

Browse files
committed
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
1 parent cec2edf commit 7f33836

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4310,6 +4310,18 @@ testdb=> \set PROMPT1 '%[%033[1;33;40m%]%n@%/%R%[%033[0m%]%# '
43104310
</listitem>
43114311
</varlistentry>
43124312

4313+
<varlistentry>
4314+
<term><literal>%w</literal></term>
4315+
<listitem>
4316+
<para>
4317+
Whitespace of the same width as the most recent output of
4318+
<varname>PROMPT1</varname>. This can be used as a
4319+
<varname>PROMPT2</varname> setting, so that multi-line statements are
4320+
aligned with the first line, but there is no visible secondary prompt.
4321+
</para>
4322+
</listitem>
4323+
</varlistentry>
4324+
43134325
</variablelist>
43144326

43154327
To insert a percent sign into your prompt, write

src/bin/psql/prompt.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* %n - database user name
4040
* %/ - current database
4141
* %~ - like %/ but "~" when database name equals user name
42+
* %w - whitespace of the same width as the most recent output of PROMPT1
4243
* %# - "#" if superuser, ">" otherwise
4344
* %R - in prompt1 normally =, or ^ if single line mode,
4445
* or a ! if session is not connected to a database;
@@ -74,6 +75,7 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
7475
bool esc = false;
7576
const char *p;
7677
const char *prompt_string = "? ";
78+
static size_t last_prompt1_width = 0;
7779

7880
switch (status)
7981
{
@@ -124,6 +126,13 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
124126
}
125127
break;
126128

129+
/* Whitespace of the same width as the last PROMPT1 */
130+
case 'w':
131+
if (pset.db)
132+
memset(buf, ' ',
133+
Min(last_prompt1_width, sizeof(buf) - 1));
134+
break;
135+
127136
/* DB server hostname (long/short) */
128137
case 'M':
129138
case 'm':
@@ -336,5 +345,48 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
336345
strlcat(destination, buf, sizeof(destination));
337346
}
338347

348+
/* Compute the visible width of PROMPT1, for PROMPT2's %w */
349+
if (prompt_string == pset.prompt1)
350+
{
351+
char *p = destination;
352+
char *end = p + strlen(p);
353+
bool visible = true;
354+
355+
last_prompt1_width = 0;
356+
while (*p)
357+
{
358+
#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
359+
if (*p == RL_PROMPT_START_IGNORE)
360+
{
361+
visible = false;
362+
++p;
363+
}
364+
else if (*p == RL_PROMPT_END_IGNORE)
365+
{
366+
visible = true;
367+
++p;
368+
}
369+
else
370+
#endif
371+
{
372+
int chlen,
373+
chwidth;
374+
375+
chlen = PQmblen(p, pset.encoding);
376+
if (p + chlen > end)
377+
break; /* Invalid string */
378+
379+
if (visible)
380+
{
381+
chwidth = PQdsplen(p, pset.encoding);
382+
if (chwidth > 0)
383+
last_prompt1_width += chwidth;
384+
}
385+
386+
p += chlen;
387+
}
388+
}
389+
}
390+
339391
return destination;
340392
}

0 commit comments

Comments
 (0)