Subject: Re: Fix to readline for case-insensitive file-name completion
From: [email-masked] (Curtis Galloway)

21 May 1997 20:58:33 -0700
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
References: <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: Mozilla 4.0b4 [en] (WinNT; I)
Original-To: "[email-masked]" <[email-masked]>
X-Priority: 3 (Normal)
Original-Sender: [email-masked]

You can argue this several ways, but my opinion is that the function of
the shell should follow the function of the OS.  On UNIX, I want my
shell to be case-sensitive; on Win32, I want it to be case-insensitive. 
But I can see why you would want the filename completion to pay
attention to case.  I think it's even possible to have a case-sensitive
filesystem on a Win32 machine with an NFS client.

Here are diffs to do case-insensitive globbing and filename completion. 
They are set to be case-insensitive by default on Win32, but can be
turned off by unsetting the special variables "glob_case_fold" and
"completion_case_fold".

--Curtis Galloway

*** subst.c.00	Tue May 20 16:25:54 1997
--- subst.c	Wed May 21 07:28:22 1997
***************
*** 74,79 ****
--- 74,83 ----
  extern int no_line_editing;
  extern int hostname_list_initialized;
  #endif
+ #if defined(__GO32__) || defined(__CYGWIN32__)
+ extern int glob_case_fold;
+ extern int completion_case_fold;
+ #endif
  
  #if !defined (USE_POSIX_GLOB_LIBRARY)
  extern int glob_dot_filenames, noglob_dot_filenames;
***************
*** 4477,4482 ****
--- 4481,4491 ----
    sv_glob_dot_filenames (), sv_nolinks (),
    sv_noclobber (), sv_allow_null_glob_expansion (), sv_strict_posix
();
  
+ #if defined(__GO32__) || defined(__CYGWIN32__)
+ void sv_glob_case_fold ();
+ void sv_completion_case_fold ();
+ #endif
+ 
  #if defined (READLINE)
  void sv_terminal (), sv_hostname_completion_file ();
  #endif
***************
*** 4549,4554 ****
--- 4558,4567 ----
    { "allow_null_glob_expansion", sv_allow_null_glob_expansion },
    { "noclobber", sv_noclobber },
    { "nolinks", sv_nolinks },
+ #if defined(__GO32__) || defined(__CYGWIN32__)
+   { "glob_case_fold", sv_glob_case_fold },
+   { "completion_case_fold", sv_completion_case_fold },
+ #endif /* __GO32__ || __CYGWIN32__ */
    { (char *)0x00, (VFunction *)0x00 }
  };
  
***************
*** 4865,4867 ****
--- 4878,4896 ----
    posix_readline_initialize (posixly_correct);
  #endif /* READLINE */
  }
+ 
+ #if defined(__GO32__) || defined(__CYGWIN32__)
+ void
+ sv_glob_case_fold (name)
+     char *name;
+ {
+   SET_INT_VAR (name, glob_case_fold);
+ }
+ 
+ void
+ sv_completion_case_fold (name)
+     char *name;
+ {
+   SET_INT_VAR (name, completion_case_fold);
+ }
+ #endif /* __GO32__ || __CYGWIN32__ */

*** variables.c.00	Wed May 21 07:17:27 1997
--- variables.c	Wed May 21 07:28:42 1997
***************
*** 44,49 ****
--- 44,53 ----
  extern char *primary_prompt, *secondary_prompt;
  extern Function *this_shell_builtin;
  extern time_t shell_start_time;
+ #if defined(__GO32__) || defined(__CYGWIN32__)
+ extern int glob_case_fold;
+ extern int completion_case_fold;
+ #endif
  
  /* The list of shell variables that the user has created, or that came
from
     the environment. */
***************
*** 249,254 ****
--- 253,263 ----
    bind_variable ("OPTIND", "1");
    bind_variable ("OPTERR", "1");
  #endif /* GETOPTS_BUILTIN */
+ 
+ #if defined(__GO32__) || defined(__CYGWIN32__)
+   bind_variable ("glob_case_fold", itos(glob_case_fold));
+   bind_variable ("completion_case_fold", itos(completion_case_fold));
+ #endif
  
    /* Get the full pathname to THIS shell, and set the BASH variable
       to it. */

*** lib/glob/fnmatch.c.00	Fri May 09 15:10:00 1997
--- lib/glob/fnmatch.c	Wed May 21 07:26:41 1997
***************
*** 25,30 ****
--- 25,36 ----
  #  endif /* !errno */
  #endif
  
+ #if defined(__GO32__) || defined (__CYGWIN32__)
+ int glob_case_fold = 1;
+ #else
+ int glob_case_fold = 0;
+ #endif
+ 
  /* Match STRING against the filename pattern PATTERN, returning zero
if
     it matches, FNM_NOMATCH if not.  */
  int
***************
*** 59,66 ****
  	case '\\':
  	  if (!(flags & FNM_NOESCAPE))
  	    c = *p++;
! 	  if (*n != c)
! 	    return (FNM_NOMATCH);
  	  break;
  
  	case '*':
--- 65,77 ----
  	case '\\':
  	  if (!(flags & FNM_NOESCAPE))
  	    c = *p++;
! 	  if (glob_case_fold) {
! 	    if (tolower(c) != tolower(*n))
! 	      return (FNM_NOMATCH);
! 	  } else {
! 	    if (c != *n)
! 	      return (FNM_NOMATCH);
! 	  }
  	  break;
  
  	case '*':
***************
*** 175,182 ****
  	  break;
  
  	default:
! 	  if (c != *n)
! 	    return (FNM_NOMATCH);
  	}
  
        ++n;
--- 186,198 ----
  	  break;
  
  	default:
! 	  if (glob_case_fold) {
! 	    if (tolower(c) != tolower(*n))
! 	      return (FNM_NOMATCH);
! 	  } else {
! 	    if (c != *n)
! 	      return (FNM_NOMATCH);
! 	  }
  	}
  
        ++n;

*** lib/readline/complete.c.00	Fri May 09 15:10:10 1997
--- lib/readline/complete.c	Tue May 20 08:49:58 1997
***************
*** 1077,1083 ****
--- 1077,1087 ----
  /* **************************************************************** */
  
  /* Non-zero means that case is not significant in completion. */
+ #if defined (__GO32__) || defined (__CYGWIN32__)
+ int completion_case_fold = 1;
+ #else
  int completion_case_fold = 0;
+ #endif
  
  /* Return an array of (char *) which is a list of completions for
TEXT.
     If there are no completions, return a NULL pointer.
***************
*** 1265,1274 ****
--- 1269,1285 ----
  	{
  	  /* Otherwise, if these match up to the length of filename, then
  	     it is a match. */
+       if (completion_case_fold) {
+ 	    if ((tolower(entry->d_name[0]) == tolower(filename[0])) &&
+ 		(((int)D_NAMLEN (entry)) >= filename_len) &&
+ 		(strncasecmp (filename, entry->d_name, filename_len) == 0))
+ 	      break;
+       } else {
  	    if ((entry->d_name[0] == filename[0]) &&
  		(((int)D_NAMLEN (entry)) >= filename_len) &&
  		(strncmp (filename, entry->d_name, filename_len) == 0))
  	      break;
+       }
  	}
      }
-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".