[BACK]Return to readline.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libedit

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libedit/readline.c between version 1.11 and 1.22

version 1.11, 2000/09/04 22:06:31 version 1.22, 2002/04/09 01:57:34
Line 36 
Line 36 
  * POSSIBILITY OF SUCH DAMAGE.   * POSSIBILITY OF SUCH DAMAGE.
  */   */
   
 #include <sys/cdefs.h>  #include "config.h"
 #if !defined(lint) && !defined(SCCSID)  #if !defined(lint) && !defined(SCCSID)
 __RCSID("$NetBSD$");  __RCSID("$NetBSD$");
 #endif /* not lint && not SCCSID */  #endif /* not lint && not SCCSID */
Line 52  __RCSID("$NetBSD$");
Line 52  __RCSID("$NetBSD$");
 #include <unistd.h>  #include <unistd.h>
 #include <limits.h>  #include <limits.h>
 #include "histedit.h"  #include "histedit.h"
 #include "readline.h"  #include "readline/readline.h"
 #include "sys.h"  
 #include "el.h"  #include "el.h"
   #include "fcns.h"               /* for EL_NUM_FCNS */
   
 /* for rl_complete() */  /* for rl_complete() */
 #define TAB             '\r'  #define TAB             '\r'
Line 65  __RCSID("$NetBSD$");
Line 65  __RCSID("$NetBSD$");
 /* readline compatibility stuff - look at readline sources/documentation */  /* readline compatibility stuff - look at readline sources/documentation */
 /* to see what these variables mean */  /* to see what these variables mean */
 const char *rl_library_version = "EditLine wrapper";  const char *rl_library_version = "EditLine wrapper";
 char *rl_readline_name = "";  static char empty[] = { '\0' };
   static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
   static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
       '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
   char *rl_readline_name = empty;
 FILE *rl_instream = NULL;  FILE *rl_instream = NULL;
 FILE *rl_outstream = NULL;  FILE *rl_outstream = NULL;
 int rl_point = 0;  int rl_point = 0;
Line 77  int history_length = 0;
Line 81  int history_length = 0;
 int max_input_history = 0;  int max_input_history = 0;
 char history_expansion_char = '!';  char history_expansion_char = '!';
 char history_subst_char = '^';  char history_subst_char = '^';
 char *history_no_expand_chars = " \t\n=(";  char *history_no_expand_chars = expand_chars;
 Function *history_inhibit_expansion_function = NULL;  Function *history_inhibit_expansion_function = NULL;
   
 int rl_inhibit_completion = 0;  int rl_inhibit_completion = 0;
 int rl_attempted_completion_over = 0;  int rl_attempted_completion_over = 0;
 char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";  char *rl_basic_word_break_characters = break_chars;
 char *rl_completer_word_break_characters = NULL;  char *rl_completer_word_break_characters = NULL;
 char *rl_completer_quote_characters = NULL;  char *rl_completer_quote_characters = NULL;
 CPFunction *rl_completion_entry_function = NULL;  CPFunction *rl_completion_entry_function = NULL;
 CPPFunction *rl_attempted_completion_function = NULL;  CPPFunction *rl_attempted_completion_function = NULL;
   
 /* used for readline emulation */  /*
    * This is set to character indicating type of completion being done by
    * rl_complete_internal(); this is available for application completion
    * functions.
    */
   int rl_completion_type = 0;
   
   /*
    * If more than this number of items results from query for possible
    * completions, we ask user if they are sure to really display the list.
    */
   int rl_completion_query_items = 100;
   
   /*
    * List of characters which are word break characters, but should be left
    * in the parsed text when it is passed to the completion function.
    * Shell uses this to help determine what kind of completing to do.
    */
   char *rl_special_prefixes = (char *)NULL;
   
   /*
    * This is the character appended to the completed words if at the end of
    * the line. Default is ' ' (a space).
    */
   int rl_completion_append_character = ' ';
   
   /* stuff below is used internally by libedit for readline emulation */
   
   /* if not zero, non-unique completions always show list of possible matches */
   static int _rl_complete_show_all = 0;
   
 static History *h = NULL;  static History *h = NULL;
 static EditLine *e = NULL;  static EditLine *e = NULL;
   static int el_rl_complete_cmdnum = 0;
   
 /* internal functions */  /* internal functions */
 static unsigned char     _el_rl_complete(EditLine *, int);  static unsigned char     _el_rl_complete(EditLine *, int);
Line 101  static int   _history_expand_command(con
Line 136  static int   _history_expand_command(con
 static char             *_rl_compat_sub(const char *, const char *,  static char             *_rl_compat_sub(const char *, const char *,
                             const char *, int);                              const char *, int);
 static int               rl_complete_internal(int);  static int               rl_complete_internal(int);
   static int               _rl_qsort_string_compare(const void *, const void *);
   
 /*  /*
  * needed for prompt switching in readline()   * needed for prompt switching in readline()
Line 112  static char *el_rl_prompt = NULL;
Line 148  static char *el_rl_prompt = NULL;
 static char *  static char *
 _get_prompt(EditLine *el)  _get_prompt(EditLine *el)
 {  {
   
         return (el_rl_prompt);          return (el_rl_prompt);
 }  }
   
Line 148  rl_initialize(void)
Line 183  rl_initialize(void)
 {  {
         HistEvent ev;          HistEvent ev;
         const LineInfo *li;          const LineInfo *li;
           int i;
           int editmode = 1;
           struct termios t;
   
         if (e != NULL)          if (e != NULL)
                 el_end(e);                  el_end(e);
Line 158  rl_initialize(void)
Line 196  rl_initialize(void)
                 rl_instream = stdin;                  rl_instream = stdin;
         if (!rl_outstream)          if (!rl_outstream)
                 rl_outstream = stdout;                  rl_outstream = stdout;
   
           /*
            * See if we don't really want to run the editor
            */
           if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
                   editmode = 0;
   
         e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);          e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
   
           if (!editmode)
                   el_set(e, EL_EDITMODE, 0);
   
         h = history_init();          h = history_init();
         if (!e || !h)          if (!e || !h)
                 return (-1);                  return (-1);
Line 178  rl_initialize(void)
Line 226  rl_initialize(void)
         /* so this can be overriden */          /* so this can be overriden */
         el_set(e, EL_EDITOR, "emacs");          el_set(e, EL_EDITOR, "emacs");
   
         /* for word completition - this has to go AFTER rebinding keys */          /*
         /* to emacs-style */           * Word completition - this has to go AFTER rebinding keys
            * to emacs-style.
            */
         el_set(e, EL_ADDFN, "rl_complete",          el_set(e, EL_ADDFN, "rl_complete",
             "ReadLine compatible completition function",              "ReadLine compatible completition function",
             _el_rl_complete);              _el_rl_complete);
         el_set(e, EL_BIND, "^I", "rl_complete", NULL);          el_set(e, EL_BIND, "^I", "rl_complete", NULL);
   
           /*
            * Find out where the rl_complete function was added; this is
            * used later to detect that lastcmd was also rl_complete.
            */
           for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {
                   if (e->el_map.func[i] == _el_rl_complete) {
                           el_rl_complete_cmdnum = i;
                           break;
                   }
           }
   
         /* read settings from configuration file */          /* read settings from configuration file */
         el_source(e, NULL);          el_source(e, NULL);
   
         /* some readline apps do use this */          /*
            * Unfortunately, some applications really do use rl_point
            * and rl_line_buffer directly.
            */
         li = el_line(e);          li = el_line(e);
         /* LINTED const cast */          /* a cheesy way to get rid of const cast. */
         rl_line_buffer = (char *) li->buffer;          rl_line_buffer = memchr(li->buffer, *li->buffer, 1);
         rl_point = rl_end = 0;          rl_point = rl_end = 0;
   
         return (0);          return (0);
Line 208  readline(const char *prompt)
Line 272  readline(const char *prompt)
         HistEvent ev;          HistEvent ev;
         int count;          int count;
         const char *ret;          const char *ret;
           char *buf;
   
         if (e == NULL || h == NULL)          if (e == NULL || h == NULL)
                 rl_initialize();                  rl_initialize();
Line 223  readline(const char *prompt)
Line 288  readline(const char *prompt)
         ret = el_gets(e, &count);          ret = el_gets(e, &count);
   
         if (ret && count > 0) {          if (ret && count > 0) {
                 char *foo;  
                 int lastidx;                  int lastidx;
   
                 foo = strdup(ret);                  buf = strdup(ret);
                 lastidx = count - 1;                  lastidx = count - 1;
                 if (foo[lastidx] == '\n')                  if (buf[lastidx] == '\n')
                         foo[lastidx] = '\0';                          buf[lastidx] = '\0';
   
                 ret = foo;  
         } else          } else
                 ret = NULL;                  buf = NULL;
   
         history(h, &ev, H_GETSIZE);          history(h, &ev, H_GETSIZE);
         history_length = ev.num;          history_length = ev.num;
   
         /* LINTED const cast */          return buf;
         return (char *) ret;  
 }  }
   
 /*  /*
Line 253  readline(const char *prompt)
Line 314  readline(const char *prompt)
 void  void
 using_history(void)  using_history(void)
 {  {
   
         if (h == NULL || e == NULL)          if (h == NULL || e == NULL)
                 rl_initialize();                  rl_initialize();
 }  }
Line 717  history_tokenize(const char *str)
Line 777  history_tokenize(const char *str)
                 start = i;                  start = i;
                 for (; str[i]; i++) {                  for (; str[i]; i++) {
                         if (str[i] == '\\') {                          if (str[i] == '\\') {
                                 if (str[i] != '\0')                                  if (str[i+1] != '\0')
                                         i++;                                          i++;
                         } else if (str[i] == delim)                          } else if (str[i] == delim)
                                 delim = '\0';                                  delim = '\0';
Line 1163  filename_completion_function(const char 
Line 1223  filename_completion_function(const char 
                         temp = tilde_expand(dirname);                          temp = tilde_expand(dirname);
                         dirname = realloc(dirname, strlen(temp) + 1);                          dirname = realloc(dirname, strlen(temp) + 1);
                         (void) strcpy(dirname, temp);   /* safe */                          (void) strcpy(dirname, temp);   /* safe */
                         free(temp);     /* no more needed */                          free(temp);     /* no longer needed */
                 }                  }
                 /* will be used in cycle */                  /* will be used in cycle */
                 filename_len = strlen(filename);                  filename_len = strlen(filename);
Line 1251  username_completion_function(const char 
Line 1311  username_completion_function(const char 
 static unsigned char  static unsigned char
 _el_rl_complete(EditLine *el, int ch)  _el_rl_complete(EditLine *el, int ch)
 {  {
   
         return (unsigned char) rl_complete(0, ch);          return (unsigned char) rl_complete(0, ch);
 }  }
   
Line 1263  char **
Line 1322  char **
 completion_matches(const char *text, CPFunction *genfunc)  completion_matches(const char *text, CPFunction *genfunc)
 {  {
         char **match_list = NULL, *retstr, *prevstr;          char **match_list = NULL, *retstr, *prevstr;
         size_t math_list_len, max_equal, which, i;          size_t match_list_len, max_equal, which, i;
         int matches;          int matches;
   
         if (h == NULL || e == NULL)          if (h == NULL || e == NULL)
                 rl_initialize();                  rl_initialize();
   
         matches = 0;          matches = 0;
         math_list_len = 1;          match_list_len = 1;
         while ((retstr = (*genfunc) (text, matches)) != NULL) {          while ((retstr = (*genfunc) (text, matches)) != NULL) {
                 if (matches + 1 >= math_list_len) {                  if (matches + 1 >= match_list_len) {
                         math_list_len <<= 1;                          match_list_len <<= 1;
                         match_list = realloc(match_list,                          match_list = realloc(match_list,
                             math_list_len * sizeof(char *));                              match_list_len * sizeof(char *));
                 }                  }
                 match_list[++matches] = retstr;                  match_list[++matches] = retstr;
         }          }
Line 1287  completion_matches(const char *text, CPF
Line 1346  completion_matches(const char *text, CPF
         which = 2;          which = 2;
         prevstr = match_list[1];          prevstr = match_list[1];
         max_equal = strlen(prevstr);          max_equal = strlen(prevstr);
         for (; which < matches; which++) {          for (; which <= matches; which++) {
                 for (i = 0; i < max_equal &&                  for (i = 0; i < max_equal &&
                     prevstr[i] == match_list[which][i]; i++)                      prevstr[i] == match_list[which][i]; i++)
                         continue;                          continue;
Line 1300  completion_matches(const char *text, CPF
Line 1359  completion_matches(const char *text, CPF
         match_list[0] = retstr;          match_list[0] = retstr;
   
         /* add NULL as last pointer to the array */          /* add NULL as last pointer to the array */
         if (matches + 1 >= math_list_len)          if (matches + 1 >= match_list_len)
                 match_list = realloc(match_list,                  match_list = realloc(match_list,
                     (math_list_len + 1) * sizeof(char *));                      (match_list_len + 1) * sizeof(char *));
         match_list[matches + 1] = (char *) NULL;          match_list[matches + 1] = (char *) NULL;
   
         return (match_list);          return (match_list);
 }  }
   
   /*
    * Sort function for qsort(). Just wrapper around strcasecmp().
    */
   static int
   _rl_qsort_string_compare(i1, i2)
           const void *i1, *i2;
   {
           const char *s1 = ((const char * const *)i1)[0];
           const char *s2 = ((const char * const *)i2)[0];
   
           return strcasecmp(s1, s2);
   }
   
 /*  /*
  * called by rl_complete()   * Display list of strings in columnar format on readline's output stream.
    * 'matches' is list of strings, 'len' is number of strings in 'matches',
    * 'max' is maximum length of string in 'matches'.
    */
   void
   rl_display_match_list (matches, len, max)
        char **matches;
        int len, max;
   {
           int i, idx, limit, count;
           int screenwidth = e->el_term.t_size.h;
   
           /*
            * Find out how many entries can be put on one line, count
            * with two spaces between strings.
            */
           limit = screenwidth / (max + 2);
           if (limit == 0)
                   limit = 1;
   
           /* how many lines of output */
           count = len / limit;
           if (count * limit < len)
                   count++;
   
           /* Sort the items if they are not already sorted. */
           qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
               _rl_qsort_string_compare);
   
           idx = 1;
           for(; count > 0; count--) {
                   for(i=0; i < limit && matches[idx]; i++, idx++)
                           fprintf(e->el_outfile, "%-*s  ", max, matches[idx]);
                   fprintf(e->el_outfile, "\n");
           }
   }
   
   /*
    * Complete the word at or before point, called by rl_complete()
    * 'what_to_do' says what to do with the completion.
    * `?' means list the possible completions.
    * TAB means do standard completion.
    * `*' means insert all of the possible completions.
    * `!' means to do standard completion, and list all possible completions if
    * there is more than one.
    *
    * Note: '*' support is not implemented
  */   */
 /* ARGSUSED */  
 static int  static int
 rl_complete_internal(int what_to_do)  rl_complete_internal(int what_to_do)
 {  {
         CPFunction *complet_func;          CPFunction *complet_func;
         const LineInfo *li;          const LineInfo *li;
         char *temp, *temp2, **arr;          char *temp, **matches;
           const char *ctemp;
         size_t len;          size_t len;
   
           rl_completion_type = what_to_do;
   
         if (h == NULL || e == NULL)          if (h == NULL || e == NULL)
                 rl_initialize();                  rl_initialize();
   
Line 1328  rl_complete_internal(int what_to_do)
Line 1447  rl_complete_internal(int what_to_do)
         if (!complet_func)          if (!complet_func)
                 complet_func = filename_completion_function;                  complet_func = filename_completion_function;
   
           /* We now look backwards for the start of a filename/variable word */
         li = el_line(e);          li = el_line(e);
         /* LINTED const cast */          ctemp = (const char *) li->cursor;
         temp = (char *) li->cursor;          while (ctemp > li->buffer
         while (temp > li->buffer &&              && !strchr(rl_basic_word_break_characters, ctemp[-1])
             !strchr(rl_basic_word_break_characters, *(temp - 1)))              && (!rl_special_prefixes
                 temp--;                          || !strchr(rl_special_prefixes, ctemp[-1]) ) )
                   ctemp--;
         len = li->cursor - temp;  
         temp2 = alloca(len + 1);          len = li->cursor - ctemp;
         (void) strncpy(temp2, temp, len);          temp = alloca(len + 1);
         temp = temp2;          (void) strncpy(temp, ctemp, len);
         temp[len] = '\0';          temp[len] = '\0';
   
         /* these can be used by function called in completion_matches() */          /* these can be used by function called in completion_matches() */
Line 1347  rl_complete_internal(int what_to_do)
Line 1467  rl_complete_internal(int what_to_do)
         rl_end = li->lastchar - li->buffer;          rl_end = li->lastchar - li->buffer;
   
         if (!rl_attempted_completion_function)          if (!rl_attempted_completion_function)
                 arr = completion_matches(temp, complet_func);                  matches = completion_matches(temp, complet_func);
         else {          else {
                 int end = li->cursor - li->buffer;                  int end = li->cursor - li->buffer;
                 arr = (*rl_attempted_completion_function) (temp, (int)                  matches = (*rl_attempted_completion_function) (temp, (int)
                     (end - len), end);                      (end - len), end);
         }          }
   
         if (arr) {          if (matches) {
                 int i;                  int i, retval = CC_REFRESH;
                   int matches_num, maxlen, match_len, match_display=1;
   
                   /*
                    * Only replace the completed string with common part of
                    * possible matches if there is possible completion.
                    */
                   if (matches[0][0] != '\0') {
                           el_deletestr(e, (int) len);
                           el_insertstr(e, matches[0]);
                   }
   
                   if (what_to_do == '?')
                           goto display_matches;
   
                   if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
                           /*
                            * We found exact match. Add a space after
                            * it, unless we do filename completition and the
                            * object is a directory.
                            */
                           size_t alen = strlen(matches[0]);
                           if ((complet_func != filename_completion_function
                                 || (alen > 0 && (matches[0])[alen - 1] != '/'))
                               && rl_completion_append_character) {
                                   char buf[2];
                                   buf[0] = rl_completion_append_character;
                                   buf[1] = '\0';
                                   el_insertstr(e, buf);
                           }
                   } else if (what_to_do == '!') {
       display_matches:
                           /*
                            * More than one match and requested to list possible
                            * matches.
                            */
   
                           for(i=1, maxlen=0; matches[i]; i++) {
                                   match_len = strlen(matches[i]);
                                   if (match_len > maxlen)
                                           maxlen = match_len;
                           }
                           matches_num = i - 1;
   
                           /* newline to get on next line from command line */
                           fprintf(e->el_outfile, "\n");
   
                           /*
                            * If there are too many items, ask user for display
                            * confirmation.
                            */
                           if (matches_num > rl_completion_query_items) {
                                   fprintf(e->el_outfile,
                                   "Display all %d possibilities? (y or n) ",
                                           matches_num);
                                   fflush(e->el_outfile);
                                   if (getc(stdin) != 'y')
                                           match_display = 0;
                                   fprintf(e->el_outfile, "\n");
                           }
   
                 el_deletestr(e, (int) len);                          if (match_display)
                 el_insertstr(e, arr[0]);                                  rl_display_match_list(matches, matches_num,
                 if (strcmp(arr[0], arr[1]) == 0) {                                          maxlen);
                         /* lcd is valid object, so add a space to mark it */                          retval = CC_REDISPLAY;
                         /* in case of filename completition, add a space  */                  } else if (matches[0][0]) {
                         /* only if object found is not directory          */                          /*
                         size_t alen = strlen(arr[0]);                           * There was some common match, but the name was
                         if (complet_func != filename_completion_function                           * not complete enough. Next tab will print possible
                             || (alen > 0 && (arr[0])[alen - 1] != '/'))                           * completions.
                                 el_insertstr(e, " ");                           */
                 } else                          el_beep(e);
                   } else {
                         /* lcd is not a valid object - further specification */                          /* lcd is not a valid object - further specification */
                         /* is needed */                          /* is needed */
                         el_beep(e);                          el_beep(e);
                           retval = CC_NORM;
                   }
   
                 /* free elements of array and the array itself */                  /* free elements of array and the array itself */
                 for (i = 0; arr[i]; i++)                  for (i = 0; matches[i]; i++)
                         free(arr[i]);                          free(matches[i]);
                 free(arr), arr = NULL;                  free(matches), matches = NULL;
   
                 return (CC_REFRESH);                  return (retval);
         }          }
         return (CC_NORM);          return (CC_NORM);
 }  }
Line 1395  rl_complete(int ignore, int invoking_key
Line 1577  rl_complete(int ignore, int invoking_key
         if (rl_inhibit_completion) {          if (rl_inhibit_completion) {
                 rl_insert(ignore, invoking_key);                  rl_insert(ignore, invoking_key);
                 return (CC_REFRESH);                  return (CC_REFRESH);
         } else          } else if (e->el_state.lastcmd == el_rl_complete_cmdnum)
                 return (rl_complete_internal(invoking_key));                  return rl_complete_internal('?');
           else if (_rl_complete_show_all)
                   return rl_complete_internal('!');
           else
                   return (rl_complete_internal(TAB));
 }  }
   
   

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.22

CVSweb <webmaster@jp.NetBSD.org>