static unsigned char _tabComplete(EditLine* elstate, int ch) { UNUSED(ch); const LineInfo* li = el_line(elstate); if (!li->buffer[0]) { return CC_ERROR; } const char* commandPtr; size_t cmd = 0, len = 0; const char* name = 0; for (commandPtr = li->buffer; commandPtr <= li->cursor; ++commandPtr, ++len) { for (; (name = _debuggerCommands[cmd].name); ++cmd) { int cmp = strncasecmp(name, li->buffer, len); if (cmp > 0) { return CC_ERROR; } if (cmp == 0) { break; } } } if (!name) { return CC_ERROR; } if (_debuggerCommands[cmd + 1].name && strlen(_debuggerCommands[cmd + 1].name) >= len - 1 && name[len - 2] == _debuggerCommands[cmd + 1].name[len - 2]) { --len; const char* next = 0; int i; for (i = cmd + 1; _debuggerCommands[i].name; ++i) { if (strncasecmp(name, _debuggerCommands[i].name, len)) { break; } next = _debuggerCommands[i].name; } if (!next) { return CC_ERROR; } for (; name[len]; ++len) { if (name[len] != next[len]) { break; } char out[2] = { name[len], '\0' }; el_insertstr(elstate, out); } return CC_REDISPLAY; } name += len - 1; el_insertstr(elstate, name); el_insertstr(elstate, " "); return CC_REDISPLAY; }
/* * Determine if complete is ambiguous. If unique, insert. * If no choices, error. If unambiguous prefix, insert that. * Otherwise, list choices. words is assumed to be filtered * to only contain possible choices. * Args: * word word which started the match * list list by default * words stringlist containing possible matches */ static unsigned char complete_ambiguous(char *word, int list, StringList *words) { char insertstr[MAXPATHLEN * 2]; char *lastmatch; int i, j; size_t matchlen, wordlen; wordlen = strlen(word); if (words->sl_cur == 0) return (CC_ERROR); /* no choices available */ if (words->sl_cur == 1) { /* only once choice available */ char *p = words->sl_str[0] + wordlen; ftpvis(insertstr, sizeof(insertstr), p, strlen(p)); if (el_insertstr(el, insertstr) == -1) return (CC_ERROR); else return (CC_REFRESH); } if (!list) { matchlen = 0; lastmatch = words->sl_str[0]; matchlen = strlen(lastmatch); for (i = 1 ; i < words->sl_cur ; i++) { for (j = wordlen ; j < strlen(words->sl_str[i]); j++) if (lastmatch[j] != words->sl_str[i][j]) break; if (j < matchlen) matchlen = j; } if (matchlen > wordlen) { ftpvis(insertstr, sizeof(insertstr), lastmatch + wordlen, matchlen - wordlen); if (el_insertstr(el, insertstr) == -1) return (CC_ERROR); else /* * XXX: really want CC_REFRESH_BEEP */ return (CC_REFRESH); } } putc('\n', ttyout); qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); list_vertical(words); return (CC_REDISPLAY); }
/* * Determine if complete is ambiguous. If unique, insert. * If no choices, error. If unambiguous prefix, insert that. * Otherwise, list choices. words is assumed to be filtered * to only contain possible choices. * Args: * word word which started the match * dolist list by default * words stringlist containing possible matches * Returns a result as per el_set(EL_ADDFN, ...) */ static unsigned char complete_ambiguous(EditLine *el, char *word, int dolist, StringList *words) { char insertstr[MAXPATHLEN]; char *lastmatch, *p; size_t i, j, matchlen, wordlen; wordlen = strlen(word); if (words->sl_cur == 0) return CC_ERROR; /* no choices available */ if (words->sl_cur == 1) { /* only once choice available */ p = words->sl_str[0] + wordlen; if (*p == '\0') /* at end of word? */ return CC_REFRESH; ftpvis(insertstr, sizeof(insertstr), p, strlen(p)); if (el_insertstr(el, insertstr) == -1) return CC_ERROR; else return CC_REFRESH; } if (!dolist) { matchlen = 0; lastmatch = words->sl_str[0]; matchlen = strlen(lastmatch); for (i = 1; i < words->sl_cur; i++) { for (j = wordlen; j < strlen(words->sl_str[i]); j++) if (lastmatch[j] != words->sl_str[i][j]) break; if (j < matchlen) matchlen = j; } if (matchlen >= wordlen) { ftpvis(insertstr, sizeof(insertstr), lastmatch + wordlen, matchlen - wordlen); if (el_insertstr(el, insertstr) == -1) return CC_ERROR; else return CC_REFRESH_BEEP; } } (void)putc('\n', ttyout); qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); list_vertical(words); return CC_REDISPLAY; }
static unsigned char complete(EditLine *el, int ch) { DIR *dd = opendir("."); struct dirent *dp; const char* ptr; const LineInfo *lf = el_line(el); int len; int res = CC_ERROR; /* * Find the last word */ for (ptr = lf->cursor - 1; !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--) continue; len = lf->cursor - ++ptr; for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { if (len > strlen(dp->d_name)) continue; if (strncmp(dp->d_name, ptr, len) == 0) { if (el_insertstr(el, &dp->d_name[len]) == -1) res = CC_ERROR; else res = CC_REFRESH; break; } } closedir(dd); return res; }
/* * Complete an option */ static unsigned char complete_option(char *word, int list) { struct option *o; StringList *words; size_t wordlen; unsigned char rv; words = ftp_sl_init(); wordlen = strlen(word); for (o = optiontab; o->name != NULL; o++) { if (wordlen > strlen(o->name)) continue; if (strncmp(word, o->name, wordlen) == 0) ftp_sl_add(words, ftp_strdup(o->name)); } rv = complete_ambiguous(word, list, words); if (rv == CC_REFRESH) { if (el_insertstr(el, " ") == -1) rv = CC_ERROR; } sl_free(words, 1); return (rv); }
/* * Complete a command */ static unsigned char complete_command(char *word, int list) { struct cmd *c; StringList *words; size_t wordlen; unsigned char rv; words = ftp_sl_init(); wordlen = strlen(word); for (c = cmdtab; c->c_name != NULL; c++) { if (wordlen > strlen(c->c_name)) continue; if (strncmp(word, c->c_name, wordlen) == 0) ftp_sl_add(words, ftp_strdup(c->c_name)); } rv = complete_ambiguous(word, list, words); if (rv == CC_REFRESH) { if (el_insertstr(el, " ") == -1) rv = CC_ERROR; } sl_free(words, 1); return (rv); }
/* * Complete a mail command. */ static unsigned char complete_command(EditLine *el, char *word, int dolist) { const struct cmd *c; StringList *words; size_t wordlen; unsigned char rv; words = mail_sl_init(); wordlen = strlen(word); for (c = cmdtab; c->c_name != NULL; c++) { if (wordlen > strlen(c->c_name)) continue; if (strncmp(word, c->c_name, wordlen) == 0) mail_sl_add(words, __UNCONST(c->c_name)); } rv = complete_ambiguous(el, word, dolist, words); if (rv == CC_REFRESH) { if (el_insertstr(el, " ") == -1) rv = CC_ERROR; } sl_free(words, 0); return rv; }
static PyObject * insert_text(EditLineObject *self, PyObject *string) { PyObject *encoded = encode(string); pel_note(__FUNCTION__); if (encoded == NULL) { return NULL; } el_insertstr(self->el, PyBytes_AS_STRING(encoded)); Py_DECREF(encoded); Py_RETURN_NONE; }
/* * Complete a local executable */ static unsigned char complete_executable(EditLine *el, char *word, int dolist) { StringList *words; char dir[ MAXPATHLEN ]; char *fname; unsigned char rv; size_t len; int error; if ((fname = strrchr(word, '/')) == NULL) { dir[0] = '\0'; /* walk the path */ fname = word; } else { if (fname == word) { dir[0] = '/'; dir[1] = '\0'; } else { len = fname - word; (void)strncpy(dir, word, len); dir[fname - word] = '\0'; } fname++; } words = sl_init(); if (*dir == '\0') { /* walk path */ char *env; char *path; env = getenv("PATH"); len = strlen(env); path = salloc(len + 1); (void)strcpy(path, env); error = find_execs(word, path, words); } else { /* check specified dir only */ error = find_execs(word, dir, words); } if (error != 0) return CC_ERROR; rv = complete_ambiguous(el, fname, dolist, words); if (rv == CC_REFRESH) { if (el_insertstr(el, " ") == -1) rv = CC_ERROR; } sl_free(words, 1); return rv; }
static unsigned char complete_alias(EditLine *el, char *word, int dolist) { struct grouphead *gh; const char **ap; const char **p; int h; int s; size_t len = strlen(word); StringList *words; unsigned char rv; words = sl_init(); /* allocate space for alias table */ s = 1; for (h = 0; h < HSHSIZE; h++) for (gh = groups[h]; gh != NULL; gh = gh->g_link) s++; ap = salloc(s * sizeof(*ap)); /* save pointers */ p = ap; for (h = 0; h < HSHSIZE; h++) for (gh = groups[h]; gh != NULL; gh = gh->g_link) *p++ = gh->g_name; *p = NULL; sort(ap); for (p = ap; *p != NULL; p++) if (len == 0 || strncmp(*p, word, len) == 0) mail_sl_add(words, estrdup(*p)); rv = complete_ambiguous(el, word, dolist, words); if (rv == CC_REFRESH) { if (el_insertstr(el, " ") == -1) rv = CC_ERROR; } sl_free(words, 1); return rv; }
static char *cli_complete(EditLine *el, int ch) { int len=0; char *ptr; int nb_matches; char **matches; char wipped; char temp_buffer[2]; int retval = CC_ERROR; int maxlen=0, match_len; LineInfo *lf = (LineInfo *)el_line(el); wipped = *(char*)lf->cursor; *(char *)lf->cursor = '\0'; ptr = (char *)lf->cursor; if (ptr) { while (ptr > lf->buffer) { if (isspace(*ptr)) { ptr++; break; } ptr--; } } len = lf->cursor - ptr; matches = acc_cli_completion_matches((char *)lf->buffer, ptr); if (matches) { /* Set edit line to the content at idx=0 */ if (matches[0][0] != '\0') { if(strcmp(matches[0],"debug")) { el_deletestr(el, (int) len); el_insertstr(el, matches[0]); } retval = CC_REFRESH; } /* Count number of items; determine maximum word length */ for (nb_matches=1; matches[nb_matches]; nb_matches++) { match_len = strlen(matches[nb_matches]); if (match_len > maxlen) maxlen = match_len; } /* The entry at idx=0 doesn't count */ nb_matches--; if (nb_matches == 0) { /* Unlikely... */ el_insertstr(el," "); retval = CC_REFRESH; } else if (nb_matches == 1) { /* Found an exact match */ if(lf->cursor != lf->lastchar) { lf->cursor++; el_deletestr(el, 1); snprintf(temp_buffer,2,"%c",wipped); el_insertstr(el,temp_buffer); } else { el_insertstr(el, " "); } retval = CC_REFRESH; } else { if(lf->cursor != lf->lastchar) { lf->cursor++; el_deletestr(el, 1); snprintf(temp_buffer,2,"%c",wipped); el_insertstr(el,temp_buffer); } /* Print possible matches, skipping idx=0 */ fprintf(stdout, "\n"); acc_cli_display_match_list(matches+1, nb_matches, maxlen); retval = CC_REDISPLAY; } for (nb_matches=0; matches[nb_matches]; nb_matches++) { free(matches[nb_matches]); } free(matches); } return (char *)(long)retval; }
/* * Complete the word at or before point, * 'what_to_do' says what to do with the completion. * \t means do standard completion. * `?' means list the possible completions. * `*' means insert all of the possible completions. * `!' means to do standard completion, and list all possible completions if * there is more than one. * * Note: '*' support is not implemented * '!' could never be invoked */ int fn_complete(EditLine *el, char *(*complet_func)(const char *, int), char **(*attempted_completion_function)(const char *, int, int), const char *word_break, const char *special_prefixes, const char *(*app_func)(const char *), size_t query_items, int *completion_type, int *over, int *point, int *end, const char *(*find_word_start_func)(const char *, const char *), char *(*dequoting_func)(const char *), char *(*quoting_func)(const char *)) { const LineInfo *li; char *temp; char *dequoted_temp; char **matches; const char *ctemp; size_t len; int what_to_do = '\t'; int retval = CC_NORM; if (el->el_state.lastcmd == el->el_state.thiscmd) what_to_do = '?'; /* readline's rl_complete() has to be told what we did... */ if (completion_type != NULL) *completion_type = what_to_do; if (!complet_func) complet_func = fn_filename_completion_function; if (!app_func) app_func = append_char_function; /* We now look backwards for the start of a filename/variable word */ li = el_line(el); if (find_word_start_func) ctemp = find_word_start_func(li->buffer, li->cursor); else { ctemp = li->cursor; while (ctemp > li->buffer && !strchr(word_break, ctemp[-1]) && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) ) ctemp--; } len = li->cursor - ctemp; #if defined(__SSP__) || defined(__SSP_ALL__) temp = malloc(sizeof(*temp) * (len + 1)); if (temp == NULL) return retval; #else temp = alloca(sizeof(*temp) * (len + 1)); #endif (void)strncpy(temp, ctemp, len); temp[len] = '\0'; if (dequoting_func) { dequoted_temp = dequoting_func(temp); if (dequoted_temp == NULL) return retval; } else dequoted_temp = NULL; /* these can be used by function called in completion_matches() */ /* or (*attempted_completion_function)() */ if (point != 0) *point = (int)(li->cursor - li->buffer); if (end != NULL) *end = (int)(li->lastchar - li->buffer); if (attempted_completion_function) { int cur_off = (int)(li->cursor - li->buffer); matches = (*attempted_completion_function) (dequoted_temp ? dequoted_temp : temp, (int)(cur_off - len), cur_off); } else matches = 0; if (!attempted_completion_function || (over != NULL && !*over && !matches)) matches = completion_matches(dequoted_temp ? dequoted_temp : temp, complet_func); if (over != NULL) *over = 0; if (matches) { int i; size_t matches_num, maxlen, match_len, match_display=1; retval = CC_REFRESH; /* * Only replace the completed string with common part of * possible matches if there is possible completion. */ if (matches[0][0] != '\0') { char *quoted_match; if (quoting_func) { quoted_match = quoting_func(matches[0]); if (quoted_match == NULL) goto free_matches; } else quoted_match = NULL; el_deletestr(el, (int) len); el_insertstr(el, quoted_match ? quoted_match : matches[0]); free(quoted_match); } if (what_to_do == '?') goto display_matches; if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { /* * We found exact match. Add a space after * it, unless we do filename completion and the * object is a directory. */ el_insertstr(el, (*app_func)(matches[0])); } else if (what_to_do == '!') { display_matches: /* * More than one match and requested to list possible * matches. */ for(i = 1, maxlen = 0; matches[i]; i++) { match_len = strlen(matches[i]); if (match_len > maxlen) maxlen = match_len; } matches_num = i - 1; /* newline to get on next line from command line */ (void)fprintf(el->el_outfile, "\n"); /* * If there are too many items, ask user for display * confirmation. */ if (matches_num > query_items) { (void)fprintf(el->el_outfile, "Display all %zu possibilities? (y or n) ", matches_num); (void)fflush(el->el_outfile); if (getc(stdin) != 'y') match_display = 0; (void)fprintf(el->el_outfile, "\n"); } if (match_display) fn_display_match_list(el, matches, matches_num, maxlen); retval = CC_REDISPLAY; } else if (matches[0][0]) { /* * There was some common match, but the name was * not complete enough. Next tab will print possible * completions. */ el_beep(el); } else { /* lcd is not a valid object - further specification */ /* is needed */ el_beep(el); retval = CC_NORM; } free_matches: /* free elements of array and the array itself */ for (i = 0; matches[i]; i++) free(matches[i]); free(matches); matches = NULL; } free(dequoted_temp); #if defined(__SSP__) || defined(__SSP_ALL__) free(temp); #endif return retval; }
/* * Complete a local file */ static unsigned char complete_local(char *word, int list) { StringList *words; char dir[MAXPATHLEN]; char *file; DIR *dd; struct dirent *dp; unsigned char rv; size_t len; if ((file = strrchr(word, '/')) == NULL) { dir[0] = '.'; dir[1] = '\0'; file = word; } else { if (file == word) { dir[0] = '/'; dir[1] = '\0'; } else (void)strlcpy(dir, word, file - word + 1); file++; } if (dir[0] == '~') { char *p; if ((p = globulize(dir)) == NULL) return (CC_ERROR); (void)strlcpy(dir, p, sizeof(dir)); free(p); } if ((dd = opendir(dir)) == NULL) return (CC_ERROR); words = ftp_sl_init(); len = strlen(file); for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; #if defined(DIRENT_MISSING_D_NAMLEN) if (len > strlen(dp->d_name)) continue; #else if (len > dp->d_namlen) continue; #endif if (strncmp(file, dp->d_name, len) == 0) { char *tcp; tcp = ftp_strdup(dp->d_name); ftp_sl_add(words, tcp); } } closedir(dd); rv = complete_ambiguous(file, list, words); if (rv == CC_REFRESH) { struct stat sb; char path[MAXPATHLEN]; (void)strlcpy(path, dir, sizeof(path)); (void)strlcat(path, "/", sizeof(path)); (void)strlcat(path, words->sl_str[0], sizeof(path)); if (stat(path, &sb) >= 0) { char suffix[2] = " "; if (S_ISDIR(sb.st_mode)) suffix[0] = '/'; if (el_insertstr(el, suffix) == -1) rv = CC_ERROR; } } sl_free(words, 1); return (rv); }
static unsigned char esl_console_complete(const char *buffer, const char *cursor) { char cmd_str[2048] = ""; unsigned char ret = CC_REDISPLAY; char *dup = strdup(buffer); char *buf = dup; int pos = 0, sc = 0; char *p; if (!esl_strlen_zero(cursor) && !esl_strlen_zero(buffer)) { pos = (int)(cursor - buffer); } if (pos > 0) { *(buf + pos) = '\0'; } if ((p = strchr(buf, '\r')) || (p = strchr(buf, '\n'))) { *p = '\0'; } while (*buf == ' ') { buf++; sc++; } #ifdef HAVE_EDITLINE if (!*buf && sc) { el_deletestr(el, sc); } #endif sc = 0; p = end_of_p(buf); while(p >= buf && *p == ' ') { sc++; p--; } #ifdef HAVE_EDITLINE if (sc > 1) { el_deletestr(el, sc - 1); *(p + 2) = '\0'; } #endif if (*cursor) { snprintf(cmd_str, sizeof(cmd_str), "api console_complete c=%ld;%s\n\n", (long)pos, buf); } else { snprintf(cmd_str, sizeof(cmd_str), "api console_complete %s\n\n", buf); } esl_send_recv(global_handle, cmd_str); if (global_handle->last_sr_event && global_handle->last_sr_event->body) { char *r = global_handle->last_sr_event->body; char *w, *p1; if (r) { if ((w = strstr(r, "\n\nwrite="))) { int len = 0; *w = '\0'; w += 8; len = atoi(w); if ((p1= strchr(w, ':'))) { w = p1+ 1; } printf("%s\n\n\n", r); #ifdef HAVE_EDITLINE el_deletestr(el, len); el_insertstr(el, w); #else #ifdef _MSC_VER console_bufferInput(0, len, (char*)buffer, DELETE_REFRESH_OP); console_bufferInput(w, (int)strlen(w), (char*)buffer, 0); #endif #endif } else { printf("%s\n", r); #ifdef _MSC_VER console_bufferInput(0, 0, (char*)buffer, DELETE_REFRESH_OP); #endif } } fflush(stdout); } esl_safe_free(dup); return ret; }