📄 complete.c
字号:
/***** History and file completion functions for editline library.*/#include "editline.h"#ifdef OS2#undef __MSDOS__#endif#if (defined(__MSDOS__) && !defined(DJD)) || defined(WIN32)#define FINDFIRSTSIZE_T FindMatches ( char *path , char ***avp );#elseSIZE_T FindMatches(const char *dir, const char *file, char ***avp) ;#endifstatic int SplitPath ( char *path , char **dirpart , char **filepart );static int compare (const void *p1, const void *p2);#ifdef NEED_STRDUP/*** Return an allocated copy of a string.*/char *strdup( const char *p){ char *new; if ((new = NEW(char, strlen(p) + 1)) != NULL) (void)strcpy(new, p); return new;}#endif /* defined(NEED_STRDUP) *//*** strcmp-like sorting predicate for qsort.*/static intcompare(const void *p1, const void *p2){#if 0 why all this ugliness? const char **v1; const char **v2; v1 = (const char **)p1; v2 = (const char **)p2; return strcmp(*v1, *v2);#endif return strcmp( p1, p2);}#ifdef FINDFIRST SIZE_T FindMatches(char *path, char ***avp){ char **av; char **new; char *p; SIZE_T ac; int i=0 ; #ifdef WIN32 struct _finddata_t merv; long filegrouphandle;#else struct ffblk merv ;#endif av = NULL; ac = 0; p = path ; while(*p) p++, i++ ; /* find proper wild card to append */ if( i > 4) i = 4 ; if( i==0 ) i = 1 ; else p-- ; if( *p != '*') strcat(path, "*") ; for( ; i > 0 ; i-- ){ if( *p == '.' ) i = -1 ; else if ( i == 1 ) strcat(path, ".*") ; else p-- ; }#ifdef WIN32 if((filegrouphandle = _findfirst( (char *) path, &merv)) != 0){ p = merv.name;#else if(!findfirst( (char *) path, &merv, 0 )){ p = merv.ff_name ;#endif strlwr( p ) ; if ((new = NEW(char*, ac + MEM_INC)) == NULL) goto myend ; *avp = new; av = new ; if ((av[ac] = strdup(p)) == NULL) { DISPOSE(av); goto myend ; } ac++;#ifdef WIN32 while( !_findnext( filegrouphandle, &merv ) ){ p = merv.name;#else while( !findnext( &merv )){ p = merv.ff_name ;#endif strlwr(p); if ((ac % MEM_INC) == 0) { /* allocate bigger array */ if ((new = NEW(char*, ac + MEM_INC)) == NULL) goto myend ; if (ac) { COPYFROMTO(new, av, ac * sizeof (char **)); DISPOSE(av); } *avp = new; av = new ; } if ((av[ac] = strdup(p)) == NULL) goto myend ; ac++; } }myend:#ifdef WIN32 _findclose (filegrouphandle);#endif if (ac) qsort( av, ac, sizeof (char **), compare ); return ac;}#else /* POSIX DIRENT *//*** Fill in *avp with an array of names that match file, up to its length.** Ignore . and .. .*/SIZE_T FindMatches(const char *dir, const char *file, char ***avp){ char **av; char **new; char *p; DIR *dp; DIRENTRY *ep; SIZE_T ac; SIZE_T len; if ((dp = opendir(dir)) == NULL) return 0; av = NULL; ac = 0; len = strlen(file); while ((ep = readdir(dp)) != NULL) { p = ep->d_name; if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0'))) continue; if (len && strncmp(p, file, len) != 0) continue; if ((ac % MEM_INC) == 0) { if ((new = NEW(char*, ac + MEM_INC)) == NULL) break; if (ac) { COPYFROMTO(new, av, ac * sizeof (char **)); DISPOSE(av); } *avp = av = new; } if ((av[ac] = strdup(p)) == NULL) { if (ac == 0) DISPOSE(av); break; } ac++; } /* Clean up and return. */ (void)closedir(dp); if (ac) qsort(av, ac, sizeof (char **), compare); return ac;}#endif/*** Split a pathname into allocated directory and trailing filename parts.*/static intSplitPath( char *path, char **dirpart, char **filepart ){ static char DOT[] = "."; char *dpart; char *fpart; if ((fpart = strrchr(path, SEPCH )) == NULL) { if ((dpart = strdup(DOT)) == NULL) return -1; if ((fpart = strdup(path)) == NULL) { DISPOSE(dpart); return -1; } } else { if ((dpart = strdup(path)) == NULL) return -1; dpart[fpart - path] = '\0'; if ((fpart = strdup(++fpart)) == NULL) { DISPOSE(dpart); return -1; } } *dirpart = dpart; *filepart = fpart; return 0;}/*** Attempt to complete the pathname, returning an allocated copy.** Fill in *unique if we completed it, or set it to 0 if ambiguous.*/char *rl_complete( char *pathname, int *unique){ char **av; char *dir; char *file; char *new; char *p; SIZE_T ac; SIZE_T end; SIZE_T i; SIZE_T j; SIZE_T len; if (SplitPath(pathname, &dir, &file) < 0) return NULL;#ifndef FINDFIRST if ((ac = FindMatches(dir, file, &av)) == 0) #else if ((ac = FindMatches(pathname, &av)) == 0 ) #endif { DISPOSE(dir); DISPOSE(file); return NULL; } p = NULL; len = strlen(file); if (ac == 1) { /* Exactly one match -- finish it off. */ *unique = 1; j = ( strlen(av[0]) - len ) + 1; if ((p = NEW(char, j + 1)) != NULL) { COPYFROMTO(p, av[0] + len, j); if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) { (void)strcpy(new, dir); (void)strcat(new, "/"); (void)strcat(new, av[0]); rl_add_slash(new, p); DISPOSE(new); } } } else { *unique = 0; if (len) { /* Find largest matching substring. */ for (i = len, end = strlen(av[0]); i < end; i++) for (j = 1; j < ac; j++) if (av[0][i] != av[j][i]) goto breakout; breakout: if (i > len) { j = i - len + 1; if ((p = NEW(char, j)) != NULL) { COPYFROMTO(p, av[0] + len, j); p[j - 1] = '\0'; } } } } /* Clean up and return. */ DISPOSE(dir); DISPOSE(file); for (i = 0; i < ac; i++) DISPOSE(av[i]); DISPOSE(av); return p;}/*** Return all possible completions.*/intrl_list_possib(char *pathname, char ***avp){ int ac;#ifndef FINDFIRST char *dir; char *file; if (SplitPath(pathname, &dir, &file) < 0) return 0; ac = FindMatches(dir, file, avp); DISPOSE(dir); DISPOSE(file);#else ac = FindMatches(pathname, avp);#endif return ac;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -