📄 complete.c
字号:
int lines;{ int i; fprintf (rl_outstream, "--More--"); fflush (rl_outstream); i = get_y_or_n (1); _rl_erase_entire_line (); if (i == 0) return -1; else if (i == 2) return (lines - 1); else return 0;}static intpath_isdir (filename) const char *filename;{ struct stat finfo; return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode));}#if defined (VISIBLE_STATS)/* Return the character which best describes FILENAME. `@' for symbolic links `/' for directories `*' for executables `=' for sockets `|' for FIFOs `%' for character special devices `#' for block special devices */static intstat_char (filename) char *filename;{ struct stat finfo; int character, r;#if defined (HAVE_LSTAT) && 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_ISCHR) else if (S_ISCHR (finfo.st_mode)) character = '%';#endif /* S_ISCHR */#if defined (S_ISBLK) else if (S_ISBLK (finfo.st_mode)) character = '#';#endif /* S_ISBLK */#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 = '=';#endif /* S_ISSOCK */#if defined (S_ISFIFO) else if (S_ISFIFO (finfo.st_mode)) character = '|';#endif else if (S_ISREG (finfo.st_mode)) { if (access (filename, X_OK) == 0) character = '*'; } return (character);}#endif /* VISIBLE_STATS *//* Return the portion of PATHNAME that should be output when listing possible completions. If we are hacking filename completion, we are only interested in the basename, the portion following the final slash. Otherwise, we return what we were passed. Since printing empty strings is not very informative, if we're doing filename completion, and the basename is the empty string, we look for the previous slash and return the portion following that. If there's no previous slash, we just return what we were passed. */static char *printable_part (pathname) char *pathname;{ char *temp, *x; if (rl_filename_completion_desired == 0) /* don't need to do anything */ return (pathname); temp = strrchr (pathname, '/');#if defined (__MSDOS__) if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') temp = pathname + 1;#endif if (temp == 0 || *temp == '\0') return (pathname); /* If the basename is NULL, we might have a pathname like '/usr/src/'. Look for a previous slash and, if one is found, return the portion following that slash. If there's no previous slash, just return the pathname we were passed. */ else if (temp[1] == '\0') { for (x = temp - 1; x > pathname; x--) if (*x == '/') break; return ((*x == '/') ? x + 1 : pathname); } else return ++temp;}/* Compute width of STRING when displayed on screen by print_filename */static intfnwidth (string) const char *string;{ int width, pos;#if defined (HANDLE_MULTIBYTE) mbstate_t ps; int left, w; size_t clen; wchar_t wc; left = strlen (string) + 1; memset (&ps, 0, sizeof (mbstate_t));#endif width = pos = 0; while (string[pos]) { if (CTRL_CHAR (*string) || *string == RUBOUT) { width += 2; pos++; } else {#if defined (HANDLE_MULTIBYTE) clen = mbrtowc (&wc, string + pos, left - pos, &ps); if (MB_INVALIDCH (clen)) { width++; pos++; memset (&ps, 0, sizeof (mbstate_t)); } else if (MB_NULLWCH (clen)) break; else { pos += clen; w = wcwidth (wc); width += (w >= 0) ? w : 1; }#else width++; pos++;#endif } } return width;}static intfnprint (to_print) const char *to_print;{ int printed_len; const char *s;#if defined (HANDLE_MULTIBYTE) mbstate_t ps; const char *end; size_t tlen; end = to_print + strlen (to_print) + 1; memset (&ps, 0, sizeof (mbstate_t));#endif printed_len = 0; s = to_print; while (*s) { if (CTRL_CHAR (*s)) { putc ('^', rl_outstream); putc (UNCTRL (*s), rl_outstream); printed_len += 2; s++;#if defined (HANDLE_MULTIBYTE) memset (&ps, 0, sizeof (mbstate_t));#endif } else if (*s == RUBOUT) { putc ('^', rl_outstream); putc ('?', rl_outstream); printed_len += 2; s++;#if defined (HANDLE_MULTIBYTE) memset (&ps, 0, sizeof (mbstate_t));#endif } else {#if defined (HANDLE_MULTIBYTE) tlen = mbrlen (s, end - s, &ps); if (MB_INVALIDCH (tlen)) { tlen = 1; memset (&ps, 0, sizeof (mbstate_t)); } else if (MB_NULLWCH (tlen)) break; fwrite (s, 1, tlen, rl_outstream); s += tlen;#else putc (*s, rl_outstream); s++;#endif printed_len++; } } return printed_len;}/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we are using it, check for and output a single character for `special' filenames. Return the number of characters we output. */static intprint_filename (to_print, full_pathname) char *to_print, *full_pathname;{ int printed_len, extension_char, slen, tlen; char *s, c, *new_full_pathname; extension_char = 0; printed_len = fnprint (to_print);#if defined (VISIBLE_STATS) if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))#else if (rl_filename_completion_desired && _rl_complete_mark_directories)#endif { /* If to_print != full_pathname, to_print is the basename of the path passed. In this case, we try to expand the directory name before checking for the stat character. */ if (to_print != full_pathname) { /* Terminate the directory name. */ c = to_print[-1]; to_print[-1] = '\0'; /* If setting the last slash in full_pathname to a NUL results in full_pathname being the empty string, we are trying to complete files in the root directory. If we pass a null string to the bash directory completion hook, for example, it will expand it to the current directory. We just want the `/'. */ s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/"); if (rl_directory_completion_hook) (*rl_directory_completion_hook) (&s); slen = strlen (s); tlen = strlen (to_print); new_full_pathname = (char *)xmalloc (slen + tlen + 2); strcpy (new_full_pathname, s); new_full_pathname[slen] = '/'; strcpy (new_full_pathname + slen + 1, to_print);#if defined (VISIBLE_STATS) if (rl_visible_stats) extension_char = stat_char (new_full_pathname); else#endif if (path_isdir (new_full_pathname)) extension_char = '/'; free (new_full_pathname); to_print[-1] = c; } else { s = tilde_expand (full_pathname);#if defined (VISIBLE_STATS) if (rl_visible_stats) extension_char = stat_char (s); else#endif if (path_isdir (s)) extension_char = '/'; } free (s); if (extension_char) { putc (extension_char, rl_outstream); printed_len++; } } return printed_len;}static char *rl_quote_filename (s, rtype, qcp) char *s; int rtype; char *qcp;{ char *r; r = (char *)xmalloc (strlen (s) + 2); *r = *rl_completer_quote_characters; strcpy (r + 1, s); if (qcp) *qcp = *rl_completer_quote_characters; return r;}/* Find the bounds of the current word for completion purposes, and leave rl_point set to the end of the word. This function skips quoted substrings (characters between matched pairs of characters in rl_completer_quote_characters). First we try to find an unclosed quoted substring on which to do matching. If one is not found, we use the word break characters to find the boundaries of the current word. We call an application-specific function to decide whether or not a particular word break character is quoted; if that function returns a non-zero result, the character does not break a word. This function returns the opening quote character if we found an unclosed quoted substring, '\0' otherwise. FP, if non-null, is set to a value saying which (shell-like) quote characters we found (single quote, double quote, or backslash) anywhere in the string. DP, if non-null, is set to the value of the delimiter character that caused a word break. */char_rl_find_completion_word (fp, dp) int *fp, *dp;{ int scan, end, found_quote, delimiter, pass_next, isbrk; char quote_char, *brkchars; end = rl_point; found_quote = delimiter = 0; quote_char = '\0'; brkchars = 0; if (rl_completion_word_break_hook) brkchars = (*rl_completion_word_break_hook) (); if (brkchars == 0) brkchars = rl_completer_word_break_characters; if (rl_completer_quote_characters) { /* We have a list of characters which can be used in pairs to quote substrings for the completer. Try to find the start of an unclosed quoted substring. */ /* FOUND_QUOTE is set so we know what kind of quotes we found. */#if defined (HANDLE_MULTIBYTE) for (scan = pass_next = 0; scan < end; scan = ((MB_CUR_MAX == 1 || rl_byte_oriented) ? (scan + 1) : _rl_find_next_mbchar (rl_line_buffer, scan, 1, MB_FIND_ANY)))#else for (scan = pass_next = 0; scan < end; scan++)#endif { if (pass_next) { pass_next = 0; continue; } /* Shell-like semantics for single quotes -- don't allow backslash to quote anything in single quotes, especially not the closing quote. If you don't like this, take out the check on the value of quote_char. */ if (quote_char != '\'' && rl_line_buffer[scan] == '\\') { pass_next = 1; found_quote |= RL_QF_BACKSLASH; continue; } if (quote_char != '\0') { /* Ignore everything until the matching close quote char. */ if (rl_line_buffer[scan] == quote_char) { /* Found matching close. Abandon this substring. */ quote_char = '\0'; rl_point = end; } } else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan])) { /* Found start of a quoted substring. */ quote_char = rl_line_buffer[scan]; rl_point = scan + 1; /* Shell-like quoting conventions. */ if (quote_char == '\'') found_quote |= RL_QF_SINGLE_QUOTE; else if (quote_char == '"') found_quote |= RL_QF_DOUBLE_QUOTE; else found_quote |= RL_QF_OTHER_QUOTE; } } } if (rl_point == end && quote_char == '\0') { /* We didn't find an unclosed quoted substring upon which to do completion, so use the word break characters to find the substring on which to complete. */#if defined (HANDLE_MULTIBYTE) while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))#else while (--rl_point)#endif { scan = rl_line_buffer[rl_point]; if (strchr (brkchars, scan) == 0) continue; /* Call the application-specific function to tell us whether
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -