?? cplfile.c
字號:
/*....................................................................... * Return a description of the last path-completion error that occurred. * * Input: * cf CompleteFile * The path-completion resource object. * Output: * return const char * The description of the last error. */const char *_cf_last_error(CompleteFile *cf){ return cf ? cf->errmsg : "NULL CompleteFile argument";}/*....................................................................... * Lookup the home directory of the specified user, or the current user * if no name is specified, appending it to output pathname. * * Input: * cf CompleteFile * The pathname completion resource object. * user const char * The username to lookup, or "" to lookup the * current user. * Output: * return int 0 - OK. * 1 - Error. */static int cf_expand_home_dir(CompleteFile *cf, const char *user){/* * Attempt to lookup the home directory. */ const char *home_dir = _hd_lookup_home_dir(cf->home, user);/* * Failed? */ if(!home_dir) { strncpy(cf->errmsg, _hd_last_home_dir_error(cf->home), ERRLEN); cf->errmsg[ERRLEN] = '\0'; return 1; };/* * Append the home directory to the pathname string. */ if(_pn_append_to_path(cf->path, home_dir, -1, 0) == NULL) { strcpy(cf->errmsg, "Insufficient memory for home directory expansion"); return 1; }; return 0;}/*....................................................................... * Lookup and report all completions of a given username prefix. * * Input: * cf CompleteFile * The filename-completion resource object. * cpl WordCompletion * The object in which to record the completions. * prefix const char * The prefix of the usernames to lookup. * line const char * The command-line in which the username appears. * word_start int The index within line[] of the start of the * username that is being completed. * word_end int The index within line[] of the character which * follows the incomplete username. * escaped int True if the completions need to have special * characters escaped. * Output: * return int 0 - OK. * 1 - Error. */static int cf_complete_username(CompleteFile *cf, WordCompletion *cpl, const char *prefix, const char *line, int word_start, int word_end, int escaped){/* * Set up a container of anonymous arguments to be sent to the * username-lookup iterator. */ CfHomeArgs args; args.cf = cf; args.cpl = cpl; args.prefix = prefix; args.line = line; args.word_start = word_start; args.word_end = word_end; args.escaped = escaped;/* * Iterate through the list of users, recording those which start * with the specified prefix. */ if(_hd_scan_user_home_dirs(cf->home, &args, cf_homedir_callback)) { strncpy(cf->errmsg, _hd_last_home_dir_error(cf->home), ERRLEN); cf->errmsg[ERRLEN] = '\0'; return 1; }; return 0;}/*....................................................................... * The user/home-directory scanner callback function (see homedir.h) * used by cf_complete_username(). */static HOME_DIR_FN(cf_homedir_callback){/* * Get the file-completion resources from the anonymous data argument. */ CfHomeArgs *args = (CfHomeArgs *) data; WordCompletion *cpl = args->cpl; CompleteFile *cf = args->cf;/* * Get the length of the username prefix. */ int prefix_len = strlen(args->prefix);/* * Get the length of the latest user name that is to be compared to * the prefix. */ int name_len = strlen(usrnam);/* * See if the latest username starts with the prefix that we are * searching for, and record its suffix in the array of matches if so. */ if(name_len >= prefix_len && strncmp(args->prefix, usrnam, prefix_len)==0) {/* * Copy the username into the pathname work buffer, adding backslash * escapes where needed. */ if(cf_prepare_suffix(cf, usrnam+prefix_len, args->escaped)) { strncpy(errmsg, cf->errmsg, maxerr); errmsg[maxerr] = '\0'; return 1; };/* * Report the completion suffix that was copied above. */ if(cpl_add_completion(cpl, args->line, args->word_start, args->word_end, cf->buff->name, FS_DIR_SEP, FS_DIR_SEP)) { strncpy(errmsg, cpl_last_error(cpl), maxerr); errmsg[maxerr] = '\0'; return 1; }; }; return 0;}/*....................................................................... * Report possible completions of the filename in cf->path->name[]. * * Input: * cf CompleteFile * The file-completion resource object. * cpl WordCompletion * The object in which to record the completions. * line const char * The input line, as received by the callback * function. * word_start int The index within line[] of the start of the * last component of the filename that is being * completed. * word_end int The index within line[] of the character which * follows the incomplete filename. * escaped int If true, escape special characters in the * completion suffixes. * check_fn CplCheckFn * If not zero, this argument specifies a * function to call to ask whether a given * file should be included in the list * of completions. * check_data void * Anonymous data to be passed to check_fn(). * Output: * return int 0 - OK. * 1 - Error. */static int cf_complete_entry(CompleteFile *cf, WordCompletion *cpl, const char *line, int word_start, int word_end, int escaped, CplCheckFn *check_fn, void *check_data){ const char *dirpath; /* The name of the parent directory */ int start; /* The index of the start of the last filename */ /* component in the transcribed filename. */ const char *prefix; /* The filename prefix to be completed */ int prefix_len; /* The length of the filename prefix */ const char *file_name; /* The lastest filename being compared */ int waserr = 0; /* True after errors */ int terminated=0; /* True if the directory part had to be terminated *//* * Get the pathname string and its current length. */ char *pathname = cf->path->name; int pathlen = strlen(pathname);/* * Locate the start of the final component of the pathname. */ for(start=pathlen - 1; start >= 0 && strncmp(pathname + start, FS_DIR_SEP, FS_DIR_SEP_LEN) != 0; start--) ;/* * Is the parent directory the root directory? */ if(start==0 || (start < 0 && strncmp(pathname, FS_ROOT_DIR, FS_ROOT_DIR_LEN) == 0)) { dirpath = FS_ROOT_DIR; start += FS_ROOT_DIR_LEN;/* * If we found a directory separator then the part which precedes the * last component is the name of the directory to be opened. */ } else if(start > 0) {/* * The _dr_open_dir() function requires the directory name to be '\0' * terminated, so temporarily do this by overwriting the first character * of the directory separator. */ pathname[start] = '\0'; dirpath = pathname; terminated = 1;/* * We reached the start of the pathname before finding a directory * separator, so arrange to open the current working directory. */ } else { start = 0; dirpath = FS_PWD; };/* * Attempt to open the directory. */ if(_dr_open_dir(cf->dr, dirpath, NULL)) { const char *fmt = "Can't open directory: %.*s"; sprintf(cf->errmsg, fmt, ERRLEN - strlen(fmt), dirpath); return 1; };/* * If removed above, restore the directory separator and skip over it * to the start of the filename. */ if(terminated) { memcpy(pathname + start, FS_DIR_SEP, FS_DIR_SEP_LEN); start += FS_DIR_SEP_LEN; };/* * Get the filename prefix and its length. */ prefix = pathname + start; prefix_len = strlen(prefix);/* * Traverse the directory, looking for files who's prefixes match the * last component of the pathname. */ while((file_name = _dr_next_file(cf->dr)) != NULL && !waserr) { int name_len = strlen(file_name);/* * Is the latest filename a possible completion of the filename prefix? */ if(name_len >= prefix_len && strncmp(prefix, file_name, prefix_len)==0) {/* * When listing all files in a directory, don't list files that start * with '.'. This is how hidden files are denoted in UNIX. */ if(prefix_len > 0 || file_name[0] != '.') {/* * Copy the completion suffix into the work pathname cf->buff->name, * adding backslash escapes if needed. */ if(cf_prepare_suffix(cf, file_name + prefix_len, escaped)) { waserr = 1; } else {/* * We want directories to be displayed with directory suffixes, * and other fully completed filenames to be followed by spaces. * To check the type of the file, append the current suffix * to the path being completed, check the filetype, then restore * the path to its original form. */ const char *cont_suffix = ""; /* The suffix to add if fully */ /* completed. */ const char *type_suffix = ""; /* The suffix to add when listing */ if(_pn_append_to_path(cf->path, file_name + prefix_len, -1, escaped) == NULL) { strcpy(cf->errmsg, "Insufficient memory to complete filename."); return 1; };/* * Specify suffixes according to the file type. */ if(_pu_path_is_dir(cf->path->name)) { cont_suffix = FS_DIR_SEP; type_suffix = FS_DIR_SEP; } else if(!check_fn || check_fn(check_data, cf->path->name)) { cont_suffix = " "; } else { cf->path->name[pathlen] = '\0'; continue; };/* * Remove the temporarily added suffix. */ cf->path->name[pathlen] = '\0';/* * Record the latest completion. */ if(cpl_add_completion(cpl, line, word_start, word_end, cf->buff->name, type_suffix, cont_suffix)) waserr = 1; }; }; }; };/* * Close the directory. */ _dr_close_dir(cf->dr); return waserr;}/*....................................................................... * Read a username or environment variable name, stopping when a directory * separator is seen, when the end of the string is reached, or the * output buffer overflows. * * Input: * cf CompleteFile * The file-completion resource object. * type char * The capitalized name of the type of name being read. * string char * The string who's prefix contains the name. * slen int The number of characters in string[]. * nambuf char * The output name buffer. * nammax int The longest string that will fit in nambuf[], excluding * the '\0' terminator. * Output: * return char * A pointer to nambuf on success. On error NULL is * returned and a description of the error is recorded * in cf->errmsg[]. */static char *cf_read_name(CompleteFile *cf, const char *type, const char *string, int slen, char *nambuf, int nammax){ int namlen; /* The number of characters in nambuf[] */ const char *sptr; /* A pointer into string[] *//* * Work out the max number of characters that should be copied. */ int nmax = nammax < slen ? nammax : slen;/* * Get the environment variable name that follows the dollar. */ for(sptr=string,namlen=0; namlen < nmax && (slen-namlen < FS_DIR_SEP_LEN || strncmp(sptr, FS_DIR_SEP, FS_DIR_SEP_LEN) != 0); namlen++) { nambuf[namlen] = *sptr++; };/* * Did the name overflow the buffer? */ if(namlen >= nammax) { const char *fmt = "%.*s name too long"; sprintf(cf->errmsg, fmt, ERRLEN - strlen(fmt), type); return NULL; };/* * Terminate the string. */ nambuf[namlen] = '\0'; return nambuf;}/*....................................................................... * Using the work buffer cf->buff, make a suitably escaped copy of a * given completion suffix, ready to be passed to cpl_add_completion(). * * Input: * cf CompleteFile * The file-completion resource object. * suffix char * The suffix to be copied. * add_escapes int If true, escape special characters. * Output: * return int 0 - OK. * 1 - Error. */static int cf_prepare_suffix(CompleteFile *cf, const char *suffix, int add_escapes){ const char *sptr; /* A pointer into suffix[] */ int nbsl; /* The number of backslashes to add to the suffix */ int i;/* * How long is the suffix? */ int suffix_len = strlen(suffix);/* * Clear the work buffer. */ _pn_clear_path(cf->buff);/* * Count the number of backslashes that will have to be added to * escape spaces, tabs, backslashes and wildcard characters. */ nbsl = 0; if(add_escapes) { for(sptr = suffix; *sptr; sptr++) { switch(*sptr) { case ' ': case '\t': case '\\': case '*': case '?': case '[': nbsl++; break; }; }; };/* * Arrange for the output path buffer to have sufficient room for the * both the suffix and any backslashes that have to be inserted. */ if(_pn_resize_path(cf->buff, suffix_len + nbsl) == NULL) { strcpy(cf->errmsg, "Insufficient memory to complete filename"); return 1; };/* * If the suffix doesn't need any escapes, copy it directly into the * work buffer. */ if(nbsl==0) { strcpy(cf->buff->name, suffix); } else {/* * Make a copy with special characters escaped? */ if(nbsl > 0) { const char *src = suffix; char *dst = cf->buff->name; for(i=0; i<suffix_len; i++) { switch(*src) { case ' ': case '\t': case '\\': case '*': case '?': case '[': *dst++ = '\\'; }; *dst++ = *src++; }; *dst = '\0'; }; }; return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -