Here's a proposed patch for Bash (or readline) which implements a
usability feature.  This feature reduces the amount of text output
when filename completion shows a list of files after pressing TAB
twice (or once if you configure it so), showing as first letter
what you have to type to disambiguate the completion. Here's an
output example:

  [0:[EMAIL PROTECTED]:0] [~/project/bash-3.1-ellipsis]$ ./bash
  [EMAIL PROTECTED]:~/project/bash-3.1-ellipsis$ ls ar<hit tab>
  ___.c         ...func.c     ...func.h     ...func.o     ___.h         ___.o
  [EMAIL PROTECTED]:~/project/bash-3.1-ellipsis$ ls array

As you can see, instead of showing the full name, an ellipsis
replaces the common prefix in the list.  This is more helpful the
longer the names get:

  [EMAIL PROTECTED]:~/project/bash-3.1-ellipsis$ ls ~/all<hit tab>
  ...df       ...s.gz
  [EMAIL PROTECTED]:~/project/bash-3.1-ellipsis$ ls ~/allegro-manual-4.0.3.en.p

The patch is not implemented for multibyte (don't know how to deal
with that) and it would be better if the length of the ellipsis
could be set at runtime rather than with a define. I wonder if you
would like to merge this patch with the main distribution. Please
tell me what modifications would I have to do, if you so desire.

Now, about the long story of this improvement. I started thinking
about it during April of 2003. The 16th of that month I mailed
[EMAIL PROTECTED] asking what would be the procedure to
collaborate a patch implementing this feature. While I waited for
an answer (which never came), I implemented this for bash 2.x and
used it just myself.

Years later I realise I forgot to contribute the patch digging
through an old mailbox.  This time, the 29th of October of 2005
I try luck with [EMAIL PROTECTED] Again, no luck. This time I
even included the patch for bash 2.x.

Nearly a month later, despite a lack of instructions, I manage to
subscribe to this mailing thanks to the answers of Bob Proulx and
Chet Ramey. Lurking here, I see no trace of active development,
no information about the process of submitting patches, no real
hint of what somebody would have to do to contribute one...

It just looks very very sad that two presumably valid email
addresses don't have anybody reading their mail (or somebody not
bothering to answer), and even instructions about mailing list
subscription are hidden and have to be asked or discovered. Isn't
the bash/readline community preventing software contributions
through lack of communication?

I yet have to find if there is any source control software in use,
so I could make a diff against some sort of development branch. I
wonder, is there any or you guys control things by hand?
diff -u -r bash-3.1/doc/bashref.info bash-3.1-ellipsis/doc/bashref.info
--- bash-3.1/doc/bashref.info   2005-10-03 21:07:32.000000000 +0200
+++ bash-3.1-ellipsis/doc/bashref.info  2005-12-10 22:43:09.091010680 +0100
@@ -5986,6 +5986,12 @@
           `insert-comment' command is executed.  The default value is
           `"#"'.
 
+    `completion-ellipsis'
+          If set to `on', Readline will transform the common prefix
+          of matched words in an ellipsis when showing possible
+          options, if the prefix is longer than three characters.
+          The default value is `off'.
+
     `completion-ignore-case'
           If set to `on', Readline performs filename matching and
           completion in a case-insensitive fashion.  The default value
diff -u -r bash-3.1/lib/readline/bind.c bash-3.1-ellipsis/lib/readline/bind.c
--- bash-3.1/lib/readline/bind.c        2005-10-14 17:04:27.000000000 +0200
+++ bash-3.1-ellipsis/lib/readline/bind.c       2005-12-10 22:39:20.485763960 
+0100
@@ -1383,6 +1383,7 @@
   { "bind-tty-special-chars",  &_rl_bind_stty_chars,           0 },
   { "blink-matching-paren",    &rl_blink_matching_paren,       V_SPECIAL },
   { "byte-oriented",           &rl_byte_oriented,              0 },
+  { "completion-ellipsis",     &_rl_completion_ellipsis,       0 },
   { "completion-ignore-case",  &_rl_completion_case_fold,      0 },
   { "convert-meta",            &_rl_convert_meta_chars_to_ascii, 0 },
   { "disable-completion",      &rl_inhibit_completion,         0 },
diff -u -r bash-3.1/lib/readline/complete.c 
bash-3.1-ellipsis/lib/readline/complete.c
--- bash-3.1/lib/readline/complete.c    2005-10-08 04:30:18.000000000 +0200
+++ bash-3.1-ellipsis/lib/readline/complete.c   2005-12-10 22:36:58.844296736 
+0100
@@ -110,8 +110,8 @@
 static int _rl_internal_pager PARAMS((int));
 static char *printable_part PARAMS((char *));
 static int fnwidth PARAMS((const char *));
-static int fnprint PARAMS((const char *));
-static int print_filename PARAMS((char *, char *));
+static int fnprint PARAMS((const char *, const int));
+static int print_filename PARAMS((char *, char *, int));
 
 static char **gen_completion_matches PARAMS((char *, int, int, 
rl_compentry_func_t *, int, int));
 
@@ -160,6 +160,11 @@
 int _rl_completion_case_fold;
 #endif
 
+/* If non-zero, the common part of the displayed matches is substituted
+   with an ellipsis if it's longer than ELLIPSIS_LENGTH characters */
+int _rl_completion_ellipsis = 0;
+#define ELLIPSIS_LENGTH 3
+
 /* If non-zero, don't match hidden files (filenames beginning with a `.' on
    Unix) when doing filename completion. */
 int _rl_match_hidden_files = 1;
@@ -615,8 +620,9 @@
 }
 
 static int
-fnprint (to_print)
+fnprint (to_print, common_length)
      const char *to_print;
+     const int common_length;
 {
   int printed_len;
   const char *s;
@@ -632,7 +638,21 @@
 #endif
 
   printed_len = 0;
-  s = to_print;
+  /* Before looping over output charactes, see if we have to skip some. */
+  if (common_length)
+    {
+      int count;
+      char ellipsis = '.';
+
+      /* Change ellipsis character if equals dot. */
+      if (ellipsis == *(to_print + common_length))
+        ellipsis = '_';
+
+      for (count = 0; count < ELLIPSIS_LENGTH; count++)
+         putc (ellipsis, rl_outstream);
+    }
+
+  s = to_print + common_length;
   while (*s)
     {
       if (CTRL_CHAR (*s))
@@ -691,14 +711,15 @@
    filenames.  Return the number of characters we output. */
 
 static int
-print_filename (to_print, full_pathname)
+print_filename (to_print, full_pathname, common_length)
      char *to_print, *full_pathname;
+     int common_length;
 {
   int printed_len, extension_char, slen, tlen;
   char *s, c, *new_full_pathname, *dn;
 
   extension_char = 0;
-  printed_len = fnprint (to_print);
+  printed_len = fnprint (to_print, common_length);
 
 #if defined (VISIBLE_STATS)
  if (rl_filename_completion_desired && (rl_visible_stats || 
_rl_complete_mark_directories))
@@ -1267,9 +1288,25 @@
      int len, max;
 {
   int count, limit, printed_len, lines;
-  int i, j, k, l;
+  int i, j, k, l, common_length;
   char *temp;
 
+  /* First match stores the common text, find out it's file length */
+  common_length = 0;
+  if (_rl_completion_ellipsis)
+    {
+      temp = strrchr (printable_part (matches[0]), '/');
+      if (!temp)
+       common_length = strlen (printable_part (matches[0]));
+      else
+       common_length = strlen (temp);
+
+      if (common_length > ELLIPSIS_LENGTH)
+       max -= common_length - ELLIPSIS_LENGTH;
+      else
+       common_length = 0;
+    }
+
   /* How many items of MAX length can we fit in the screen window? */
   max += 2;
   limit = _rl_screenwidth / max;
@@ -1307,7 +1344,7 @@
              else
                {
                  temp = printable_part (matches[l]);
-                 printed_len = print_filename (temp, matches[l]);
+                 printed_len = print_filename (temp, matches[l], 
common_length);
 
                  if (j + 1 < limit)
                    for (k = 0; k < max - printed_len; k++)
@@ -1331,7 +1368,7 @@
       for (i = 1; matches[i]; i++)
        {
          temp = printable_part (matches[i]);
-         printed_len = print_filename (temp, matches[i]);
+         printed_len = print_filename (temp, matches[i], common_length);
          /* Have we reached the end of this line? */
          if (matches[i+1])
            {
@@ -1381,7 +1418,7 @@
     {
       temp = printable_part (matches[0]);
       rl_crlf ();
-      print_filename (temp, matches[0]);
+      print_filename (temp, matches[0], 0);
       rl_crlf ();
 
       rl_forced_update_display ();
diff -u -r bash-3.1/lib/readline/doc/rluser.texi 
bash-3.1-ellipsis/lib/readline/doc/rluser.texi
--- bash-3.1/lib/readline/doc/rluser.texi       2005-09-14 20:22:30.000000000 
+0200
+++ bash-3.1-ellipsis/lib/readline/doc/rluser.texi      2005-12-10 
22:41:37.553926432 +0100
@@ -420,6 +420,12 @@
 @code{insert-comment} command is executed.  The default value
 is @code{"#"}.
 
[EMAIL PROTECTED] completion-ellipsis
+If set to @samp{on}, Readline will transform the common prefix of matched
+words in an ellipsis when showing possible options, if the prefix is
+longer than three characters.
+The default value is @samp{off}.
+
 @item completion-ignore-case
 If set to @samp{on}, Readline performs filename matching and completion
 in a case-insensitive fashion.
diff -u -r bash-3.1/lib/readline/rlprivate.h 
bash-3.1-ellipsis/lib/readline/rlprivate.h
--- bash-3.1/lib/readline/rlprivate.h   2005-08-27 02:58:19.000000000 +0200
+++ bash-3.1-ellipsis/lib/readline/rlprivate.h  2005-12-10 22:44:12.241410360 
+0100
@@ -346,6 +346,7 @@
 extern int _rl_complete_mark_directories;
 extern int _rl_complete_mark_symlink_dirs;
 extern int _rl_print_completions_horizontally;
+extern int _rl_completion_ellipsis;
 extern int _rl_completion_case_fold;
 extern int _rl_match_hidden_files;
 extern int _rl_page_completions;
_______________________________________________
Bug-bash mailing list
Bug-bash@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-bash

Reply via email to