?? complete.c
字號(hào):
{ rl_ding (); FREE (saved_line_buffer); completion_changed_buffer = 0; RL_UNSETSTATE(RL_STATE_COMPLETING); return (0); } switch (what_to_do) { case TAB: case '!': /* Insert the first match with proper quoting. */ if (*matches[0]) insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); /* If there are more matches, ring the bell to indicate. If we are in vi mode, Posix.2 says to not ring the bell. If the `show-all-if-ambiguous' variable is set, display all the matches immediately. Otherwise, if this was the only match, and we are hacking files, check the file to see if it was a directory. If so, and the `mark-directories' variable is set, 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 == '!') { display_matches (matches); break; } else if (rl_editing_mode != vi_mode) rl_ding (); /* There are other matches remaining. */ } else append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); break; case '*': insert_all_matches (matches, start, "e_char); break; case '?': display_matches (matches); break; default: fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do); rl_ding (); FREE (saved_line_buffer); RL_UNSETSTATE(RL_STATE_COMPLETING); return 1; } _rl_free_match_list (matches); /* Check to see if the line has changed through all of this manipulation. */ if (saved_line_buffer) { completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0; free (saved_line_buffer); } RL_UNSETSTATE(RL_STATE_COMPLETING); return 0;}/***************************************************************//* *//* Application-callable completion match generator functions *//* *//***************************************************************//* 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 **rl_completion_matches (text, entry_function) const char *text; rl_compentry_func_t *entry_function;{ /* Number of slots in match_list. */ int match_list_size; /* The list of matches. */ char **match_list; /* Number of matches actually found. */ int matches; /* Temporary string binder. */ char *string; matches = 0; match_list_size = 10; match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); 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) compute_lcd_of_matches (match_list, matches, text); else /* There were no matches. */ { free (match_list); match_list = (char **)NULL; } return (match_list);}/* A completion function for usernames. TEXT contains a partial username preceded by a random character (usually `~'). */char *rl_username_completion_function (text, state) const char *text; int state;{#if defined (__WIN32__) || defined (__OPENNT) return (char *)NULL;#else /* !__WIN32__ && !__OPENNT) */ static char *username = (char *)NULL; static struct passwd *entry; static int namelen, first_char, first_char_loc; char *value; if (state == 0) { FREE (username); first_char = *text; first_char_loc = first_char == '~'; username = savestring (&text[first_char_loc]); namelen = strlen (username); setpwent (); } while (entry = getpwent ()) { /* Null usernames should result in all users as possible completions. */ if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) break; } if (entry == 0) { endpwent (); return ((char *)NULL); } else { value = (char *)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 /* !__WIN32__ && !__OPENNT */}/* 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 *rl_filename_completion_function (text, state) const char *text; int state;{ static DIR *directory = (DIR *)NULL; static char *filename = (char *)NULL; static char *dirname = (char *)NULL; static char *users_dirname = (char *)NULL; static int filename_len; char *temp; int dirlen; struct dirent *entry; /* If we don't have any state, then do some initialization. */ if (state == 0) { /* If we were interrupted before closing the directory or reading all of its contents, close it. */ if (directory) { closedir (directory); directory = (DIR *)NULL; } FREE (dirname); FREE (filename); FREE (users_dirname); filename = savestring (text); if (*text == 0) text = "."; dirname = savestring (text); temp = strrchr (dirname, '/');#if defined (__MSDOS__) /* special hack for //X/... */ if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/') temp = strrchr (dirname + 3, '/');#endif if (temp) { strcpy (filename, ++temp); *temp = '\0'; }#if defined (__MSDOS__) /* searches from current directory on the drive */ else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':') { strcpy (filename, dirname + 2); dirname[2] = '\0'; }#endif else { dirname[0] = '.'; dirname[1] = '\0'; } /* 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); if (*dirname == '~') { temp = tilde_expand (dirname); free (dirname); dirname = temp; } if (rl_directory_rewrite_hook) (*rl_directory_rewrite_hook) (&dirname); if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&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. */ entry = (struct dirent *)NULL; while (directory && (entry = readdir (directory))) { /* Special case for no filename. If the user has disabled the `match-hidden-files' variable, skip filenames beginning with `.'. All other entries except "." and ".." match. */ if (filename_len == 0) { if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name)) continue; if (entry->d_name[0] != '.' || (entry->d_name[1] && (entry->d_name[1] != '.' || entry->d_name[2]))) break; } else { /* Otherwise, if these match up to the length of filename, then it is a match. */ if (_rl_completion_case_fold) { if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) && (((int)D_NAMLEN (entry)) >= filename_len) && (_rl_strnicmp (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; } } } if (entry == 0) { 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 { /* dirname && (strcmp (dirname, ".") != 0) */ if (dirname && (dirname[0] != '.' || dirname[1])) { if (rl_complete_with_tilde_expansion && *users_dirname == '~') { dirlen = strlen (dirname); temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, dirname); /* Canonicalization cuts off any final slash present. We may need to add it back. */ if (dirname[dirlen - 1] != '/') { temp[dirlen++] = '/'; temp[dirlen] = '\0'; } } else { dirlen = strlen (users_dirname); temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, users_dirname); /* Make sure that temp has a trailing slash here. */ if (users_dirname[dirlen - 1] != '/') temp[dirlen++] = '/'; } strcpy (temp + dirlen, entry->d_name); } else temp = savestring (entry->d_name); return (temp); }}/* An initial implementation of a menu completion function a la tcsh. The first time (if the last readline command was not rl_menu_complete), we generate the list of matches. This code is very similar to the code in rl_complete_internal -- there should be a way to combine the two. Then, for each item in the list of matches, we insert the match in an undoable fashion, with the appropriate character appended (this happens on the second and subsequent consecutive calls to rl_menu_complete). When we hit the end of the match list, we restore the original unmatched text, ring the bell, and reset the counter to zero. */intrl_menu_complete (count, ignore) int count, ignore;{ rl_compentry_func_t *our_func; int matching_filenames, found_quote; static char *orig_text; static char **matches = (char **)0; static int match_list_index = 0; static int match_list_size = 0; static int orig_start, orig_end; static char quote_char; static int delimiter; /* The first time through, we generate the list of matches and set things up to insert them. */ if (rl_last_func != rl_menu_complete) { /* Clean up from previous call, if any. */ FREE (orig_text); if (matches) _rl_free_match_list (matches); match_list_index = match_list_size = 0; matches = (char **)NULL; /* Only the completion entry function can change these. */ set_completion_defaults ('%'); our_func = rl_completion_entry_function ? rl_completion_entry_function : rl_filename_completion_function; /* We now look backwards for the start of a filename/variable word. */ orig_end = rl_point; found_quote = delimiter = 0; quote_char = '\0'; if (rl_point) /* This (possibly) changes rl_point. If it returns a non-zero char, we know we have an open quote. */ quote_char = _rl_find_completion_word (&found_quote, &delimiter); orig_start = rl_point; rl_point = orig_end; orig_text = rl_copy_text (orig_start, orig_end); matches = gen_completion_matches (orig_text, orig_start, orig_end, our_func, found_quote, quote_char); /* If we are matching filenames, the attempted completion function will have set rl_filename_completion_desired to a non-zero value. The basic rl_filename_completion_function does this. */ matching_filenames = rl_filename_completion_desired; if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) { rl_ding (); FREE (matches); matches = (char **)0; FREE (orig_text); orig_text = (char *)0; completion_changed_buffer = 0; return (0); } for (match_list_size = 0; matches[match_list_size]; match_list_size++) ; /* matches[0] is lcd if match_list_size > 1, but the circular buffer code below should take care of it. */ } /* Now we have the list of matches. Replace the text between rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with matches[match_list_index], and add any necessary closing char. */ if (matches == 0 || match_list_size == 0) { rl_ding (); FREE (matches); matches = (char **)0; completion_changed_buffer = 0; return (0); } match_list_index = (match_list_index + count) % match_list_size; if (match_list_index < 0) match_list_index += match_list_size; if (match_list_index == 0 && match_list_size > 1) { rl_ding (); insert_match (orig_text, orig_start, MULT_MATCH, "e_char); } else { insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); append_to_match (matches[match_list_index], delimiter, quote_char, strcmp (orig_text, matches[match_list_index])); } completion_changed_buffer = 1; return (0);}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -