Re: psql: tab completion differs on semicolon placement

From: Dagfinn Ilmari Mannsåker <ilmari(at)ilmari(dot)org>
To: David Fetter <david(at)fetter(dot)org>
Cc: Daniel Gustafsson <daniel(at)yesql(dot)se>, PostgreSQL Developers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: psql: tab completion differs on semicolon placement
Date: 2021-09-21 10:25:08
Message-ID: 87tuieted7.fsf@wibble.ilmari.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

David Fetter <david(at)fetter(dot)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(at)$><=;|&{() "
>>
>> 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(at)[local]:5432 ~=# drop table "foo<tab><tab>
"foo$bar" "foo$zot" "foo-bar" "foo-zot"
ilmari(at)[local]:5432 ~=# drop table "foo-<tab><tab>
"foo-bar" "foo-zot"
ilmari(at)[local]:5432 ~=# rop table "foo$<tab><tab>

ilmari(at)[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

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Marcos Pegoraro 2021-09-21 10:51:14 Re: logical replication restrictions
Previous Message Amit Kapila 2021-09-21 09:59:25 Re: POC: Cleaning up orphaned files using undo logs