📄 complete.c
字号:
this word break character is quoted and should be skipped. */ if (rl_char_is_quoted_p && found_quote && (*rl_char_is_quoted_p) (rl_line_buffer, rl_point)) continue; /* Convoluted code, but it avoids an n^2 algorithm with calls to char_is_quoted. */ break; } } /* If we are at an unquoted word break, then advance past it. */ scan = rl_line_buffer[rl_point]; /* If there is an application-specific function to say whether or not a character is quoted and we found a quote character, let that function decide whether or not a character is a word break, even if it is found in rl_completer_word_break_characters. Don't bother if we're at the end of the line, though. */ if (scan) { if (rl_char_is_quoted_p) isbrk = (found_quote == 0 || (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) && strchr (brkchars, scan) != 0; else isbrk = strchr (brkchars, scan) != 0; if (isbrk) { /* If the character that caused the word break was a quoting character, then remember it as the delimiter. */ if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, 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 == 0 || strchr (rl_special_prefixes, scan) == 0) rl_point++; } } if (fp) *fp = found_quote; if (dp) *dp = delimiter; return (quote_char);}static char **gen_completion_matches (text, start, end, our_func, found_quote, quote_char) char *text; int start, end; rl_compentry_func_t *our_func; int found_quote, quote_char;{ char **matches, *temp; rl_completion_found_quote = found_quote; rl_completion_quote_character = quote_char; /* 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; return (matches); } } /* Beware -- we're stripping the quotes here. Do this only if we know we are doing filename completion and the application has defined a filename dequoting function. */ temp = (char *)NULL; if (found_quote && our_func == rl_filename_completion_function && rl_filename_dequoting_function) { /* delete single and double quotes */ temp = (*rl_filename_dequoting_function) (text, quote_char); text = temp; /* not freeing text is not a memory leak */ } matches = rl_completion_matches (text, our_func); FREE (temp); return matches; }/* Filter out duplicates in MATCHES. This frees up the strings in MATCHES. */static char **remove_duplicate_matches (matches) char **matches;{ char *lowest_common; int i, j, newlen; char dead_slot; char **temp_array; /* Sort the items. */ for (i = 0; matches[i]; i++) ; /* Sort the array without matches[0], since we need it to stay in place no matter what. */ if (i) qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); /* Remember the lowest common denominator for it may be unique. */ lowest_common = savestring (matches[0]); for (i = newlen = 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]); /* Place the lowest common denominator back in [0]. */ temp_array[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 (temp_array[0], temp_array[1]) == 0) { free (temp_array[1]); temp_array[1] = (char *)NULL; } return (temp_array);}/* Find the common prefix of the list of matches, and put it into matches[0]. */static intcompute_lcd_of_matches (match_list, matches, text) char **match_list; int matches; const char *text;{ register int i, c1, c2, si; int low; /* Count of max-matched characters. */ char *dtext; /* dequoted TEXT, if needed */#if defined (HANDLE_MULTIBYTE) int v; mbstate_t ps1, ps2; wchar_t wc1, wc2;#endif /* If only one match, just use that. Otherwise, compare each member of the list with the next, finding out where they stop matching. */ if (matches == 1) { match_list[0] = match_list[1]; match_list[1] = (char *)NULL; return 1; } for (i = 1, low = 100000; i < matches; i++) {#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { memset (&ps1, 0, sizeof (mbstate_t)); memset (&ps2, 0, sizeof (mbstate_t)); }#endif if (_rl_completion_case_fold) { for (si = 0; (c1 = _rl_to_lower(match_list[i][si])) && (c2 = _rl_to_lower(match_list[i + 1][si])); si++)#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1); mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2); wc1 = towlower (wc1); wc2 = towlower (wc2); if (wc1 != wc2) break; else if (v > 1) si += v - 1; } else#endif if (c1 != c2) break; } else { for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++)#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { mbstate_t ps_back = ps1; if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) break; else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) si += v - 1; } else#endif if (c1 != c2) break; } if (low > si) low = si; } /* If there were multiple matches, but none matched up to even the first character, and the user typed something, use that as the value of matches[0]. */ if (low == 0 && text && *text) { match_list[0] = (char *)xmalloc (strlen (text) + 1); strcpy (match_list[0], text); } else { match_list[0] = (char *)xmalloc (low + 1); /* XXX - this might need changes in the presence of multibyte chars */ /* If we are ignoring case, try to preserve the case of the string the user typed in the face of multiple matches differing in case. */ if (_rl_completion_case_fold) { /* We're making an assumption here: IF we're completing filenames AND the application has defined a filename dequoting function AND we found a quote character AND the application has requested filename quoting THEN we assume that TEXT was dequoted before checking against the file system and needs to be dequoted here before we check against the list of matches FI */ dtext = (char *)NULL; if (rl_filename_completion_desired && rl_filename_dequoting_function && rl_completion_found_quote && rl_filename_quoting_desired) { dtext = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); text = dtext; } /* sort the list to get consistent answers. */ qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); si = strlen (text); if (si <= low) { for (i = 1; i <= matches; i++) if (strncmp (match_list[i], text, si) == 0) { strncpy (match_list[0], match_list[i], low); break; } /* no casematch, use first entry */ if (i > matches) strncpy (match_list[0], match_list[1], low); } else /* otherwise, just use the text the user typed. */ strncpy (match_list[0], text, low); FREE (dtext); } else strncpy (match_list[0], match_list[1], low); 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++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -