⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 complete.c

📁 Linux下的MUD客户端程序
💻 C
📖 第 1 页 / 共 3 页
字号:
          strchr (rl_completer_word_break_characters, scan))#else      if (strchr (rl_completer_word_break_characters, scan))#endif	{	  /* If the character that caused the word break was a quoting	     character, then remember it as the delimiter. */	  if (strchr ("\"'", scan) && (end - rl_point) > 1)	    delimiter = scan;	  /* If the character isn't needed to determine something special	     about what kind of completion to perform, then advance past it. */	  if (!rl_special_prefixes || strchr (rl_special_prefixes, scan) == 0)	    rl_point++;	}    }  /* At this point, we know we have an open quote if quote_char != '\0'. */  start = rl_point;  rl_point = end;  text = rl_copy_text (start, end);  /* If the user wants to TRY to complete, but then wants to give     up and use the default completion function, they set the     variable rl_attempted_completion_function. */  if (rl_attempted_completion_function)    {      matches = (*rl_attempted_completion_function) (text, start, end);      if (matches || rl_attempted_completion_over)	{	  rl_attempted_completion_over = 0;	  our_func = (Function *)NULL;	  goto after_usual_completion;	}    }#if defined (SHELL)  /* Beware -- we're stripping the quotes here.  Do this only if we know     we are doing filename completion. */  if (found_quote && our_func == (Function *)filename_completion_function)    {      /* delete single and double quotes */      replacement = _delete_quotes (text);      free (text);      text = replacement;      replacement = (char *)0;    }#endif /* SHELL */  matches = completion_matches (text, our_func); after_usual_completion:  free (text);  if (!matches)    ding ();  else    {      register int i;      int should_quote;      /* It seems to me that in all the cases we handle we would like	 to ignore duplicate possiblilities.  Scan for the text to	 insert being identical to the other completions. */      if (rl_ignore_completion_duplicates)	{	  char *lowest_common;	  int j, newlen = 0;	  char dead_slot;	  char **temp_array;	  /* Sort the items. */	  /* It is safe to sort this array, because the lowest common	     denominator found in matches[0] will remain in place. */	  for (i = 0; matches[i]; i++);	  qsort (matches, i, sizeof (char *), compare_strings);	  /* Remember the lowest common denominator for it may be unique. */	  lowest_common = savestring (matches[0]);	  for (i = 0; matches[i + 1]; i++)	    {	      if (strcmp (matches[i], matches[i + 1]) == 0)		{		  free (matches[i]);		  matches[i] = (char *)&dead_slot;		}	      else		newlen++;	    }	  /* We have marked all the dead slots with (char *)&dead_slot.	     Copy all the non-dead entries into a new array. */	  temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));	  for (i = j = 1; matches[i]; i++)	    {	      if (matches[i] != (char *)&dead_slot)		temp_array[j++] = matches[i];	    }	  temp_array[j] = (char *)NULL;	  if (matches[0] != (char *)&dead_slot)	    free (matches[0]);	  free (matches);	  matches = temp_array;	  /* Place the lowest common denominator back in [0]. */	  matches[0] = lowest_common;	  /* If there is one string left, and it is identical to the	     lowest common denominator, then the LCD is the string to	     insert. */	  if (j == 2 && strcmp (matches[0], matches[1]) == 0)	    {	      free (matches[1]);	      matches[1] = (char *)NULL;	    }	}      switch (what_to_do)	{	case TAB:	case '!':	  /* If we are matching filenames, then here is our chance to	     do clever processing by re-examining the list.  Call the	     ignore function with the array as a parameter.  It can	     munge the array, deleting matches as it desires. */	  if (rl_ignore_some_completions_function &&	      our_func == (Function *)filename_completion_function)	    (void)(*rl_ignore_some_completions_function)(matches);	  /* If we are doing completion on quoted substrings, and any matches	     contain any of the completer_word_break_characters, then auto-	     matically prepend the substring with a quote character (just pick	     the first one from the list of such) if it does not already begin	     with a quote string.  FIXME: Need to remove any such automatically	     inserted quote character when it no longer is necessary, such as	     if we change the string we are completing on and the new set of	     matches don't require a quoted substring. */	  replacement = matches[0];	  should_quote = matches[0] && rl_completer_quote_characters &&			 rl_filename_completion_desired &&			 rl_filename_quoting_desired;	  if (should_quote)#if defined (SHELL)	    should_quote = should_quote && (!quote_char || quote_char == '"');#else	    should_quote = should_quote && !quote_char;#endif	  if (should_quote)	    {	      int do_replace;	      do_replace = NO_MATCH;	      /* If there is a single match, see if we need to quote it.		 This also checks whether the common prefix of several		 matches needs to be quoted.  If the common prefix should		 not be checked, add !matches[1] to the if clause. */	      should_quote = rl_strpbrk (matches[0], rl_completer_word_break_characters) != 0;#if defined (SHELL)	      should_quote = should_quote || rl_strpbrk (matches[0], "#$`") != 0;#endif	      if (should_quote)		do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH;	      if (do_replace != NO_MATCH)		{#if defined (SHELL)		  /* Quote the replacement, since we found an		     embedded word break character in a potential		     match. */		  char *rtext, *mtext;		  int rlen;		  extern char *double_quote ();	/* in builtins/common.c */		  /* If DO_REPLACE == MULT_MATCH, it means that there is		     more than one match.  In this case, we do not add		     the closing quote or attempt to perform tilde		     expansion.  If DO_REPLACE == SINGLE_MATCH, we try		     to perform tilde expansion, because double quotes		     inhibit tilde expansion by the shell. */		  mtext = matches[0];		  if (mtext[0] == '~' && do_replace == SINGLE_MATCH)		    mtext = tilde_expand (matches[0]);		  rtext = double_quote (mtext);		  if (mtext != matches[0])		    free (mtext);		  rlen = strlen (rtext);		  replacement = xmalloc (rlen + 1);		  /* If we're completing on a quoted string where the user		     has already supplied the opening quote, we don't want		     the quote in the replacement text, and we reset		     QUOTE_CHAR to 0 to avoid an extra closing quote. */		  if (quote_char == '"')		    {		      strcpy (replacement, rtext + 1);		      rlen--;		      quote_char = 0;		    }		  else		    strcpy (replacement, rtext);		  if (do_replace == MULT_MATCH)		    replacement[rlen - 1] = '\0';		  free (rtext);#else /* !SHELL */		  /* Found an embedded word break character in a potential		     match, so we need to prepend a quote character if we		     are replacing the completion string. */		  replacement = xmalloc (strlen (matches[0]) + 2);		  quote_char = *rl_completer_quote_characters;		  *replacement = quote_char;		  strcpy (replacement + 1, matches[0]);#endif /* SHELL */		}	    }	  if (replacement)	    {	      rl_begin_undo_group ();	      rl_delete_text (start, rl_point);	      rl_point = start;	      rl_insert_text (replacement);	      rl_end_undo_group ();	      if (replacement != matches[0])		free (replacement);	    }	  /* If there are more matches, ring the bell to indicate.	     If this was the only match, and we are hacking files,	     check the file to see if it was a directory.  If so,	     add a '/' to the name.  If not, and we are at the end	     of the line, then add a space. */	  if (matches[1])	    {	      if (what_to_do == '!')		goto display_matches;		/* XXX */	      else if (rl_editing_mode != vi_mode)		ding ();	/* There are other matches remaining. */	    }	  else	    {	      char temp_string[4];	      int temp_string_index = 0;	      if (quote_char)		temp_string[temp_string_index++] = quote_char;	      temp_string[temp_string_index++] = delimiter ? delimiter : ' ';	      temp_string[temp_string_index++] = '\0';	      if (rl_filename_completion_desired)		{		  struct stat finfo;		  char *filename = tilde_expand (matches[0]);		  if ((stat (filename, &finfo) == 0) && S_ISDIR (finfo.st_mode))		    {		      if (rl_line_buffer[rl_point] != '/')			rl_insert_text ("/");		    }		  else		    {		      if (rl_point == rl_end)			rl_insert_text (temp_string);		    }		  free (filename);		}	      else		{		  if (rl_point == rl_end)		    rl_insert_text (temp_string);		}	    }	  break;	case '*':	  {	    int i = 1;	    rl_begin_undo_group ();	    rl_delete_text (start, rl_point);	    rl_point = start;	    if (matches[1])	      {		while (matches[i])		  {		    rl_insert_text (matches[i++]);		    rl_insert_text (" ");		  }	      }	    else	      {		rl_insert_text (matches[0]);		rl_insert_text (" ");	      }	    rl_end_undo_group ();	  }	  break;	case '?':	  {	    int len, count, limit, max;	    int j, k, l;	    /* Handle simple case first.  What if there is only one answer? */	    if (!matches[1])	      {		char *temp;		temp = printable_part (matches[0]);		crlf ();		print_filename (temp, matches[0]);		crlf ();		goto restart;	      }	    /* There is more than one answer.  Find out how many there are,	       and find out what the maximum printed length of a single entry	       is. */	  display_matches:	    for (max = 0, i = 1; matches[i]; i++)	      {		char *temp;		int name_length;		temp = printable_part (matches[i]);		name_length = strlen (temp);		if (name_length > max)		  max = name_length;	      }	    len = i - 1;	    /* If there are many items, then ask the user if she	       really wants to see them all. */	    if (len >= rl_completion_query_items)	      {		crlf ();		fprintf (rl_outstream,			 "There are %d possibilities.  Do you really", len);		crlf ();		fprintf (rl_outstream, "wish to see them all? (y or n)");		fflush (rl_outstream);		if (!get_y_or_n ())		  {		    crlf ();		    goto restart;		  }	      }	    /* How many items of MAX length can we fit in the screen window? */	    max += 2;	    limit = screenwidth / max;	    if (limit != 1 && (limit * max == screenwidth))	      limit--;	    /* Avoid a possible floating exception.  If max > screenwidth,	       limit will be 0 and a divide-by-zero fault will result. */	    if (limit == 0)	      limit = 1;	    /* How many iterations of the printing loop? */	    count = (len + (limit - 1)) / limit;	    /* Watch out for special case.  If LEN is less than LIMIT, then	       just do the inner printing loop. */	    if (len < limit)	      count = 1;	    /* Sort the items if they are not already sorted. */	    if (!rl_ignore_completion_duplicates)	      qsort (matches, len, sizeof (char *), compare_strings);	    /* Print the sorted items, up-and-down alphabetically, like	       ls might. */	    crlf ();	    for (i = 1; i < count + 1; i++)	      {		for (j = 0, l = i; j < limit; j++)		  {		    if (l > len || !matches[l])		      break;		    else		      {			char *temp;			int printed_length;			temp = printable_part (matches[l]);			printed_length = strlen (temp);			printed_length += print_filename (temp, matches[l]);			if (j + 1 < limit)			  {			    for (k = 0; k < max - printed_length; k++)			      putc (' ', rl_outstream);			  }		      }		    l += count;		  }		crlf ();	      }	  restart:	    rl_on_new_line ();	  }	  break;	default:	  fprintf (stderr, "\r\nreadline: bad value for what_to_do in rl_complete\n");	  abort ();	}      for (i = 0; matches[i]; i++)	free (matches[i]);      free (matches);    }  /* Check to see if the line has changed through all of this manipulation. */  if (saved_line_buffer)    {      if (strcmp (rl_line_buffer, saved_line_buffer) != 0)	completion_changed_buffer = 1;      else	completion_changed_buffer = 0;      free (saved_line_buffer);    }  return 0;}#if defined (VISIBLE_STATS)/* Return the character which best describes FILENAME.     `@' for symbolic links     `/' for directories     `*' for executables     `=' for sockets */static intstat_char (filename)     char *filename;{  struct stat finfo;  int character, r;#if defined (S_ISLNK)  r = lstat (filename, &finfo);#else  r = stat (filename, &finfo);#endif  if (r == -1)    return (0);  character = 0;  if (S_ISDIR (finfo.st_mode))    character = '/';#if defined (S_ISLNK)  else if (S_ISLNK (finfo.st_mode))    character = '@';#endif /* S_ISLNK */#if defined (S_ISSOCK)  else if (S_ISSOCK (finfo.st_mode))    character = '=';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -