Re: Uppercase tab completion keywords in psql?

Bruce Momjian <bruce@momjian.us>

From: Bruce Momjian <bruce@momjian.us>
To: Peter Eisentraut <peter_e@gmx.net>
Cc: David Fetter <david@fetter.org>, Andrew Dunstan <andrew@dunslane.net>, PostgreSQL-development <pgsql-hackers@postgreSQL.org>
Date: 2012-05-03T19:47:48Z
Lists: pgsql-hackers

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. psql: Add variable to control keyword case in tab completion

  2. psql: Case preserving completion of SQL key words

Peter, where are we on this?

---------------------------------------------------------------------------

On Fri, Mar 30, 2012 at 08:16:59PM +0300, Peter Eisentraut wrote:
> On fre, 2012-03-23 at 07:52 -0700, David Fetter wrote:
> > On Thu, Mar 22, 2012 at 06:05:30PM -0400, Andrew Dunstan wrote:
> > > On 03/22/2012 05:49 PM, Bruce Momjian wrote:
> > > >Robert Haas and I are disappointed by this change.  I liked the
> > > >fact that I could post nice-looking SQL queries without having to
> > > >use my capslock key (which I use as a second control key).  Any
> > > >chance of reverting this change?
> > > >
> > > 
> > > Should it be governed by a setting?
> > 
> > Something like (upper|lower|preserve) ?
> 
> How about this patch then?  (There are actually four possible settings,
> see patch.)
> 

> diff --git i/doc/src/sgml/ref/psql-ref.sgml w/doc/src/sgml/ref/psql-ref.sgml
> index b849101..be9d37d 100644
> --- i/doc/src/sgml/ref/psql-ref.sgml
> +++ w/doc/src/sgml/ref/psql-ref.sgml
> @@ -2652,6 +2652,22 @@ bar
>        </varlistentry>
>  
>        <varlistentry>
> +        <term><varname>COMP_KEYWORD_CASE</varname></term>
> +        <listitem>
> +        <para>
> +        Determines which letter case to use when completing an SQL key word.
> +        If set to <literal>lower</literal> or <literal>upper</literal>, the
> +        completed word will be in lower or upper case, respectively.  If set
> +        to <literal>preserve-lower</literal>
> +        or <literal>preserve-upper</literal> (the default), the completed word
> +        will be in the case of the word already entered, but words being
> +        completed without anything entered will be in lower or upper case,
> +        respectively.
> +        </para>
> +        </listitem>
> +      </varlistentry>
> +
> +      <varlistentry>
>          <term><varname>DBNAME</varname></term>
>          <listitem>
>          <para>
> diff --git i/src/bin/psql/tab-complete.c w/src/bin/psql/tab-complete.c
> index 6f481bb..00d87d5 100644
> --- i/src/bin/psql/tab-complete.c
> +++ w/src/bin/psql/tab-complete.c
> @@ -682,7 +682,7 @@ static char **complete_from_variables(char *text,
>  						const char *prefix, const char *suffix);
>  static char *complete_from_files(const char *text, int state);
>  
> -static char *pg_strdup_same_case(const char *s, const char *ref);
> +static char *pg_strdup_keyword_case(const char *s, const char *ref);
>  static PGresult *exec_query(const char *query);
>  
>  static void get_previous_words(int point, char **previous_words, int nwords);
> @@ -3048,7 +3048,7 @@ create_or_drop_command_generator(const char *text, int state, bits32 excluded)
>  	{
>  		if ((pg_strncasecmp(name, text, string_length) == 0) &&
>  			!(words_after_create[list_index - 1].flags & excluded))
> -			return pg_strdup_same_case(name, text);
> +			return pg_strdup_keyword_case(name, text);
>  	}
>  	/* if nothing matches, return NULL */
>  	return NULL;
> @@ -3335,9 +3335,9 @@ complete_from_list(const char *text, int state)
>  			if (completion_case_sensitive)
>  				return pg_strdup(item);
>  			else
> -				/* If case insensitive matching was requested initially, return
> -				 * it in the case of what was already entered. */
> -				return pg_strdup_same_case(item, text);
> +				/* If case insensitive matching was requested initially, adjust
> +				 * the case according to setting. */
> +				return pg_strdup_keyword_case(item, text);
>  		}
>  	}
>  
> @@ -3374,9 +3374,9 @@ complete_from_const(const char *text, int state)
>  		if (completion_case_sensitive)
>  			return pg_strdup(completion_charp);
>  		else
> -			/* If case insensitive matching was requested initially, return it
> -			 * in the case of what was already entered. */
> -			return pg_strdup_same_case(completion_charp, text);
> +			/* If case insensitive matching was requested initially, adjust the
> +			 * case according to setting. */
> +			return pg_strdup_keyword_case(completion_charp, text);
>  	}
>  	else
>  		return NULL;
> @@ -3484,27 +3484,48 @@ complete_from_files(const char *text, int state)
>  
>  
>  /*
> - * Make a pg_strdup copy of s and convert it to the same case as ref.
> + * Make a pg_strdup copy of s and convert the case according to
> + * COMP_KEYWORD_CASE variable, using ref as the text that was already entered.
>   */
>  static char *
> -pg_strdup_same_case(const char *s, const char *ref)
> +pg_strdup_keyword_case(const char *s, const char *ref)
>  {
>  	char *ret, *p;
>  	unsigned char first = ref[0];
> +	int		tocase;
> +	const char *varval;
> +
> +	varval = GetVariable(pset.vars, "COMP_KEYWORD_CASE");
> +	if (!varval)
> +		tocase = 0;
> +	else if (strcmp(varval, "lower") == 0)
> +		tocase = -2;
> +	else if (strcmp(varval, "preserve-lower") == 0)
> +		tocase = -1;
> +	else if (strcmp(varval, "preserve-upper") == 0)
> +		tocase = +1;
> +	else if (strcmp(varval, "upper") == 0)
> +		tocase = +2;
> +	else
> +		tocase = 0;
>  
> -	if (isalpha(first))
> -	{
> -		ret = pg_strdup(s);
> -		if (islower(first))
> -			for (p = ret; *p; p++)
> -				*p = pg_tolower((unsigned char) *p);
> -		else
> -			for (p = ret; *p; p++)
> -				*p = pg_toupper((unsigned char) *p);
> -		return ret;
> -	}
> +	/* default */
> +	if (tocase == 0)
> +		tocase = +1;
> +
> +	ret = pg_strdup(s);
> +
> +	if (tocase == -2
> +		|| ((tocase == -1 || tocase == +1) && islower(first))
> +		|| (tocase == -1 && !isalpha(first))
> +		)
> +		for (p = ret; *p; p++)
> +			*p = pg_tolower((unsigned char) *p);
>  	else
> -		return pg_strdup(s);
> +		for (p = ret; *p; p++)
> +			*p = pg_toupper((unsigned char) *p);
> +
> +	return ret;
>  }
>  
>  


-- 
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + It's impossible for everything to be true. +