From 7b3af5190a7816f0b8dae39332bd04bfcfd3adc5 Mon Sep 17 00:00:00 2001
From: alterego655 <824662526@qq.com>
Date: Fri, 7 Nov 2025 18:04:46 +0800
Subject: [PATCH v3] Add tab completion support for the WAIT FOR command

This commit implements tab completion for the WAIT FOR LSN command in psql.

Discussion: https://postgr.es/m/CABPTF7WnLPKcoTGCGge1dDpOieZ2HGF7OVqhNXDcRLPPdSw%3DxA%40mail.gmail.com
Author: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com>
---
 src/bin/psql/tab-complete.in.c | 37 +++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 316a2dafbf1..51806597037 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1270,7 +1270,8 @@ static const char *const sql_commands[] = {
 	"REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
 	"RESET", "REVOKE", "ROLLBACK",
 	"SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
-	"TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
+	"TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES",
+	"WAIT FOR", "WITH",
 	NULL
 };
 
@@ -5310,6 +5311,40 @@ match_previous_words(int pattern_id,
 	else if (HeadMatches("VACUUM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_vacuumables);
 
+/*
+ * WAIT FOR LSN '<lsn>' [ WITH ( option [, ...] ) ]
+ * where option can be:
+ *   TIMEOUT '<timeout>'
+ *   NO_THROW
+ */
+	else if (Matches("WAIT"))
+		COMPLETE_WITH("FOR");
+	else if (Matches("WAIT", "FOR"))
+		COMPLETE_WITH("LSN");
+	else if (Matches("WAIT", "FOR", "LSN"))
+		/* No completion for LSN value - user must provide manually */
+		;
+	else if (Matches("WAIT", "FOR", "LSN", MatchAny))
+		COMPLETE_WITH("WITH");
+	else if (Matches("WAIT", "FOR", "LSN", MatchAny, "WITH"))
+		COMPLETE_WITH("(");
+	else if (HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*") &&
+			 !HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*)"))
+	{
+		/*
+		 * This fires if we're in an unfinished parenthesized option list.
+		 * get_previous_words treats a completed parenthesized option list as
+		 * one word, so the above test is correct.
+		 */
+		if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
+			COMPLETE_WITH("timeout", "no_throw");
+
+		/*
+		 * timeout takes a string value, no_throw takes no value. We don't
+		 * offer completions for these values.
+		 */
+	}
+
 /* WITH [RECURSIVE] */
 
 	/*
-- 
2.39.5 (Apple Git-154)

