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

Reply via email to