Re: psql: tab completion differs on semicolon placement - Mailing list pgsql-hackers

From Dagfinn Ilmari Mannsåker
Subject Re: psql: tab completion differs on semicolon placement
Date
Msg-id 87tuieted7.fsf@wibble.ilmari.org
Whole thread Raw
In response to Re: psql: tab completion differs on semicolon placement  (David Fetter <david@fetter.org>)
List pgsql-hackers
David Fetter <david@fetter.org> writes:

> On Mon, Sep 20, 2021 at 08:26:51PM +0100, Dagfinn Ilmari Mannsåker wrote:
>
>> The same applies to any completion after a MatchAny that ends in a any
>> of the WORD_BREAKS characters (except whitespace and () which are
>> handled specially).
>> 
>> #define WORD_BREAKS             "\t\n@$><=;|&{() "
>> 
>> IMO a fix should be more principled than just special-casing semicolon
>> and CREATE TABLE.  Maybe get_previous_words() should stop when it sees
>> an unquoted semicolon?
>
> Is there some reason get_previous_words() shouldn't stop for
> everything that's WORD_BREAKS? If not, making that the test might make the
> general rule a little simpler to write, and if WORD_BREAKS ever
> changed, for example to include all space, or all breaking space, or
> similar, the consequences would at least not propagate through
> seemingly unrelated code.

By "stopping" I meant ignoring everything before the last semicolon when
splitting the buffer into words, i.e. not putting them into the
previous_words array, so they're not considered by the
(Tail|Head)?Matches(CS)? macros.  WORD_BREAKS is the list of characters
used for splitting the input buffer into the previous_words array, so it
would need to keep going past those, or you'd only be able to match the
last word when tab completing, rendering the entire exercise pointless.

> At the moment, get_previous_words() does look for everything in
> WORD_BREAKS, and then accounts for double quotes (") and then does
> something clever to account for double quotes and the quoting behavior
> that doubling them ("") accomplishes. Anyhow, that looks like it
> should work in this case, but clearly it's not.

WORD_BREAK characters inside double-quoted identifiers are handled
correclty, but only after you've typed the closing quote.  If you have
an ambiguous prefix that contains a WORD_BREAK character, you can't
tab-complete the rest:

ilmari@[local]:5432 ~=# drop table "foo<tab><tab>
"foo$bar"  "foo$zot"  "foo-bar"  "foo-zot"
ilmari@[local]:5432 ~=# drop table "foo-<tab><tab>
"foo-bar"  "foo-zot"
ilmari@[local]:5432 ~=# rop table "foo$<tab><tab>

ilmari@[local]:5432 ~=# drop table "foo$bar" <tab><tab>
cascade   restrict

Tangentially, I would argue that $ shouldn't be a WORD_BREAK character,
since it's valid in unquoted identifiers (except at the start, just like
numbers).  But you do need to quote such identifiers when
tab-completing, since quote_ident() quotes anything tht's not all
lowercase letters, underscores and numbers.

- ilmari



pgsql-hackers by date:

Previous
From: Amit Kapila
Date:
Subject: Re: POC: Cleaning up orphaned files using undo logs
Next
From: Marcos Pegoraro
Date:
Subject: Re: logical replication restrictions