From 34bdc35d94351f9094f40a8b99bcc459aadede22 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Thu, 2 Jun 2005 18:41:31 +0000 Subject: [PATCH] readd tab completion of history strings, with a few minor tweaks git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2577 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 16 ++++---- src/files.c | 10 +---- src/proto.h | 13 ++++--- src/search.c | 102 ++++++++++++++++++++++++++++++++++++++++----------- src/winio.c | 36 +++++++++++++++--- 5 files changed, 129 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2efbbd4c..2319c28c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,14 +21,14 @@ CVS code - do_gotolinecolumn_void()), nano.1, and nano.texi. (DLR, suggested by PFTank) - Overhaul the history code to work more consistently, and clean - up various parts of it. Note that history tab completion has - been removed. New function history_has_changed(); changes to - load_history(), writehist(), thanks_for_all_the_fish(), - history_init(), find_node() (renamed find_history()), - update_history(), get_history_older(), get_history_newer(), - do_search(), do_replace(), nanogetstr(), and statusq(); - removal of remove_node(), insert_node(), and - get_history_completion(). (DLR) + up various parts of it. New function history_has_changed(); + changes to load_history(), writehist(), + thanks_for_all_the_fish(), history_init(), find_node() + (renamed find_history()), update_history(), + get_history_older(), get_history_newer(), + get_history_completion(), do_search(), do_replace(), + nanogetstr(), and statusq(); removal of remove_node() and + insert_node(). (DLR) - Replace all instances of strncpy() with charcpy(), since the only difference between them is that the former pads strings with nulls when they're longer than the number of characters diff --git a/src/files.c b/src/files.c index 78294072..c3d7af19 100644 --- a/src/files.c +++ b/src/files.c @@ -2915,8 +2915,6 @@ void load_history(void) * replace history) from oldest to newest. Assume the last * history entry is a blank line. */ filestruct **history = &search_history; - filestruct **historyage = &searchage; - filestruct **historybot = &searchbot; char *line = NULL; size_t buflen = 0; ssize_t read; @@ -2928,13 +2926,9 @@ void load_history(void) } if (read > 0) { unsunder(line, read); - update_history(history, historyage, historybot, - line); - } else { + update_history(history, line); + } else history = &replace_history; - historyage = &replaceage; - historybot = &replacebot; - } } fclose(hist); diff --git a/src/proto.h b/src/proto.h index c6049bf3..7efa41e2 100644 --- a/src/proto.h +++ b/src/proto.h @@ -322,6 +322,9 @@ char *histfilename(void); void load_history(void); bool writehist(FILE *hist, filestruct *histhead); void save_history(void); +#ifndef DISABLE_TABCOMP +char *get_history_completion(filestruct **h, char *s, size_t len); +#endif #endif /* Public functions in global.c. */ @@ -527,9 +530,9 @@ void do_find_bracket(void); #if !defined(NANO_SMALL) && defined(ENABLE_NANORC) bool history_has_changed(void); void history_init(void); -filestruct *find_history(filestruct *h, const char *s); -void update_history(filestruct **h, filestruct **hage, filestruct - **hbot, const char *s); +filestruct *find_history(filestruct *h_start, filestruct *h_end, const + char *s, size_t len); +void update_history(filestruct **h, const char *s); char *get_history_older(filestruct **h); char *get_history_newer(filestruct **h); #endif @@ -649,7 +652,7 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool void nanoget_repaint(const char *buf, const char *inputbuf, size_t x); int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, #if !defined(NANO_SMALL) && defined(ENABLE_NANORC) - filestruct *history_list, + filestruct **history_list, #endif const shortcut *s #ifndef DISABLE_TABCOMP @@ -658,7 +661,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, ); int statusq(bool allow_tabs, const shortcut *s, const char *curranswer, #if !defined(NANO_SMALL) && defined(ENABLE_NANORC) - filestruct *history_list, + filestruct **history_list, #endif const char *msg, ...); void statusq_abort(void); diff --git a/src/search.c b/src/search.c index 2ae9c385..66e8190f 100644 --- a/src/search.c +++ b/src/search.c @@ -165,7 +165,7 @@ int search_init(bool replacing, bool use_answer) i = statusq(FALSE, replacing ? replace_list : whereis_list, backupstring, #ifndef NANO_SMALL - search_history, + &search_history, #endif "%s%s%s%s%s%s", _("Search"), @@ -476,7 +476,7 @@ void do_search(void) /* If answer is not "", add this search string to the search history * list. */ if (answer[0] != '\0') - update_history(&search_history, &searchage, &searchbot, answer); + update_history(&search_history, answer); #endif findnextstr_wrap_reset(); @@ -905,14 +905,14 @@ void do_replace(void) * copy answer into last_search. */ if (answer[0] != '\0') { #ifndef NANO_SMALL - update_history(&search_history, &searchage, &searchbot, answer); + update_history(&search_history, answer); #endif last_search = mallocstrcpy(last_search, answer); } i = statusq(FALSE, replace_list_2, last_replace, #ifndef NANO_SMALL - replace_history, + &replace_history, #endif _("Replace with")); @@ -920,8 +920,7 @@ void do_replace(void) /* Add this replace string to the replace history list. i == 0 * means that the string is not "". */ if (i == 0) - update_history(&replace_history, &replaceage, &replacebot, - answer); + update_history(&replace_history, answer); #endif if (i != 0 && i != -2) { @@ -1140,32 +1139,42 @@ void history_init(void) replacebot = replace_history; } -/* Return the first node containing the string s in the history list, - * starting at h, or NULL if there isn't one. */ -filestruct *find_history(filestruct *h, const char *s) +/* Return the first node containing the first len characters of the + * string s in the history list, starting at h_start and ending at + * h_end, or NULL if there isn't one. */ +filestruct *find_history(filestruct *h_start, filestruct *h_end, const + char *s, size_t len) { - assert(h != NULL); + filestruct *p; - for (; h->next != NULL; h = h->next) { - if (strcmp(s, h->data) == 0) - return h; + for (p = h_start; p != h_end->next && p != NULL; p = p->next) { + if (strncmp(s, p->data, len) == 0) + return p; } return NULL; } -/* Update a history list. h should be the current position in the list, - * hage should be the top of the list, and hbot should be the bottom of - * the list. */ -void update_history(filestruct **h, filestruct **hage, filestruct - **hbot, const char *s) +/* Update a history list. h should be the current position in the + * list. */ +void update_history(filestruct **h, const char *s) { - filestruct *p; + filestruct **hage = NULL, **hbot = NULL, *p; - assert(h != NULL && hage != NULL && hbot != NULL && s != NULL); + assert(h != NULL && s != NULL); + + if (*h == search_history) { + hage = &searchage; + hbot = &searchbot; + } else if (*h == replace_history) { + hage = &replaceage; + hbot = &replacebot; + } + + assert(hage != NULL && hbot != NULL); /* If this string is already in the history, delete it. */ - p = find_history(*hage, s); + p = find_history(*hage, *hbot, s, (size_t)-1); if (p != NULL) { filestruct *foo, *bar; @@ -1239,4 +1248,55 @@ char *get_history_newer(filestruct **h) return (*h)->data; } + +#ifndef DISABLE_TABCOMP +/* Move h to the next string that's a tab completion of the string s, + * looking at only the first len characters of s, and return that + * string. If there isn't one, or if len is 0, don't move h, truncate s + * to len characters, and return s. */ +char *get_history_completion(filestruct **h, char *s, size_t len) +{ + assert(s != NULL); + + if (len > 0) { + filestruct *hage = NULL, *hbot = NULL, *p; + + assert(h != NULL); + + if (*h == search_history) { + hage = searchage; + hbot = searchbot; + } else if (*h == replace_history) { + hage = replaceage; + hbot = replacebot; + } + + assert(hage != NULL && hbot != NULL); + + /* Search the history list from the entry after the current + * position to the bottom for a match of len characters. */ + p = find_history((*h)->next, hbot, s, len); + + if (p != NULL) { + *h = p; + return (*h)->data; + } + + /* Search the history list from the top to the current position + * for a match of len characters. */ + p = find_history(hage, *h, s, len); + + if (p != NULL) { + *h = p; + return (*h)->data; + } + } + + /* If we're here, we didn't find a match, or len is 0. Truncate s + * to len characters, and return it. */ + null_at(&s, len); + + return s; +} +#endif #endif /* !NANO_SMALL && ENABLE_NANORC */ diff --git a/src/winio.c b/src/winio.c index 964f44c4..72854df1 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2431,7 +2431,7 @@ void nanoget_repaint(const char *buf, const char *inputbuf, size_t x) * statusq(). */ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, #if !defined(NANO_SMALL) && defined(ENABLE_NANORC) - filestruct *history_list, + filestruct **history_list, #endif const shortcut *s #ifndef DISABLE_TABCOMP @@ -2447,6 +2447,13 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, /* Whether we've pressed Tab. */ #endif #if !defined(NANO_SMALL) && defined(ENABLE_NANORC) +#ifndef DISABLE_TABCOMP + size_t complete_len = 0; + /* The length of the original string that we're trying to + * tab complete, if any. */ +#endif + int last_kbinput = ERR; + /* The key we pressed before the current key. */ char *history = NULL; /* The current history string. */ char *magichistory = NULL; @@ -2494,6 +2501,19 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, switch (kbinput) { case NANO_TAB_KEY: #ifndef DISABLE_TABCOMP +#if !defined(NANO_SMALL) && defined(ENABLE_NANORC) + if (history_list != NULL) { + if (last_kbinput != NANO_TAB_KEY) + complete_len = strlen(answer); + + if (complete_len > 0) { + answer = mallocstrcpy(answer, + get_history_completion(history_list, + answer, complete_len)); + statusbar_x = strlen(answer); + } + } else +#endif if (allow_tabs) answer = input_tab(answer, &statusbar_x, &tabbed, list); @@ -2506,7 +2526,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, * history list, answer isn't blank, and * magichistory isn't set, save answer in * magichistory. */ - if (history_list->next == NULL && + if ((*history_list)->next == NULL && answer[0] != '\0' && magichistory == NULL) magichistory = mallocstrcpy(NULL, answer); @@ -2514,7 +2534,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, * save it in answer. If there is no older search, * don't do anything. */ if ((history = - get_history_older(&history_list)) != NULL) { + get_history_older(history_list)) != NULL) { answer = mallocstrcpy(answer, history); statusbar_x = strlen(answer); } @@ -2535,7 +2555,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, * save it in answer. If there is no newer search, * don't do anything. */ if ((history = - get_history_newer(&history_list)) != NULL) { + get_history_newer(history_list)) != NULL) { answer = mallocstrcpy(answer, history); statusbar_x = strlen(answer); } @@ -2544,7 +2564,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, * the history list, answer is blank, and * magichistory is set, save magichistory in * answer. */ - if (history_list->next == NULL && + if ((*history_list)->next == NULL && answer[0] == '\0' && magichistory != NULL) { answer = mallocstrcpy(answer, magichistory); statusbar_x = strlen(answer); @@ -2560,6 +2580,10 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, if (finished) break; +#if !defined(NANO_SMALL) && defined(ENABLE_NANORC) && !defined(DISABLE_TABCOMP) + last_kbinput = kbinput; +#endif + nanoget_repaint(buf, answer, statusbar_x); wrefresh(bottomwin); } @@ -2588,7 +2612,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer, * interpreted. */ int statusq(bool allow_tabs, const shortcut *s, const char *curranswer, #if !defined(NANO_SMALL) && defined(ENABLE_NANORC) - filestruct *history_list, + filestruct **history_list, #endif const char *msg, ...) {