📄 complete.c
字号:
return '?'; else if (_rl_complete_show_all) return '!'; else if (_rl_complete_show_unmodified) return '@'; else return TAB;}/************************************//* *//* Completion utility functions *//* *//************************************//* Reset readline state on a signal or other event. */void_rl_reset_completion_state (){ rl_completion_found_quote = 0; rl_completion_quote_character = 0;}/* Set default values for readline word completion. These are the variables that application completion functions can change or inspect. */static voidset_completion_defaults (what_to_do) int what_to_do;{ /* Only the completion entry function can change these. */ rl_filename_completion_desired = 0; rl_filename_quoting_desired = 1; rl_completion_type = what_to_do; rl_completion_suppress_append = rl_completion_suppress_quote = 0; rl_completion_append_character = ' '; /* The completion entry function may optionally change this. */ rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;}/* The user must press "y" or "n". Non-zero return means "y" pressed. */static intget_y_or_n (for_pager) int for_pager;{ int c; /* For now, disable pager in callback mode, until we later convert to state driven functions. Have to wait until next major version to add new state definition, since it will change value of RL_STATE_DONE. */#if defined (READLINE_CALLBACKS) if (RL_ISSTATE (RL_STATE_CALLBACK)) return 1;#endif for (;;) { RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); if (c == 'y' || c == 'Y' || c == ' ') return (1); if (c == 'n' || c == 'N' || c == RUBOUT) return (0); if (c == ABORT_CHAR || c < 0) _rl_abort_internal (); if (for_pager && (c == NEWLINE || c == RETURN)) return (2); if (for_pager && (c == 'q' || c == 'Q')) return (0); rl_ding (); }}static int_rl_internal_pager (lines) 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; /* Short-circuit a //server on cygwin, since that will always behave as a directory. */#if __CYGWIN__ if (filename[0] == '/' && filename[1] == '/' && strchr (filename+2, '/') == 0) return '/';#endif#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[pos]) || string[pos] == 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;}#define ELLIPSIS_LEN 3static intfnprint (to_print, prefix_bytes) const char *to_print; int prefix_bytes;{ int printed_len, w; const char *s;#if defined (HANDLE_MULTIBYTE) mbstate_t ps; const char *end; size_t tlen; int width; wchar_t wc; end = to_print + strlen (to_print) + 1; memset (&ps, 0, sizeof (mbstate_t));#endif printed_len = 0; /* Don't print only the ellipsis if the common prefix is one of the possible completions */ if (to_print[prefix_bytes] == '\0') prefix_bytes = 0; if (prefix_bytes) { char ellipsis; ellipsis = (to_print[prefix_bytes] == '.') ? '_' : '.'; for (w = 0; w < ELLIPSIS_LEN; w++) putc (ellipsis, rl_outstream); printed_len = ELLIPSIS_LEN; } s = to_print + prefix_bytes; 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 = mbrtowc (&wc, s, end - s, &ps); if (MB_INVALIDCH (tlen)) { tlen = 1; width = 1; memset (&ps, 0, sizeof (mbstate_t)); } else if (MB_NULLWCH (tlen)) break; else { w = wcwidth (wc); width = (w >= 0) ? w : 1; } fwrite (s, 1, tlen, rl_outstream); s += tlen; printed_len += width;#else putc (*s, rl_outstream); s++; printed_len++;#endif } } 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, prefix_bytes) char *to_print, *full_pathname; int prefix_bytes;{ int printed_len, extension_char, slen, tlen; char *s, c, *new_full_pathname, *dn; extension_char = 0; printed_len = fnprint (to_print, prefix_bytes);#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 `/'. */ if (full_pathname == 0 || *full_pathname == 0) dn = "/"; else if (full_pathname[0] != '/') dn = full_pathname; else if (full_pathname[1] == 0) dn = "//"; /* restore trailing slash to `//' */ else if (full_pathname[1] == '/' && full_pathname[2] == 0) dn = "/"; /* don't turn /// into // */ else dn = full_pathname; s = tilde_expand (dn); 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); if (s[slen - 1] == '/') slen--; else new_full_pathname[slen] = '/'; 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 = '/'; xfree (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 = '/'; } xfree (s); if (extension_char) { putc (extension_char, rl_outstream);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -