📄 complete.c
字号:
#endif /* S_ISSOCK */ else if (S_ISREG (finfo.st_mode)) { if (access (filename, X_OK) == 0) character = '*'; } return (character);}#endif /* VISIBLE_STATS *//* Stupid comparison routine for qsort () ing strings. */static intcompare_strings (s1, s2) char **s1, **s2;{ int result; result = **s1 - **s2; if (result == 0) result = strcmp (*s1, *s2); return result;}/* A completion function for usernames. TEXT contains a partial username preceded by a random character (usually `~'). */char *username_completion_function (text, state) int state; char *text;{#if defined (__GO32__) return (char *)NULL;#else /* !__GO32__ */ static char *username = (char *)NULL; static struct passwd *entry; static int namelen, first_char, first_char_loc; if (!state) { if (username) free (username); first_char = *text; if (first_char == '~') first_char_loc = 1; else first_char_loc = 0; username = savestring (&text[first_char_loc]); namelen = strlen (username); setpwent (); } while (entry = getpwent ()) { if ((username[0] == entry->pw_name[0]) && (strncmp (username, entry->pw_name, namelen) == 0)) break; } if (!entry) { endpwent (); return ((char *)NULL); } else { char *value = xmalloc (2 + strlen (entry->pw_name)); *value = *text; strcpy (value + first_char_loc, entry->pw_name); if (first_char == '~') rl_filename_completion_desired = 1; return (value); }#endif /* !__GO32__ */}/* **************************************************************** *//* *//* Completion *//* *//* **************************************************************** *//* Non-zero means that case is not significant in completion. */int completion_case_fold = 0;/* Return an array of (char *) which is a list of completions for TEXT. If there are no completions, return a NULL pointer. The first entry in the returned array is the substitution for TEXT. The remaining entries are the possible completions. The array is terminated with a NULL pointer. ENTRY_FUNCTION is a function of two args, and returns a (char *). The first argument is TEXT. The second is a state argument; it should be zero on the first call, and non-zero on subsequent calls. It returns a NULL pointer to the caller when there are no more matches. */char **completion_matches (text, entry_function) char *text; CPFunction *entry_function;{ /* Number of slots in match_list. */ int match_list_size; /* The list of matches. */ char **match_list = (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *)); /* Number of matches actually found. */ int matches = 0; /* Temporary string binder. */ char *string; match_list[1] = (char *)NULL; while (string = (*entry_function) (text, matches)) { if (matches + 1 == match_list_size) match_list = (char **)xrealloc (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); match_list[++matches] = string; match_list[matches + 1] = (char *)NULL; } /* If there were any matches, then look through them finding out the lowest common denominator. That then becomes match_list[0]. */ if (matches) { register int i = 1; int low = 100000; /* Count of max-matched characters. */ /* If only one match, just use that. */ if (matches == 1) { match_list[0] = match_list[1]; match_list[1] = (char *)NULL; } else { /* Otherwise, compare each member of the list with the next, finding out where they stop matching. */ while (i < matches) { register int c1, c2, si; if (completion_case_fold) { for (si = 0; (c1 = to_lower(match_list[i][si])) && (c2 = to_lower(match_list[i + 1][si])); si++) if (c1 != c2) break; } else { for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++) if (c1 != c2) break; } if (low > si) low = si; i++; } match_list[0] = xmalloc (low + 1); strncpy (match_list[0], match_list[1], low); match_list[0][low] = '\0'; } } else /* There were no matches. */ { free (match_list); match_list = (char **)NULL; } return (match_list);}/* Okay, now we write the entry_function for filename completion. In the general case. Note that completion in the shell is a little different because of all the pathnames that must be followed when looking up the completion for a command. */char *filename_completion_function (text, state) int state; char *text;{ static DIR *directory; static char *filename = (char *)NULL; static char *dirname = (char *)NULL; static char *users_dirname = (char *)NULL; static int filename_len; struct dirent *entry = (struct dirent *)NULL; /* If we don't have any state, then do some initialization. */ if (!state) { char *temp; if (dirname) free (dirname); if (filename) free (filename); if (users_dirname) free (users_dirname); filename = savestring (text); if (!*text) text = "."; dirname = savestring (text); temp = strrchr (dirname, '/'); if (temp) { strcpy (filename, ++temp); *temp = '\0'; } else strcpy (dirname, "."); /* We aren't done yet. We also support the "~user" syntax. */ /* Save the version of the directory that the user typed. */ users_dirname = savestring (dirname); { char *temp_dirname; int replace_dirname; temp_dirname = tilde_expand (dirname); free (dirname); dirname = temp_dirname; replace_dirname = 0; if (rl_directory_completion_hook) replace_dirname = (*rl_directory_completion_hook) (&dirname); if (replace_dirname) { free (users_dirname); users_dirname = savestring (dirname); } } directory = opendir (dirname); filename_len = strlen (filename); rl_filename_completion_desired = 1; } /* At this point we should entertain the possibility of hacking wildcarded filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name contains globbing characters, then build an array of directories, and then map over that list while completing. */ /* *** UNIMPLEMENTED *** */ /* Now that we have some state, we can read the directory. */ while (directory && (entry = readdir (directory))) { /* Special case for no filename. All entries except "." and ".." match. */ if (!filename_len) { if ((strcmp (entry->d_name, ".") != 0) && (strcmp (entry->d_name, "..") != 0)) break; } else { /* Otherwise, if these match up to the length of filename, then it is a match. */ if ((entry->d_name[0] == filename[0]) && (((int)D_NAMLEN (entry)) >= filename_len) && (strncmp (filename, entry->d_name, filename_len) == 0)) break; } } if (!entry) { if (directory) { closedir (directory); directory = (DIR *)NULL; } if (dirname) { free (dirname); dirname = (char *)NULL; } if (filename) { free (filename); filename = (char *)NULL; } if (users_dirname) { free (users_dirname); users_dirname = (char *)NULL; } return (char *)NULL; } else { char *temp; /* dirname && (strcmp (dirname, ".") != 0) */ if (dirname && (dirname[0] != '.' || dirname[1])) { if (rl_complete_with_tilde_expansion && *users_dirname == '~') { int dirlen = strlen (dirname); temp = xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, dirname); /* Canonicalization cuts off any final slash present. We need to add it back. */ if (dirname[dirlen - 1] != '/') { temp[dirlen] = '/'; temp[dirlen + 1] = '\0'; } } else { temp = xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry)); strcpy (temp, users_dirname); } strcat (temp, entry->d_name); } else temp = (savestring (entry->d_name)); return (temp); }}/* A function for simple tilde expansion. */intrl_tilde_expand (ignore, key) int ignore, key;{ register int start, end; char *homedir; end = rl_point; start = end - 1; if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') { homedir = tilde_expand ("~"); goto insert; } else if (rl_line_buffer[start] != '~') { for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--); start++; } end = start; do { end++; } while (!whitespace (rl_line_buffer[end]) && end < rl_end); if (whitespace (rl_line_buffer[end]) || end >= rl_end) end--; /* If the first character of the current word is a tilde, perform tilde expansion and insert the result. If not a tilde, do nothing. */ if (rl_line_buffer[start] == '~') { char *temp; int len; len = end - start + 1; temp = xmalloc (len + 1); strncpy (temp, rl_line_buffer + start, len); temp[len] = '\0'; homedir = tilde_expand (temp); free (temp); insert: rl_begin_undo_group (); rl_delete_text (start, end + 1); rl_point = start; rl_insert_text (homedir); rl_end_undo_group (); } return (0);}/* Find the first occurrence in STRING1 of any character from STRING2. Return a pointer to the character in STRING1. */static char *rl_strpbrk (string1, string2) char *string1, *string2;{ register char *scan; for (; *string1; string1++) { for (scan = string2; *scan; scan++) { if (*string1 == *scan) { return (string1); } } } return ((char *)NULL);}#if defined (STATIC_MALLOC)/* **************************************************************** *//* *//* xmalloc and xrealloc () *//* *//* **************************************************************** */static void memory_error_and_abort ();static char *xmalloc (bytes) int bytes;{ char *temp = (char *)malloc (bytes); if (!temp) memory_error_and_abort (); return (temp);}static char *xrealloc (pointer, bytes) char *pointer; int bytes;{ char *temp; if (!pointer) temp = (char *)malloc (bytes); else temp = (char *)realloc (pointer, bytes); if (!temp) memory_error_and_abort (); return (temp);}static voidmemory_error_and_abort (){ fprintf (stderr, "readline: Out of virtual memory!\n"); abort ();}#endif /* STATIC_MALLOC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -