summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian2006-02-11 21:55:35 +0000
committerBruce Momjian2006-02-11 21:55:35 +0000
commitce494f35629ffa46dee7d0fa30ddff8bbb24b10d (patch)
tree863663c9a13cf11daee08178fd60a7dc9d177a24
parent896f862a86e8243f55e89a512200e5718ef44f89 (diff)
o Improve psql's handling of multi-line statements
Currently, while \e saves a single statement as one entry, interactive statements are saved one line at a time. Ideally all statements would be saved like \e does. Sergey E. Koposov
-rw-r--r--src/bin/psql/help.c1
-rw-r--r--src/bin/psql/input.c92
-rw-r--r--src/bin/psql/input.h5
-rw-r--r--src/bin/psql/mainloop.c35
-rw-r--r--src/bin/psql/prompt.c1
-rw-r--r--src/bin/psql/tab-complete.c2
6 files changed, 119 insertions, 17 deletions
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 91b1b57d22..1b371fedf1 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -7,6 +7,7 @@
*/
#include "postgres_fe.h"
#include "common.h"
+#include "pqexpbuffer.h"
#include "input.h"
#include "print.h"
#include "help.h"
diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c
index 8694b9cc72..d34ef71eed 100644
--- a/src/bin/psql/input.c
+++ b/src/bin/psql/input.c
@@ -7,8 +7,8 @@
*/
#include "postgres_fe.h"
-#include "input.h"
#include "pqexpbuffer.h"
+#include "input.h"
#include "settings.h"
#include "tab-complete.h"
#include "common.h"
@@ -90,18 +90,55 @@ gets_interactive(const char *prompt)
#ifdef USE_READLINE
char *s;
- static char *prev_hist = NULL;
-
if (useReadline)
/* On some platforms, readline is declared as readline(char *) */
s = readline((char *) prompt);
else
s = gets_basic(prompt);
- if (useHistory && s && s[0])
+ return s;
+#else
+ return gets_basic(prompt);
+#endif
+}
+
+
+/* Put the line in the history buffer and also add the trailing \n */
+void pgadd_history(char *s, PQExpBuffer history_buf)
+{
+#ifdef USE_READLINE
+
+ int slen;
+ if (useReadline && useHistory && s && s[0])
{
- enum histcontrol HC;
+ slen = strlen(s);
+ if (s[slen-1] == '\n')
+ appendPQExpBufferStr(history_buf, s);
+ else
+ {
+ appendPQExpBufferStr(history_buf, s);
+ appendPQExpBufferChar(history_buf, '\n');
+ }
+ }
+#endif
+}
+
+/* Feed the contents of the history buffer to readline */
+void pgflush_history(PQExpBuffer history_buf)
+{
+#ifdef USE_READLINE
+ char *s;
+ static char *prev_hist;
+ int slen, i;
+
+ if (useReadline && useHistory )
+ {
+ enum histcontrol HC;
+
+ s = history_buf->data;
+ prev_hist = NULL;
+
HC = GetHistControlConfig();
if (((HC & hctl_ignorespace) && s[0] == ' ') ||
@@ -112,17 +149,27 @@ gets_interactive(const char *prompt)
else
{
free(prev_hist);
+ slen = strlen(s);
+ /* Trim the trailing \n's */
+ for (i = slen-1; i >= 0 && s[i] == '\n'; i--)
+ ;
+ s[i + 1] = '\0';
prev_hist = pg_strdup(s);
add_history(s);
}
+
+ resetPQExpBuffer(history_buf);
}
-
- return s;
-#else
- return gets_basic(prompt);
#endif
}
+void pgclear_history(PQExpBuffer history_buf)
+{
+#ifdef USE_READLINE
+ if (useReadline && useHistory)
+ resetPQExpBuffer(history_buf);
+#endif
+}
/*
@@ -157,6 +204,30 @@ gets_fromFile(FILE *source)
}
+static void encode_history()
+{
+ HIST_ENTRY *cur_hist;
+ char *cur_ptr;
+
+ for (history_set_pos(0), cur_hist = current_history();
+ cur_hist; cur_hist = next_history())
+ for (cur_ptr = cur_hist->line; *cur_ptr; cur_ptr++)
+ if (*cur_ptr == '\n')
+ *cur_ptr = '\0';
+}
+
+static void decode_history()
+{
+ HIST_ENTRY *cur_hist;
+ char *cur_ptr;
+
+ for (history_set_pos(0), cur_hist = current_history();
+ cur_hist; cur_hist = next_history())
+ for (cur_ptr = cur_hist->line; *cur_ptr; cur_ptr++)
+ if (*cur_ptr == '\0')
+ *cur_ptr = '\n';
+}
+
/*
* Put any startup stuff related to input in here. It's good to maintain
@@ -197,6 +268,8 @@ initializeInput(int flags)
if (psql_history)
read_history(psql_history);
+
+ decode_history();
}
#endif
@@ -215,6 +288,7 @@ saveHistory(char *fname)
#ifdef USE_READLINE
if (useHistory && fname)
{
+ encode_history();
if (write_history(fname) == 0)
return true;
diff --git a/src/bin/psql/input.h b/src/bin/psql/input.h
index dee88b6d9a..dea4c8247b 100644
--- a/src/bin/psql/input.h
+++ b/src/bin/psql/input.h
@@ -39,4 +39,9 @@ char *gets_fromFile(FILE *source);
void initializeInput(int flags);
bool saveHistory(char *fname);
+void pgadd_history(char *s, PQExpBuffer history_buf);
+void pgclear_history(PQExpBuffer history_buf);
+void pgflush_history(PQExpBuffer history_buf);
+
+
#endif /* INPUT_H */
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index 463ec39789..c9af4c90fb 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -37,6 +37,7 @@ MainLoop(FILE *source)
PQExpBuffer query_buf; /* buffer for query being accumulated */
PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
* yet, use this one for \e, etc. */
+ PQExpBuffer history_buf;
char *line; /* current line of input */
int added_nl_pos;
bool success;
@@ -66,7 +67,9 @@ MainLoop(FILE *source)
query_buf = createPQExpBuffer();
previous_buf = createPQExpBuffer();
- if (!query_buf || !previous_buf)
+ history_buf = createPQExpBuffer();
+
+ if (!query_buf || !previous_buf || !history_buf)
{
psql_error("out of memory\n");
exit(EXIT_FAILURE);
@@ -90,7 +93,7 @@ MainLoop(FILE *source)
successResult = EXIT_USER;
break;
}
-
+ pgclear_history(history_buf);
cancel_pressed = false;
}
@@ -106,6 +109,8 @@ MainLoop(FILE *source)
count_eof = 0;
slashCmdStatus = PSQL_CMD_UNKNOWN;
prompt_status = PROMPT_READY;
+ if (pset.cur_cmd_interactive)
+ pgclear_history(history_buf);
if (pset.cur_cmd_interactive)
putc('\n', stdout);
@@ -138,11 +143,15 @@ MainLoop(FILE *source)
psql_scan_reset(scan_state);
slashCmdStatus = PSQL_CMD_UNKNOWN;
prompt_status = PROMPT_READY;
+
+ if (pset.cur_cmd_interactive)
+ /*
+ * Pass all the contents of history_buf to readline
+ * and free the history buffer.
+ */
+ pgflush_history(history_buf);
}
-
- /*
- * otherwise, get another line
- */
+ /* otherwise, get another line */
else if (pset.cur_cmd_interactive)
{
/* May need to reset prompt, eg after \r command */
@@ -212,7 +221,11 @@ MainLoop(FILE *source)
*/
psql_scan_setup(scan_state, line, strlen(line));
success = true;
-
+
+ if (pset.cur_cmd_interactive)
+ /* Put current line in the history buffer */
+ pgadd_history(line, history_buf);
+
while (success || !die_on_error)
{
PsqlScanResult scan_result;
@@ -287,6 +300,13 @@ MainLoop(FILE *source)
scan_result == PSCAN_EOL)
break;
}
+
+ if (pset.cur_cmd_interactive && prompt_status != PROMPT_CONTINUE)
+ /*
+ * Pass all the contents of history_buf to readline
+ * and free the history buffer.
+ */
+ pgflush_history(history_buf);
psql_scan_finish(scan_state);
free(line);
@@ -333,6 +353,7 @@ MainLoop(FILE *source)
destroyPQExpBuffer(query_buf);
destroyPQExpBuffer(previous_buf);
+ destroyPQExpBuffer(history_buf);
psql_scan_destroy(scan_state);
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index 66e74644b5..cdc791fc2c 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -12,6 +12,7 @@
#include "settings.h"
#include "common.h"
+#include "pqexpbuffer.h"
#include "input.h"
#include "variables.h"
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index ba119cc571..f5cab0c348 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -43,6 +43,7 @@
#include "postgres_fe.h"
#include "tab-complete.h"
+#include "pqexpbuffer.h"
#include "input.h"
/* If we don't have this, we might as well forget about the whole thing: */
@@ -50,7 +51,6 @@
#include <ctype.h>
#include "libpq-fe.h"
-#include "pqexpbuffer.h"
#include "common.h"
#include "settings.h"