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
master
David Lawrence Ramsey 2005-06-02 18:41:31 +00:00
parent 1726050ef9
commit 34bdc35d94
5 changed files with 129 additions and 48 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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, ...)
{