On 9/9/07, Sibte Abbas <[EMAIL PROTECTED]> wrote:
> Attached is the patch for the TODO item mentioned at
> http://archives.postgresql.org/pgsql-hackers/2007-09/msg00352.php
>
> The command has the following synopsis:
>
> \#: displays the command history. Like \s but prefixes the lines with line
> numbers
>
> \# <line_no>: executes the command(if any) executed at the line specified by
> line_no
>
> regards,
> --
> Sibte Abbas
>
>
The attached patch adds the following new functionality:
\#e <lineno>: Will open the command at the given lineno in an editor.
\#e with no lineno will behave exactly like \e.
Example:
=====
psql> \#
199: create or replace function foo() returns integer as $$
begin
return 10;
end;
$$language 'plpgsql';
200: select version();
201: select * from foo();
\# 200
<select version() is executed>
psql> \#e 199
<the contents of lineno 199 are opened in the editor>
Definitely not for 8.3, however I hope that it can be queued for 8.4.
thanks,
--
Sibte Abbas
? psql_slash#.patch
? psql_slash#_v2.patch
? doc/src/sgml/ref/.psql-ref.sgml.swp
? src/cscope.out
? src/bin/psql/cscope.out
? src/pl/plperl/SPI.c
? src/pl/plperl/libplperl.so.0.0
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.194
diff -c -r1.194 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml 22 Aug 2007 04:45:20 -0000 1.194
--- doc/src/sgml/ref/psql-ref.sgml 14 Sep 2007 14:07:46 -0000
***************
*** 1923,1928 ****
--- 1922,1956 ----
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>\# [ <replaceable class="parameter">lineno</replaceable> ]</literal></term>
+ <listitem>
+ <para>
+ If <replaceable class="parameter">lineno</replaceable> is specified
+ then the query at the specified lineno from psql's command history is
+ executed. Otherwise it behaves like \s (with no commands) with the
+ difference being that it prefixes all lines with their respective
+ line numbers like <lineno>:<line>. This option is only available if
+ <application>psql</application> is configured to use the <acronym>GNU</acronym>
+ <application>Readline</application> library.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>\#e [ <replaceable class="parameter">lineno</replaceable> ]</literal></term>
+ <listitem>
+ <para>
+ If <replaceable class="parameter">lineno</replaceable> is specified
+ then the query at the specified lineno from the psql's command history is
+ opened in an editor. Otherwise whatever query is in the query buffer is
+ opened for edition; just like \e (with no commands). In each case, once
+ the editor is opened the following behaviour is similar to that of \e's.
+ This option is only available if <application>psql</application> is configured
+ to use the <acronym>GNU</acronym> <application>Readline</application> library.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><literal>\?</literal></term>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.181
diff -c -r1.181 command.c
*** src/bin/psql/command.c 21 Aug 2007 01:11:22 -0000 1.181
--- src/bin/psql/command.c 14 Sep 2007 14:07:47 -0000
***************
*** 55,61 ****
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
static bool do_connect(char *dbname, char *user, char *host, char *port);
static bool do_shell(const char *command);
!
/*----------
* HandleSlashCmds:
--- 55,64 ----
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
static bool do_connect(char *dbname, char *user, char *host, char *port);
static bool do_shell(const char *command);
! #ifdef USE_READLINE
! static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent);
! static int str_to_pint(const char *str);
! #endif
/*----------
* HandleSlashCmds:
***************
*** 435,441 ****
free(pattern);
}
-
/*
* \e or \edit -- edit the current query buffer (or a file and make it the
* query buffer
--- 438,443 ----
***************
*** 834,839 ****
--- 836,917 ----
free(fname);
}
+ #ifdef USE_READLINE
+ /* \# show history on screen with all lines prefixed with incrementing line numbers
+ * OR execute a history command at a specific line number
+ */
+ else if (strcmp(cmd, "#") == 0)
+ {
+ char *next = psql_scan_slash_option(scan_state,
+ OT_NORMAL, NULL, true);
+ if (next)
+ {
+ /* something follows after \#, hence consider it a \# <lineno> case */
+ HIST_ENTRY he;
+ memset(&he, 0, sizeof(he));
+ success = get_hist_entry(next, &he);
+
+ if (success)
+ {
+ resetPQExpBuffer(query_buf);
+ psql_scan_reset(scan_state);
+
+ appendPQExpBuffer(query_buf, he.line);
+ status = PSQL_CMD_SEND;
+ }
+ free(next);
+ }
+ else
+ {
+ /* only \#, simply display the history contents on the screen */
+ register HIST_ENTRY **the_list;
+ register int i;
+
+ the_list = history_list();
+ if (the_list)
+ {
+ for (i = 0; the_list[i]; i++)
+ printf ("%d: %s\n", i + history_base, the_list[i]->line);
+ }
+ success = true;
+ }
+ }
+
+ /* \#e <lineno> edit the specified history command */
+ else if (strcmp(cmd, "#e") == 0)
+ {
+ char *next = psql_scan_slash_option(scan_state,
+ OT_NORMAL, NULL, true);
+ success = false;
+ if (next)
+ {
+ /* something follows after \#e, hence consider it a \#e <lineno> case */
+ HIST_ENTRY he;
+ memset(&he, 0, sizeof(he));
+
+ if ((success = get_hist_entry(next, &he)))
+ {
+ resetPQExpBuffer(query_buf);
+ psql_scan_reset(scan_state);
+ appendPQExpBuffer(query_buf, he.line);
+ }
+ free(next);
+ }
+ else
+ {
+ /* only \#e -- just edit current contents of the query_buf */
+ if (!query_buf)
+ {
+ psql_error("no query buffer\n");
+ status = PSQL_CMD_ERROR;
+ }
+ success = true;
+ }
+ if (success)
+ status = do_edit(NULL, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR;
+ }
+ #endif
+
/* \set -- generalized set variable/option command */
else if (strcmp(cmd, "set") == 0)
{
***************
*** 1807,1809 ****
--- 1885,1949 ----
}
return true;
}
+
+ #ifdef USE_READLINE
+ /*
+ * get_hist_entry
+ *
+ * Returns the history entry corresponding to the line number specificed by 'lno_s' string.
+ * The returned value is copied in 'hist_ent'
+ */
+ static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent)
+ {
+ int lno_i = 0;
+ HIST_ENTRY *he;
+
+ psql_assert(lno_s);
+ psql_assert(hist_ent);
+
+ /* convert the line no string to integer form */
+ if ((lno_i = str_to_pint(lno_s)) == -1)
+ {
+ fprintf(stderr, _("%s is an invalid value for line number\n"), lno_s);
+ return false;
+ }
+
+ /* lookup the history corresponding to the line no */
+ if ((he = history_get(lno_i)) != NULL)
+ {
+ memcpy(hist_ent, he, sizeof(HIST_ENTRY));
+ return true;
+ }
+
+ /* else */
+ fprintf(stderr, _("Could'nt find any command at line number %d\n"), lno_i);
+ return false;
+ }
+
+ /*
+ * str_to_pint
+ *
+ * converts the given string into a positive int. Returns an error if "str"
+ * represents a negative integer.
+ *
+ * Returns, the converted value
+ * On Error, -1 is returned
+ */
+ static int str_to_pint(const char *str)
+ {
+ char *end = NULL;
+ int result = -1;
+ int save_errno = errno;
+ psql_assert(str);
+
+ errno = 0;
+ result = strtol(str, &end, 10);
+
+ if ((errno == ERANGE) || (strlen(end) != 0) || (result < 0))
+ result = -1;
+
+ errno = save_errno;
+ return result;
+ }
+ #endif
+
Index: src/bin/psql/help.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.118
diff -c -r1.118 help.c
*** src/bin/psql/help.c 21 Aug 2007 01:11:22 -0000 1.118
--- src/bin/psql/help.c 14 Sep 2007 14:07:48 -0000
***************
*** 196,201 ****
--- 196,203 ----
fprintf(output, _(" \\r reset (clear) the query buffer\n"));
#ifdef USE_READLINE
fprintf(output, _(" \\s [FILE] display history or save it to file\n"));
+ fprintf(output, _(" \\# [LINENO] display history in lineno:<command> format or execute a line from that history\n"));
+ fprintf(output, _(" \\#e [LINENO] edit the query buffer or the history command at LINENO, with external editor\n"));
#endif
fprintf(output, _(" \\w FILE write query buffer to file\n"));
fprintf(output, "\n");
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.167
diff -c -r1.167 tab-complete.c
*** src/bin/psql/tab-complete.c 14 Sep 2007 04:25:24 -0000 1.167
--- src/bin/psql/tab-complete.c 14 Sep 2007 14:07:49 -0000
***************
*** 570,576 ****
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
"\\set", "\\t", "\\T",
! "\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
};
(void) end; /* not used */
--- 570,576 ----
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
"\\set", "\\t", "\\T",
! "\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", "\\#", "\\#e", NULL
};
(void) end; /* not used */
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?
http://archives.postgresql.org