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