On Thu, Apr 3, 2008 at 7:54 PM, Sibte Abbas <[EMAIL PROTECTED]> wrote:
> On Sun, Mar 30, 2008 at 3:09 PM, Tom Lane <[EMAIL PROTECTED]> > wrote:<http://archives.postgresql.org/pgsql-hackers/2006-12/msg00255.php> > > > > I wonder whether it wouldn't be safer and more convenient if we defined > > '\# n' as pulling command n into the edit buffer, rather than > > immediately executing it. Actual execution is only a <return> away, > > but this definition would allow you to edit the command a bit more > > before you execute it --- including \e to use an editor. It also > > closes the loop in terms of providing some confidence that you typed > > the number you should have typed. > > > > This makes more sense and also appears to be much safer. I will start > modifying the patch as per this approach now. > > Based on your feedback I have modified the attached patch as follows: 1) \# n opens command n into the edit buffer. 2) A new psql variable; SHOW_LINE_NO is added, which is consulted by the \s command. If it is set, \s prefixs each line of its output with an incrementing line number. regards, -- Sibte Abbas
? GNUmakefile ? config.log ? config.status ? mydiff.diff ? pgsql.log ? psql_slash#_v2.patch ? psql_slash#_v3.patch ? src/Makefile.global ? src/cscope.out ? src/backend/postgres ? src/backend/access/objfiles.txt ? src/backend/access/common/objfiles.txt ? src/backend/access/gin/objfiles.txt ? src/backend/access/gist/objfiles.txt ? src/backend/access/hash/objfiles.txt ? src/backend/access/heap/objfiles.txt ? src/backend/access/index/objfiles.txt ? src/backend/access/nbtree/objfiles.txt ? src/backend/access/transam/objfiles.txt ? src/backend/bootstrap/objfiles.txt ? src/backend/catalog/objfiles.txt ? src/backend/catalog/postgres.bki ? src/backend/catalog/postgres.description ? src/backend/catalog/postgres.shdescription ? src/backend/commands/objfiles.txt ? src/backend/executor/objfiles.txt ? src/backend/lib/objfiles.txt ? src/backend/libpq/objfiles.txt ? src/backend/main/objfiles.txt ? src/backend/nodes/objfiles.txt ? src/backend/optimizer/objfiles.txt ? src/backend/optimizer/geqo/objfiles.txt ? src/backend/optimizer/path/objfiles.txt ? src/backend/optimizer/plan/objfiles.txt ? src/backend/optimizer/prep/objfiles.txt ? src/backend/optimizer/util/objfiles.txt ? src/backend/parser/objfiles.txt ? src/backend/port/objfiles.txt ? src/backend/postmaster/objfiles.txt ? src/backend/regex/objfiles.txt ? src/backend/rewrite/objfiles.txt ? src/backend/snowball/libdict_snowball.so.0.0 ? src/backend/snowball/snowball_create.sql ? src/backend/storage/objfiles.txt ? src/backend/storage/buffer/objfiles.txt ? src/backend/storage/file/objfiles.txt ? src/backend/storage/freespace/objfiles.txt ? src/backend/storage/ipc/objfiles.txt ? src/backend/storage/large_object/objfiles.txt ? src/backend/storage/lmgr/objfiles.txt ? src/backend/storage/page/objfiles.txt ? src/backend/storage/smgr/objfiles.txt ? src/backend/tcop/objfiles.txt ? src/backend/tsearch/objfiles.txt ? src/backend/utils/objfiles.txt ? src/backend/utils/probes.h ? src/backend/utils/adt/objfiles.txt ? src/backend/utils/cache/objfiles.txt ? src/backend/utils/error/objfiles.txt ? src/backend/utils/fmgr/objfiles.txt ? src/backend/utils/hash/objfiles.txt ? src/backend/utils/init/objfiles.txt ? src/backend/utils/mb/objfiles.txt ? src/backend/utils/mb/conversion_procs/conversion_create.sql ? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_jis_2004_and_shift_jis_2004/libeuc_jis_2004_and_shift_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0 ? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0 ? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jis_2004/libutf8_and_euc_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_shift_jis_2004/libutf8_and_shift_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_win/libutf8_and_win.so.0.0 ? src/backend/utils/misc/objfiles.txt ? src/backend/utils/mmgr/objfiles.txt ? src/backend/utils/resowner/objfiles.txt ? src/backend/utils/sort/objfiles.txt ? src/backend/utils/time/objfiles.txt ? src/bin/initdb/initdb ? src/bin/pg_config/pg_config ? src/bin/pg_controldata/pg_controldata ? src/bin/pg_ctl/pg_ctl ? src/bin/pg_dump/pg_dump ? src/bin/pg_dump/pg_dumpall ? src/bin/pg_dump/pg_restore ? src/bin/pg_resetxlog/pg_resetxlog ? src/bin/psql/how ? src/bin/psql/psql ? src/bin/scripts/clusterdb ? src/bin/scripts/createdb ? src/bin/scripts/createlang ? src/bin/scripts/createuser ? src/bin/scripts/dropdb ? src/bin/scripts/droplang ? src/bin/scripts/dropuser ? src/bin/scripts/reindexdb ? src/bin/scripts/vacuumdb ? src/include/pg_config.h ? src/include/stamp-h ? src/interfaces/ecpg/compatlib/exports.list ? src/interfaces/ecpg/compatlib/libecpg_compat.so.3.1 ? src/interfaces/ecpg/ecpglib/exports.list ? src/interfaces/ecpg/ecpglib/libecpg.so.6.1 ? src/interfaces/ecpg/include/ecpg_config.h ? src/interfaces/ecpg/pgtypeslib/exports.list ? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.3.1 ? src/interfaces/ecpg/preproc/ecpg ? src/interfaces/libpq/exports.list ? src/interfaces/libpq/libpq.so.5.2 ? src/pl/plpgsql/src/libplpgsql.so.1.0 ? src/port/pg_config_paths.h ? src/test/regress/libregress.so.0.0 ? src/test/regress/pg_regress ? src/test/regress/testtablespace ? src/timezone/objfiles.txt ? src/timezone/zic Index: doc/src/sgml/ref/psql-ref.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v retrieving revision 1.199 diff -c -r1.199 psql-ref.sgml *** doc/src/sgml/ref/psql-ref.sgml 30 Mar 2008 18:10:20 -0000 1.199 --- doc/src/sgml/ref/psql-ref.sgml 10 Apr 2008 23:55:29 -0000 *************** *** 1768,1777 **** <para> Print or save the command line history to <replaceable class="parameter">filename</replaceable>. If <replaceable ! class="parameter">filename</replaceable> is omitted, the history ! is written to the standard output. This option is only available ! if <application>psql</application> is configured to use the ! <acronym>GNU</acronym> <application>Readline</application> library. </para> </listitem> </varlistentry> --- 1768,1781 ---- <para> Print or save the command line history to <replaceable class="parameter">filename</replaceable>. If <replaceable ! class="parameter">filename</replaceable> is omitted, the ! history is written to the standard output. In which case ! the output format is determined on the basis of the value ! of <varname>SHOW_LINE_NO</varname>. If it is set, then ! the output is prefixed with line numbers. This option is ! only available if <application>psql</application> is configured ! to use the <acronym>GNU</acronym> <application>Readline</application> ! library. </para> </listitem> </varlistentry> *************** *** 1909,1914 **** --- 1913,1929 ---- </listitem> </varlistentry> + <varlistentry> + <term><literal>\# [ <replaceable class="parameter">lineno</replaceable> ]</literal></term> + <listitem> + <para> + Opens the query at <replaceable class="parameter">lineno</replaceable> from + the psql's command history in an editor. 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> *************** *** 2373,2378 **** --- 2388,2403 ---- </varlistentry> <varlistentry> + <term><varname>SHOW_LINE_NO</varname></term> + <listitem> + <para> + When set, \s(while printing to standard output) will prefix + each line of its output with a line number. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><varname>SINGLELINE</varname></term> <listitem> <para> Index: src/bin/psql/command.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v retrieving revision 1.186 diff -c -r1.186 command.c *** src/bin/psql/command.c 1 Jan 2008 19:45:55 -0000 1.186 --- src/bin/psql/command.c 10 Apr 2008 23:55:31 -0000 *************** *** 54,60 **** 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: --- 54,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); ! static bool display_history(void); ! #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 --- 439,444 ---- *************** *** 826,840 **** OT_NORMAL, NULL, true); expand_tilde(&fname); ! /* This scrolls off the screen when using /dev/tty */ ! success = saveHistory(fname ? fname : DEVTTY, false); ! if (success && !pset.quiet && fname) ! printf(gettext("Wrote history to file \"%s/%s\".\n"), ! pset.dirname ? pset.dirname : ".", fname); ! if (!fname) ! putchar('\n'); ! free(fname); } /* \set -- generalized set variable/option command */ else if (strcmp(cmd, "set") == 0) --- 829,878 ---- OT_NORMAL, NULL, true); expand_tilde(&fname); ! if (fname) ! { ! /* its a \s <filename>, so save history contents in fname */ ! success = saveHistory(fname, false); ! if (success && !pset.quiet) ! printf(gettext("Wrote history to file \"%s/%s\".\n"), ! pset.dirname ? pset.dirname : ".", fname); ! free(fname); ! } ! else /* only \s -- just print the history contents to STDOUT */ ! success = display_history(); ! } ! ! #ifdef USE_READLINE ! /* \# <lineno> edit the specified history command */ ! 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 = do_edit(NULL, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR; ! } ! free(next); ! } ! else ! { ! /* only \# is an error */ ! psql_error("\\%s: missing required argument\n", cmd); ! success = false; ! } } + #endif /* \set -- generalized set variable/option command */ else if (strcmp(cmd, "set") == 0) *************** *** 1810,1812 **** --- 1848,1938 ---- } return true; } + + static bool display_history(void) + { + #ifdef USE_READLINE + /* only \s, simply display the history contents on the screen */ + register HIST_ENTRY **the_list; + register int i; + + the_list = history_list(); + if (the_list) + { + if (pset.show_line_no) + { + for (i = 0; the_list[i]; i++) + printf ("%d: %s\n", i + history_base, the_list[i]->line); + } + else + { + for (i = 0; the_list[i]; i++) + printf ("%s\n", the_list[i]->line); + } + } + return true; + #endif + psql_error("history is not supported by this installation\n"); + return false; + } + + #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.126 diff -c -r1.126 help.c *** src/bin/psql/help.c 4 Apr 2008 18:00:25 -0000 1.126 --- src/bin/psql/help.c 10 Apr 2008 23:55:31 -0000 *************** *** 197,202 **** --- 197,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] edit 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/settings.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/psql/settings.h,v retrieving revision 1.33 diff -c -r1.33 settings.h *** src/bin/psql/settings.h 1 Jan 2008 19:45:56 -0000 1.33 --- src/bin/psql/settings.h 10 Apr 2008 23:55:31 -0000 *************** *** 96,101 **** --- 96,102 ---- bool quiet; bool singleline; bool singlestep; + bool show_line_no; int fetch_count; PSQL_ECHO echo; PSQL_ECHO_HIDDEN echo_hidden; Index: src/bin/psql/startup.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/psql/startup.c,v retrieving revision 1.146 diff -c -r1.146 startup.c *** src/bin/psql/startup.c 1 Jan 2008 19:45:56 -0000 1.146 --- src/bin/psql/startup.c 10 Apr 2008 23:55:31 -0000 *************** *** 868,873 **** --- 868,879 ---- PQsetErrorVerbosity(pset.db, pset.verbosity); } + static void + show_line_no_hook(const char *newval) + { + pset.show_line_no = ParseVariableBool(newval); + } + static void EstablishVariableSpace(void) *************** *** 888,891 **** --- 894,898 ---- SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook); SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook); SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook); + SetVariableAssignHook(pset.vars, "SHOW_LINE_NO", show_line_no_hook); } Index: src/bin/psql/tab-complete.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v retrieving revision 1.170 diff -c -r1.170 tab-complete.c *** src/bin/psql/tab-complete.c 29 Mar 2008 19:19:14 -0000 1.170 --- src/bin/psql/tab-complete.c 10 Apr 2008 23:55:32 -0000 *************** *** 628,634 **** "\\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 */ --- 628,634 ---- "\\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 */
-- Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-patches