From 10e3ffa305e5a318b4a3ea8cbe8e36cea085e4d7 Mon Sep 17 00:00:00 2001 From: Yugo Nagata Date: Thu, 5 Jun 2025 09:39:09 +0900 Subject: [PATCH 3/3] Improve tab completion for COPY option lists Previously, only the first option in a parenthesized list was suggested during tab completion. Subsequent options after a comma were not completed. This commit enhances the behavior to suggest valid options after each comma. --- src/bin/psql/tab-complete.in.c | 47 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 6d10c818ce0..6f8933a73a2 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -3300,27 +3300,32 @@ match_previous_words(int pattern_id, COMPLETE_WITH("WITH (", "WHERE"); /* Complete COPY FROM|TO [PROGRAM] WITH ( */ - else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(") || - Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(")) - COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL", - "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE", - "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT", - "ON_ERROR", "LOG_VERBOSITY"); - - /* Complete COPY FROM|TO [PROGRAM] WITH (FORMAT */ - else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(", "FORMAT") || - Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(", "FORMAT")) - COMPLETE_WITH("binary", "csv", "text"); - - /* Complete COPY FROM [PROGRAM] WITH (ON_ERROR */ - else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(", "ON_ERROR") || - Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(", "ON_ERROR")) - COMPLETE_WITH("stop", "ignore"); - - /* Complete COPY FROM [PROGRAM] WITH (LOG_VERBOSITY */ - else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(", "LOG_VERBOSITY") || - Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(", "LOG_VERBOSITY")) - COMPLETE_WITH("silent", "default", "verbose"); + else if (HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*") || + HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*")) + { + if (!HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*)") && + !HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*)")) + { + /* We're in an unfinished parenthesized option list. */ + if (ends_with(prev_wd, '(') || ends_with(prev_wd, ',')) + COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL", + "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE", + "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT", + "ON_ERROR", "LOG_VERBOSITY"); + + /* Complete COPY FROM|TO filename WITH (FORMAT */ + else if (TailMatches("FORMAT")) + COMPLETE_WITH("binary", "csv", "text"); + + /* Complete COPY FROM filename WITH (ON_ERROR */ + else if (TailMatches("ON_ERROR")) + COMPLETE_WITH("stop", "ignore"); + + /* Complete COPY FROM filename WITH (LOG_VERBOSITY */ + else if (TailMatches("LOG_VERBOSITY")) + COMPLETE_WITH("silent", "default", "verbose"); + } + } /* Complete COPY FROM [PROGRAM] WITH () */ else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM"), "WITH", MatchAny) || -- 2.43.0