?? complete.c
字號:
match_list[0][low] = '\0'; } return matches;}static intpostprocess_matches (matchesp, matching_filenames) char ***matchesp; int matching_filenames;{ char *t, **matches, **temp_matches; int nmatch, i; matches = *matchesp; if (matches == 0) return 0; /* 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) { temp_matches = remove_duplicate_matches (matches); free (matches); matches = temp_matches; } /* 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 && matching_filenames) { for (nmatch = 1; matches[nmatch]; nmatch++) ; (void)(*rl_ignore_some_completions_function) (matches); if (matches == 0 || matches[0] == 0) { FREE (matches); *matchesp = (char **)0; return 0; } else { /* If we removed some matches, recompute the common prefix. */ for (i = 1; matches[i]; i++) ; if (i > 1 && i < nmatch) { t = matches[0]; compute_lcd_of_matches (matches, i - 1, t); FREE (t); } } } *matchesp = matches; return (1);}/* A convenience function for displaying a list of strings in columnar format on readline's output stream. MATCHES is the list of strings, in argv format, LEN is the number of strings in MATCHES, and MAX is the length of the longest string in MATCHES. */voidrl_display_match_list (matches, len, max) char **matches; int len, max;{ int count, limit, printed_len, lines; int i, j, k, l; char *temp; /* How many items of MAX length can we fit in the screen window? */ max += 2; limit = _rl_screenwidth / max; if (limit != 1 && (limit * max == _rl_screenwidth)) limit--; /* Avoid a possible floating exception. If max > _rl_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. 0 < len <= limit implies count = 1. */ /* Sort the items if they are not already sorted. */ if (rl_ignore_completion_duplicates == 0) qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); rl_crlf (); lines = 0; if (_rl_print_completions_horizontally == 0) { /* Print the sorted items, up-and-down alphabetically, like ls. */ for (i = 1; i <= count; i++) { for (j = 0, l = i; j < limit; j++) { if (l > len || matches[l] == 0) break; else { temp = printable_part (matches[l]); printed_len = print_filename (temp, matches[l]); if (j + 1 < limit) for (k = 0; k < max - printed_len; k++) putc (' ', rl_outstream); } l += count; } rl_crlf (); lines++; if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count) { lines = _rl_internal_pager (lines); if (lines < 0) return; } } } else { /* Print the sorted items, across alphabetically, like ls -x. */ for (i = 1; matches[i]; i++) { temp = printable_part (matches[i]); printed_len = print_filename (temp, matches[i]); /* Have we reached the end of this line? */ if (matches[i+1]) { if (i && (limit > 1) && (i % limit) == 0) { rl_crlf (); lines++; if (_rl_page_completions && lines >= _rl_screenheight - 1) { lines = _rl_internal_pager (lines); if (lines < 0) return; } } else for (k = 0; k < max - printed_len; k++) putc (' ', rl_outstream); } } rl_crlf (); }}/* Display MATCHES, a list of matching filenames in argv format. This handles the simple case -- a single match -- first. If there is more than one match, we compute the number of strings in the list and the length of the longest string, which will be needed by the display function. If the application wants to handle displaying the list of matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the address of a function, and we just call it. If we're handling the display ourselves, we just call rl_display_match_list. We also check that the list of matches doesn't exceed the user-settable threshold, and ask the user if he wants to see the list if there are more matches than RL_COMPLETION_QUERY_ITEMS. */static voiddisplay_matches (matches) char **matches;{ int len, max, i; char *temp; /* Move to the last visible line of a possibly-multiple-line command. */ _rl_move_vert (_rl_vis_botlin); /* Handle simple case first. What if there is only one answer? */ if (matches[1] == 0) { temp = printable_part (matches[0]); rl_crlf (); print_filename (temp, matches[0]); rl_crlf (); rl_forced_update_display (); rl_display_fixed = 1; return; } /* There is more than one answer. Find out how many there are, and find the maximum printed length of a single entry. */ for (max = 0, i = 1; matches[i]; i++) { temp = printable_part (matches[i]); len = strlen (temp); if (len > max) max = len; } len = i - 1; /* If the caller has defined a display hook, then call that now. */ if (rl_completion_display_matches_hook) { (*rl_completion_display_matches_hook) (matches, len, max); return; } /* If there are many items, then ask the user if she really wants to see them all. */ if (len >= rl_completion_query_items) { rl_crlf (); fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); fflush (rl_outstream); if (get_y_or_n (0) == 0) { rl_crlf (); rl_forced_update_display (); rl_display_fixed = 1; return; } } rl_display_match_list (matches, len, max); rl_forced_update_display (); rl_display_fixed = 1;}static char *make_quoted_replacement (match, mtype, qc) char *match; int mtype; char *qc; /* Pointer to quoting character, if any */{ int should_quote, do_replace; char *replacement; /* 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 = match; should_quote = match && rl_completer_quote_characters && rl_filename_completion_desired && rl_filename_quoting_desired; if (should_quote) should_quote = should_quote && (!qc || !*qc || (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc))); if (should_quote) { /* 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. */ should_quote = rl_filename_quote_characters ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0) : 0; do_replace = should_quote ? mtype : NO_MATCH; /* Quote the replacement, since we found an embedded word break character in a potential match. */ if (do_replace != NO_MATCH && rl_filename_quoting_function) replacement = (*rl_filename_quoting_function) (match, do_replace, qc); } return (replacement);}static voidinsert_match (match, start, mtype, qc) char *match; int start, mtype; char *qc;{ char *replacement; char oqc; oqc = qc ? *qc : '\0'; replacement = make_quoted_replacement (match, mtype, qc); /* Now insert the match. */ if (replacement) { /* Don't double an opening quote character. */ if (qc && *qc && start && rl_line_buffer[start - 1] == *qc && replacement[0] == *qc) start--; /* If make_quoted_replacement changed the quoting character, remove the opening quote and insert the (fully-quoted) replacement. */ else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc && replacement[0] != oqc) start--; _rl_replace_text (replacement, start, rl_point - 1); if (replacement != match) free (replacement); }}/* Append any necessary closing quote and a separator character to the just-inserted match. If the user has specified that directories should be marked by a trailing `/', append one of those instead. The default trailing character is a space. Returns the number of characters appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS has them) and don't add a suffix for a symlink to a directory. A nontrivial match is one that actually adds to the word being completed. The variable rl_completion_mark_symlink_dirs controls this behavior (it's initially set to the what the user has chosen, indicated by the value of _rl_complete_mark_symlink_dirs, but may be modified by an application's completion function). */static intappend_to_match (text, delimiter, quote_char, nontrivial_match) char *text; int delimiter, quote_char, nontrivial_match;{ char temp_string[4], *filename; int temp_string_index, s; struct stat finfo; temp_string_index = 0; if (quote_char && rl_point && rl_line_buffer[rl_point - 1] != quote_char) temp_string[temp_string_index++] = quote_char; if (delimiter) temp_string[temp_string_index++] = delimiter; else if (rl_completion_suppress_append == 0 && rl_completion_append_character) temp_string[temp_string_index++] = rl_completion_append_character; temp_string[temp_string_index++] = '\0'; if (rl_filename_completion_desired) { filename = tilde_expand (text); s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0) ? LSTAT (filename, &finfo) : stat (filename, &finfo); if (s == 0 && S_ISDIR (finfo.st_mode)) { if (_rl_complete_mark_directories) { /* This is clumsy. Avoid putting in a double slash if point is at the end of the line and the previous character is a slash. */ if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/') ; else if (rl_line_buffer[rl_point] != '/') rl_insert_text ("/"); } }#ifdef S_ISLNK /* Don't add anything if the filename is a symlink and resolves to a directory. */ else if (s == 0 && S_ISLNK (finfo.st_mode) && stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) ;#endif else { if (rl_point == rl_end && temp_string_index) rl_insert_text (temp_string); } free (filename); } else { if (rl_point == rl_end && temp_string_index) rl_insert_text (temp_string); } return (temp_string_index);}static voidinsert_all_matches (matches, point, qc) char **matches; int point; char *qc;{ int i; char *rp; rl_begin_undo_group (); /* remove any opening quote character; make_quoted_replacement will add it back. */ if (qc && *qc && point && rl_line_buffer[point - 1] == *qc) point--; rl_delete_text (point, rl_point); rl_point = point; if (matches[1]) { for (i = 1; matches[i]; i++) { rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc); rl_insert_text (rp); rl_insert_text (" "); if (rp != matches[i]) free (rp); } } else { rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc); rl_insert_text (rp); rl_insert_text (" "); if (rp != matches[0]) free (rp); } rl_end_undo_group ();}void_rl_free_match_list (matches) char **matches;{ register int i; if (matches == 0) return; for (i = 0; matches[i]; i++) free (matches[i]); free (matches);}/* Complete the word at or before point. 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. */intrl_complete_internal (what_to_do) int what_to_do;{ char **matches; rl_compentry_func_t *our_func; int start, end, delimiter, found_quote, i, nontrivial_lcd; char *text, *saved_line_buffer; char quote_char; RL_SETSTATE(RL_STATE_COMPLETING); set_completion_defaults (what_to_do); saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; 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. */ 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); start = rl_point; rl_point = end; text = rl_copy_text (start, end); matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); /* nontrivial_lcd is set if the common prefix adds something to the word being completed. */ nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; free (text); if (matches == 0) { rl_ding (); FREE (saved_line_buffer); completion_changed_buffer = 0; RL_UNSETSTATE(RL_STATE_COMPLETING); return (0); } /* 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. */ i = rl_filename_completion_desired; if (postprocess_matches (&matches, i) == 0)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -