diff options
author | Bruce Momjian <bruce@momjian.us> | 1999-11-04 21:56:02 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1999-11-04 21:56:02 +0000 |
commit | a45195a191eec367a4f305bb71ab541d17a3b9f9 (patch) | |
tree | 99b815a93f6175b0db76c2da0da39e95a0ee6b8d /src/bin/psql/prompt.c | |
parent | 2ea3b6d63addeaf07267e2390597645cbf013c36 (diff) | |
download | postgresql-a45195a191eec367a4f305bb71ab541d17a3b9f9.tar.gz postgresql-a45195a191eec367a4f305bb71ab541d17a3b9f9.zip |
Major psql overhaul by Peter Eisentraut.
Diffstat (limited to 'src/bin/psql/prompt.c')
-rw-r--r-- | src/bin/psql/prompt.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c new file mode 100644 index 00000000000..a0fa7975953 --- /dev/null +++ b/src/bin/psql/prompt.c @@ -0,0 +1,256 @@ +#include <config.h> +#include <c.h> +#include "prompt.h" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <libpq-fe.h> + +#include "settings.h" +#include "common.h" + +#ifdef WIN32 +#define popen(x,y) _popen(x,y) +#define pclose(x) _pclose(x) +#endif + + + +/*-------------------------- + * get_prompt + * + * Returns a statically allocated prompt made by interpolating certain + * tcsh style escape sequences into pset->vars "prompt1|2|3". + * (might not be completely multibyte safe) + * + * Defined interpolations are: + * %M - database server hostname (or "." if not TCP/IP) + * %m - like %M but hostname truncated after first dot + * %> - database server port number (or "." if not TCP/IP) + * %n - database user name + * %/ - current database + * %~ - like %/ but "~" when database name equals user name + * %# - "#" if the username is postgres, ">" otherwise + * %R - in prompt1 normally =, or ^ if single line mode, + * or a ! if session is not connected to a database; + * in prompt2 -, *, ', or "; + * in prompt3 nothing + * %? - the error code of the last query (not yet implemented) + * %% - a percent sign + * + * %[0-9] - the character with the given decimal code + * %0[0-7] - the character with the given octal code + * %0x[0-9A-Fa-f] - the character with the given hexadecimal code + * + * %`command` - The result of executing command in /bin/sh with trailing + * newline stripped. + * %$name$ - The value of the psql/environment/magic varible 'name' + * (same rules as for, e.g., \echo $foo) + * (those will not be rescanned for more escape sequences!) + * + * + * If the application-wide prompts became NULL somehow, the returned string + * will be empty (not NULL!). Do not free() the result of this function unless + * you want trouble. + *-------------------------- + */ +const char * +get_prompt(PsqlSettings *pset, promptStatus_t status) +{ +#define MAX_PROMPT_SIZE 256 + static char destination[MAX_PROMPT_SIZE+1]; + char buf[MAX_PROMPT_SIZE+1]; + bool esc = false; + const char *p; + const char * prompt_string; + + if (GetVariable(pset->vars, "quiet")) + return ""; + + if (status == PROMPT_READY) + prompt_string = GetVariable(pset->vars, "prompt1"); + else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT) + prompt_string = GetVariable(pset->vars, "prompt2"); + else if (status == PROMPT_COPY) + prompt_string = GetVariable(pset->vars, "prompt3"); + else + prompt_string = "? "; + + + destination[0] = '\0'; + + for (p = prompt_string; + p && *p && strlen(destination)<MAX_PROMPT_SIZE; + p++) + { + MemSet(buf, 0, MAX_PROMPT_SIZE+1); + if (esc) + { + switch (*p) + { + case '%': + strcpy(buf, "%"); + break; + + /* Current database */ + case '/': + if (pset->db) + strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE); + break; + case '~': { + const char * var; + if (pset->db) { + if ( strcmp(PQdb(pset->db), PQuser(pset->db))==0 || + ( (var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db))==0) ) + strcpy(buf, "~"); + else + strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE); + } + break; + } + /* DB server hostname (long/short) */ + case 'M': + case 'm': + if (pset->db) { + if (PQhost(pset->db)) { + strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE); + if (*p == 'm') + buf[strcspn(buf,".")] = '\0'; + } + else + buf[0] = '.'; + } + break; + /* DB server port number */ + case '>': + if (pset->db) { + if (PQhost(pset->db)) + strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE); + else + buf[0] = '.'; + } + break; + /* DB server user name */ + case 'n': + if (pset->db) + strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE); + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + long int l; + char * end; + l = strtol(p, &end, 0); + sprintf(buf, "%c", (unsigned char)l); + p = end-1; + break; + } + + case 'R': + switch(status) { + case PROMPT_READY: + if (!pset->db) + buf[0] = '!'; + else if (!GetVariableBool(pset->vars, "singleline")) + buf[0] = '='; + else + buf[0] = '^'; + break; + case PROMPT_CONTINUE: + buf[0] = '-'; + break; + case PROMPT_SINGLEQUOTE: + buf[0] = '\''; + break; + case PROMPT_DOUBLEQUOTE: + buf[0] = '"'; + break; + case PROMPT_COMMENT: + buf[0] = '*'; + break; + default: + buf[0] = '\0'; + break; + } + + case '?': + /* not here yet */ + break; + + case '#': + { + if (pset->db && strcmp(PQuser(pset->db), "postgres")==0) + buf[0] = '#'; + else + buf[0] = '>'; + + break; + } + + /* execute command */ + case '`': + { + FILE * fd = NULL; + char * file = strdup(p+1); + int cmdend; + cmdend = strcspn(file, "`"); + file[cmdend] = '\0'; + if (file) + fd = popen(file, "r"); + if (fd) { + fgets(buf, MAX_PROMPT_SIZE-1, fd); + pclose(fd); + } + if (buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + free(file); + p += cmdend+1; + break; + } + + /* interpolate variable */ + case '$': + { + char *name; + const char *val; + int nameend; + name = strdup(p+1); + nameend = strcspn(name, "$"); + name[nameend] = '\0'; + val = interpolate_var(name, pset); + if (val) + strncpy(buf, val, MAX_PROMPT_SIZE); + free(name); + p += nameend+1; + break; + } + + + default: + buf[0] = *p; + buf[1] = '\0'; + + } + esc = false; + } + else if (*p == '%') + esc = true; + else + { + buf[0] = *p; + buf[1] = '\0'; + esc = false; + } + + if (!esc) { + strncat(destination, buf, MAX_PROMPT_SIZE-strlen(destination)); + } + } + + destination[MAX_PROMPT_SIZE] = '\0'; + return destination; +} + |