📄 cplmatch.c
字号:
return strcmp(m1->completion, m2->completion);}/*....................................................................... * Sort the array of matches in order of their suffixes. * * Input: * cpl WordCompletion * The completion resource object. */static void cpl_sort_suffixes(WordCompletion *cpl){ qsort(cpl->result.matches, cpl->result.nmatch, sizeof(cpl->result.matches[0]), cpl_cmp_suffixes);}/*....................................................................... * This is a qsort() comparison function used to sort matches in order of * their suffixes. * * Input: * v1, v2 void * Pointers to the two matches to be compared. * Output: * return int -1 -> v1 < v2. * 0 -> v1 == v2 * 1 -> v1 > v2 */static int cpl_cmp_suffixes(const void *v1, const void *v2){ const CplMatch *m1 = (const CplMatch *) v1; const CplMatch *m2 = (const CplMatch *) v2; return strcmp(m1->suffix, m2->suffix);}/*....................................................................... * Find the common prefix of all of the matching completion matches, * and record a pointer to it in cpl->result.suffix. Note that this has * the side effect of sorting the matches into suffix order. * * Input: * cpl WordCompletion * The completion resource object. * Output: * return int 0 - OK. * 1 - Error. */static int cpl_common_suffix(WordCompletion *cpl){ CplMatches *result; /* The result container */ const char *first, *last; /* The first and last matching suffixes */ int length; /* The length of the common suffix *//* * Get the container of the array of matching files. */ result = &cpl->result;/* * No matching completions? */ if(result->nmatch < 1) return 0;/* * Sort th matches into suffix order. */ cpl_sort_suffixes(cpl);/* * Given that the array of matches is sorted, the first and last * suffixes are those that differ most in their prefixes, so the common * prefix of these strings is the longest common prefix of all of the * suffixes. */ first = result->matches[0].suffix; last = result->matches[result->nmatch - 1].suffix;/* * Find the point at which the first and last matching strings * first difffer. */ while(*first && *first == *last) { first++; last++; };/* * How long is the common suffix? */ length = first - result->matches[0].suffix;/* * Allocate memory to record the common suffix. */ result->suffix = _sg_alloc_string(cpl->sg, length); if(!result->suffix) { strcpy(cpl->errmsg, "Insufficient memory to record common completion suffix."); return 1; };/* * Record the common suffix. */ strncpy(result->suffix, result->matches[0].suffix, length); result->suffix[length] = '\0'; return 0;}/*....................................................................... * Discard the contents of the array of possible completion matches. * * Input: * cpl WordCompletion * The word-completion resource object. */static void cpl_clear_completions(WordCompletion *cpl){/* * Discard all of the strings. */ _clr_StringGroup(cpl->sg);/* * Record the fact that the array is now empty. */ cpl->result.nmatch = 0; cpl->result.suffix = NULL; cpl->result.cont_suffix = "";/* * Also clear the error message. */ cpl->errmsg[0] = '\0'; return;}/*....................................................................... * Given an input line and the point at which it completion is to be * attempted, return an array of possible completions. * * Input: * cpl WordCompletion * The completion resource object. * line char * The current input line. * word_end int The index of the character in line[] which * follows the end of the token that is being * completed. * data void * Anonymous 'data' to be passed to match_fn(). * match_fn CplMatchFn * The function that will identify the prefix * to be completed from the input line, and * record completion matches. * Output: * return CplMatches * The container of the array of possible * completions. The returned pointer refers * to a container owned by the parent WordCompletion * object, and its contents thus potentially * change on every call to cpl_matches(). * On error, NULL is returned, and a description * of the error can be acquired by calling * cpl_last_error(cpl). */CplMatches *cpl_complete_word(WordCompletion *cpl, const char *line, int word_end, void *data, CplMatchFn *match_fn){ int line_len; /* The total length of the input line *//* * How long is the input line? */ line_len = strlen(line);/* * Check the arguments. */ if(!cpl || !line || !match_fn || word_end < 0 || word_end > line_len) { if(cpl) strcpy(cpl->errmsg, "cpl_complete_word: Invalid arguments."); return NULL; };/* * Clear the return container. */ cpl_clear_completions(cpl);/* * Have the matching function record possible completion matches in * cpl->result.matches. */ if(match_fn(cpl, data, line, word_end)) { if(cpl->errmsg[0] == '\0') strcpy(cpl->errmsg, "Error completing word."); return NULL; };/* * Record a copy of the common initial part of all of the prefixes * in cpl->result.common. */ if(cpl_common_suffix(cpl)) return NULL;/* * Sort the matches into lexicographic order. */ cpl_sort_matches(cpl);/* * Discard any duplicate matches. */ cpl_zap_duplicates(cpl);/* * If there is more than one match, discard the continuation suffix. */ if(cpl->result.nmatch > 1) cpl->result.cont_suffix = "";/* * Return the array of matches. */ return &cpl->result;}/*....................................................................... * Print out an array of matching completions. * * Input: * result CplMatches * The container of the sorted array of * completions. * fp FILE * The output stream to write to. * term_width int The width of the terminal. * Output: * return int 0 - OK. * 1 - Error. */int cpl_list_completions(CplMatches *result, FILE *fp, int term_width){ int maxlen; /* The length of the longest matching string */ int width; /* The width of a column */ int ncol; /* The number of columns to list */ int nrow; /* The number of rows needed to list all of the matches */ int row,col; /* The row and column being written to */ int i; int newline, onewline; /* Flags if the prev/curr string ends on '\n' *//* * Check the arguments. */ if(!result || !fp) { fprintf(stderr, "cpl_list_completions: NULL argument(s).\n"); return 1; };/* * Not enough space to list anything? */ if(term_width < 1) return 0;/* * Work out the maximum length of the matching strings. */ maxlen = 0; for(i=0; i<result->nmatch; i++) { CplMatch *match = result->matches + i; int len = strlen(match->completion) + strlen(match->type_suffix); if(len > maxlen) maxlen = len; };/* * Nothing to list? */ if(maxlen == 0) return 0;/* * Split the available terminal width into columns of maxlen + 2 characters. */ width = maxlen + 2; ncol = term_width / width;/* * If the column width is greater than the terminal width, the matches will * just have to overlap onto the next line. */ if(ncol < 1) ncol = 1;/* * How many rows will be needed? */ nrow = (result->nmatch + ncol - 1) / ncol;/* * Print the matches out in ncol columns, sorted in row order within each * column. */ onewline = 1; newline = 1; for(row=0; row < nrow; row++) { for(col=0; col < ncol; col++) { int m = col*nrow + row; onewline = newline; newline = 0; if(m < result->nmatch) { CplMatch *match = result->matches + m; /* Compute if the result string ends on '\n' */ do { int len = strlen(match->type_suffix); if (len) { if (match->type_suffix[len-1] == '\n') newline = 1; break; } len = strlen(match->completion); if (len) { if (match->type_suffix[len-1] == '\n') newline = 1; break; } } while (0); if(fprintf(fp, "%s%-*s%s", match->completion, (int) (((!onewline) && ncol > 1) ? maxlen - strlen(match->completion):0), match->type_suffix, newline ? "" : col<ncol-1 ? " " : "\r\n") < 0) return 1; } else { if(!onewline && fprintf(fp, "\r\n") < 0) return 1; newline = 1; break; }; }; }; return 0;}/*....................................................................... * Return a description of the string-completion error that occurred. * * Input: * cpl WordCompletion * The string-completion resource object. * Output: * return const char * The description of the last error.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -