📄 tab-complete.c
字号:
{ static const char *const list_DECLARECURSOR[] = {"WITH HOLD", "WITHOUT HOLD", "FOR", NULL}; COMPLETE_WITH_LIST(list_DECLARECURSOR); }/* DELETE */ /* * Complete DELETE with FROM (only if the word before that is not "ON" * (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT) */ else if (pg_strcasecmp(prev_wd, "DELETE") == 0 && !(pg_strcasecmp(prev2_wd, "ON") == 0 || pg_strcasecmp(prev2_wd, "GRANT") == 0 || pg_strcasecmp(prev2_wd, "BEFORE") == 0 || pg_strcasecmp(prev2_wd, "AFTER") == 0)) COMPLETE_WITH_CONST("FROM"); /* Complete DELETE FROM with a list of tables */ else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 && pg_strcasecmp(prev_wd, "FROM") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* Complete DELETE FROM <table> */ else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 && pg_strcasecmp(prev2_wd, "FROM") == 0) { static const char *const list_DELETE[] = {"USING", "WHERE", "SET", NULL}; COMPLETE_WITH_LIST(list_DELETE); } /* XXX: implement tab completion for DELETE ... USING *//* DROP (when not the previous word) */ /* DROP AGGREGATE */ else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && pg_strcasecmp(prev2_wd, "AGGREGATE") == 0) COMPLETE_WITH_CONST("("); /* DROP object with CASCADE / RESTRICT */ else if ((pg_strcasecmp(prev3_wd, "DROP") == 0 && (pg_strcasecmp(prev2_wd, "CONVERSION") == 0 || pg_strcasecmp(prev2_wd, "DOMAIN") == 0 || pg_strcasecmp(prev2_wd, "FUNCTION") == 0 || pg_strcasecmp(prev2_wd, "INDEX") == 0 || pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 || pg_strcasecmp(prev2_wd, "SCHEMA") == 0 || pg_strcasecmp(prev2_wd, "SEQUENCE") == 0 || pg_strcasecmp(prev2_wd, "TABLE") == 0 || pg_strcasecmp(prev2_wd, "TYPE") == 0 || pg_strcasecmp(prev2_wd, "VIEW") == 0)) || (pg_strcasecmp(prev4_wd, "DROP") == 0 && pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 && prev_wd[strlen(prev_wd) - 1] == ')')) { static const char *const list_DROPCR[] = {"CASCADE", "RESTRICT", NULL}; COMPLETE_WITH_LIST(list_DROPCR); }/* EXPLAIN */ /* * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands */ else if (pg_strcasecmp(prev_wd, "EXPLAIN") == 0) { static const char *const list_EXPLAIN[] = {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "ANALYZE", "VERBOSE", NULL}; COMPLETE_WITH_LIST(list_EXPLAIN); } else if (pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 && pg_strcasecmp(prev_wd, "ANALYZE") == 0) { static const char *const list_EXPLAIN[] = {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "VERBOSE", NULL}; COMPLETE_WITH_LIST(list_EXPLAIN); } else if (pg_strcasecmp(prev_wd, "VERBOSE") == 0 && pg_strcasecmp(prev3_wd, "VACUUM") != 0 && pg_strcasecmp(prev4_wd, "VACUUM") != 0 && (pg_strcasecmp(prev2_wd, "ANALYZE") == 0 || pg_strcasecmp(prev2_wd, "EXPLAIN") == 0)) { static const char *const list_EXPLAIN[] = {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", NULL}; COMPLETE_WITH_LIST(list_EXPLAIN); }/* FETCH && MOVE */ /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */ else if (pg_strcasecmp(prev_wd, "FETCH") == 0 || pg_strcasecmp(prev_wd, "MOVE") == 0) { static const char *const list_FETCH1[] = {"ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE", NULL}; COMPLETE_WITH_LIST(list_FETCH1); } /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */ else if (pg_strcasecmp(prev2_wd, "FETCH") == 0 || pg_strcasecmp(prev2_wd, "MOVE") == 0) { static const char *const list_FETCH2[] = {"ALL", "NEXT", "PRIOR", NULL}; COMPLETE_WITH_LIST(list_FETCH2); } /* * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent, * but we may as well tab-complete both: perhaps some users prefer one * variant or the other. */ else if (pg_strcasecmp(prev3_wd, "FETCH") == 0 || pg_strcasecmp(prev3_wd, "MOVE") == 0) { static const char *const list_FROMIN[] = {"FROM", "IN", NULL}; COMPLETE_WITH_LIST(list_FROMIN); }/* GRANT && REVOKE*/ /* Complete GRANT/REVOKE with a list of privileges */ else if (pg_strcasecmp(prev_wd, "GRANT") == 0 || pg_strcasecmp(prev_wd, "REVOKE") == 0) { static const char *const list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL}; COMPLETE_WITH_LIST(list_privileg); } /* Complete GRANT/REVOKE <sth> with "ON" */ else if (pg_strcasecmp(prev2_wd, "GRANT") == 0 || pg_strcasecmp(prev2_wd, "REVOKE") == 0) COMPLETE_WITH_CONST("ON"); /* * Complete GRANT/REVOKE <sth> ON with a list of tables, views, sequences, * and indexes * * keywords DATABASE, FUNCTION, LANGUAGE, SCHEMA added to query result via * UNION; seems to work intuitively * * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented * here will only work if the privilege list contains exactly one * privilege */ else if ((pg_strcasecmp(prev3_wd, "GRANT") == 0 || pg_strcasecmp(prev3_wd, "REVOKE") == 0) && pg_strcasecmp(prev_wd, "ON") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv, " UNION SELECT 'DATABASE'" " UNION SELECT 'FUNCTION'" " UNION SELECT 'LANGUAGE'" " UNION SELECT 'SCHEMA'" " UNION SELECT 'TABLESPACE'"); /* Complete "GRANT/REVOKE * ON * " with "TO" */ else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 || pg_strcasecmp(prev4_wd, "REVOKE") == 0) && pg_strcasecmp(prev2_wd, "ON") == 0) { if (pg_strcasecmp(prev_wd, "DATABASE") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_databases); else if (pg_strcasecmp(prev_wd, "FUNCTION") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL); else if (pg_strcasecmp(prev_wd, "LANGUAGE") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_languages); else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_schemas); else if (pg_strcasecmp(prev_wd, "TABLESPACE") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); else if (pg_strcasecmp(prev4_wd, "GRANT") == 0) COMPLETE_WITH_CONST("TO"); else COMPLETE_WITH_CONST("FROM"); } /* Complete "GRANT/REVOKE * ON * TO/FROM" with username, GROUP, or PUBLIC */ else if (pg_strcasecmp(prev3_wd, "ON") == 0 && ((pg_strcasecmp(prev5_wd, "GRANT") == 0 && pg_strcasecmp(prev_wd, "TO") == 0) || (pg_strcasecmp(prev5_wd, "REVOKE") == 0 && pg_strcasecmp(prev_wd, "FROM") == 0))) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);/* GROUP BY */ else if (pg_strcasecmp(prev3_wd, "FROM") == 0 && pg_strcasecmp(prev_wd, "GROUP") == 0) COMPLETE_WITH_CONST("BY");/* INSERT */ /* Complete INSERT with "INTO" */ else if (pg_strcasecmp(prev_wd, "INSERT") == 0) COMPLETE_WITH_CONST("INTO"); /* Complete INSERT INTO with table names */ else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 && pg_strcasecmp(prev_wd, "INTO") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* Complete "INSERT INTO <table> (" with attribute names */ else if (rl_line_buffer[start - 1] == '(' && pg_strcasecmp(prev3_wd, "INSERT") == 0 && pg_strcasecmp(prev2_wd, "INTO") == 0) COMPLETE_WITH_ATTR(prev_wd); /* * Complete INSERT INTO <table> with "VALUES" or "SELECT" or "DEFAULT * VALUES" */ else if (pg_strcasecmp(prev3_wd, "INSERT") == 0 && pg_strcasecmp(prev2_wd, "INTO") == 0) { static const char *const list_INSERT[] = {"DEFAULT VALUES", "SELECT", "VALUES", NULL}; COMPLETE_WITH_LIST(list_INSERT); } /* Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" */ else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && pg_strcasecmp(prev3_wd, "INTO") == 0 && prev_wd[strlen(prev_wd) - 1] == ')') { static const char *const list_INSERT[] = {"SELECT", "VALUES", NULL}; COMPLETE_WITH_LIST(list_INSERT); } /* Insert an open parenthesis after "VALUES" */ else if (pg_strcasecmp(prev_wd, "VALUES") == 0 && pg_strcasecmp(prev2_wd, "DEFAULT") != 0) COMPLETE_WITH_CONST("(");/* LOCK */ /* Complete LOCK [TABLE] with a list of tables */ else if (pg_strcasecmp(prev_wd, "LOCK") == 0 || (pg_strcasecmp(prev_wd, "TABLE") == 0 && pg_strcasecmp(prev2_wd, "LOCK") == 0)) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* For the following, handle the case of a single table only for now */ /* Complete LOCK [TABLE] <table> with "IN" */ else if ((pg_strcasecmp(prev2_wd, "LOCK") == 0 && pg_strcasecmp(prev_wd, "TABLE")) || (pg_strcasecmp(prev2_wd, "TABLE") == 0 && pg_strcasecmp(prev3_wd, "LOCK") == 0)) COMPLETE_WITH_CONST("IN"); /* Complete LOCK [TABLE] <table> IN with a lock mode */ else if (pg_strcasecmp(prev_wd, "IN") == 0 && (pg_strcasecmp(prev3_wd, "LOCK") == 0 || (pg_strcasecmp(prev3_wd, "TABLE") == 0 && pg_strcasecmp(prev4_wd, "LOCK") == 0))) { static const char *const lock_modes[] = {"ACCESS SHARE MODE", "ROW SHARE MODE", "ROW EXCLUSIVE MODE", "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE", "SHARE ROW EXCLUSIVE MODE", "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE", NULL}; COMPLETE_WITH_LIST(lock_modes); }/* NOTIFY */ else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0) COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(relname) FROM pg_catalog.pg_listener WHERE substring(pg_catalog.quote_ident(relname),1,%d)='%s'");/* OWNER TO - complete with available roles*/ else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 && pg_strcasecmp(prev_wd, "TO") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_roles);/* ORDER BY */ else if (pg_strcasecmp(prev3_wd, "FROM") == 0 && pg_strcasecmp(prev_wd, "ORDER") == 0) COMPLETE_WITH_CONST("BY"); else if (pg_strcasecmp(prev4_wd, "FROM") == 0 && pg_strcasecmp(prev2_wd, "ORDER") == 0 && pg_strcasecmp(prev_wd, "BY") == 0) COMPLETE_WITH_ATTR(prev3_wd);/* PREPARE xx AS */ else if (pg_strcasecmp(prev_wd, "AS") == 0 && pg_strcasecmp(prev3_wd, "PREPARE") == 0) { static const char *const list_PREPARE[] = {"SELECT", "UPDATE", "INSERT", "DELETE", NULL}; COMPLETE_WITH_LIST(list_PREPARE); }/* REINDEX */ else if (pg_strcasecmp(prev_wd, "REINDEX") == 0) { static const char *const list_REINDEX[] = {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL}; COMPLETE_WITH_LIST(list_REINDEX); } else if (pg_strcasecmp(prev2_wd, "REINDEX") == 0) { if (pg_strcasecmp(prev_wd, "TABLE") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); else if (pg_strcasecmp(prev_wd, "INDEX") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL); else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 || pg_strcasecmp(prev_wd, "DATABASE") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_databases); }/* SELECT */ /* naah . . . *//* SET, RESET, SHOW */ /* Complete with a variable name */ else if ((pg_strcasecmp(prev_wd, "SET") == 0 && pg_strcasecmp(prev3_wd, "UPDATE") != 0) || pg_strcasecmp(prev_wd, "RESET") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_set_vars); else if (pg_strcasecmp(prev_wd, "SHOW") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_show_vars); /* Complete "SET TRANSACTION" */ else if ((pg_strcasecmp(prev2_wd, "SET") == 0 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) || (pg_strcasecmp(prev2_wd, "START") == 0 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) || (pg_strcasecmp(prev2_wd, "BEGIN") == 0 && pg_strcasecmp(prev_wd, "WORK") == 0) || (pg_strcasecmp(prev2_wd, "BEGIN") == 0 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) || (pg_strcasecmp(prev4_wd, "SESSION") == 0 && pg_strcasecmp(prev3_wd, "CHARACTERISTICS") == 0 && pg_strcasecmp(prev2_wd, "AS") == 0 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0)) { static const char *const my_list[] = {"ISOLATION LEVEL", "READ", NULL}; COMPLETE_WITH_LIST(my_list); } else if ((pg_strcasecmp(prev3_wd, "SET") == 0 || pg_strcasecmp(prev3_wd, "BEGIN") == 0 || pg_strcasecmp(prev3_wd, "START") == 0 || (pg_strcasecmp(prev4_wd, "CHARACTERISTICS") == 0 && pg_strcasecmp(prev3_wd, "AS") == 0)) && (pg_strcasecmp(prev2_wd, "TRANSACTION") == 0 || pg_strcasecmp(prev2_wd, "WORK") == 0) && pg_strcasecmp(prev_wd, "ISOLATION") == 0) COMPLETE_WITH_CONST("LEVEL"); else if ((pg_strcasecmp(prev4_wd, "SET") == 0 || pg_strcasecmp(prev4_wd, "BEGIN") == 0 || pg_strcasecmp(prev4_wd, "START") == 0 || pg_strcasecmp(prev4_wd, "AS") == 0) && (pg_strcasecmp(prev3_wd, "TRANSACTION") == 0 || pg_strcasecmp(prev3_wd, "WORK") == 0) && pg_strcasecmp(prev2_wd, "ISOLATION") == 0 && pg_strcasecmp(prev_wd, "LEVEL") == 0) { static const char *const my_list[] = {"READ", "REPEATABLE", "SERIALIZABLE", NULL}; COMPLETE_WITH_LIST(my_list); } else if ((pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 || pg_strcasecmp(prev4_wd, "WORK") == 0) && pg_strcasecmp(prev3_wd, "ISOLATION") == 0 && pg_strcasecmp(prev2_wd, "LEVEL") == 0 && pg_strcasecmp(prev_wd, "READ") == 0) { static const char *const my_list[] = {"UNCOMMITTED", "COMMITTED", NULL}; COMPLETE_WITH_LIST(my_list); } else if ((pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 || pg_strcasecmp(prev4_wd, "WORK") == 0) && pg_strcasecmp(prev3_wd, "ISOLATION") == 0 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -