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-d3aeb78583b8master
parent
1726050ef9
commit
34bdc35d94
16
ChangeLog
16
ChangeLog
|
@ -21,14 +21,14 @@ CVS code -
|
||||||
do_gotolinecolumn_void()), nano.1, and nano.texi. (DLR,
|
do_gotolinecolumn_void()), nano.1, and nano.texi. (DLR,
|
||||||
suggested by PFTank)
|
suggested by PFTank)
|
||||||
- Overhaul the history code to work more consistently, and clean
|
- Overhaul the history code to work more consistently, and clean
|
||||||
up various parts of it. Note that history tab completion has
|
up various parts of it. New function history_has_changed();
|
||||||
been removed. New function history_has_changed(); changes to
|
changes to load_history(), writehist(),
|
||||||
load_history(), writehist(), thanks_for_all_the_fish(),
|
thanks_for_all_the_fish(), history_init(), find_node()
|
||||||
history_init(), find_node() (renamed find_history()),
|
(renamed find_history()), update_history(),
|
||||||
update_history(), get_history_older(), get_history_newer(),
|
get_history_older(), get_history_newer(),
|
||||||
do_search(), do_replace(), nanogetstr(), and statusq();
|
get_history_completion(), do_search(), do_replace(),
|
||||||
removal of remove_node(), insert_node(), and
|
nanogetstr(), and statusq(); removal of remove_node() and
|
||||||
get_history_completion(). (DLR)
|
insert_node(). (DLR)
|
||||||
- Replace all instances of strncpy() with charcpy(), since the
|
- Replace all instances of strncpy() with charcpy(), since the
|
||||||
only difference between them is that the former pads strings
|
only difference between them is that the former pads strings
|
||||||
with nulls when they're longer than the number of characters
|
with nulls when they're longer than the number of characters
|
||||||
|
|
10
src/files.c
10
src/files.c
|
@ -2915,8 +2915,6 @@ void load_history(void)
|
||||||
* replace history) from oldest to newest. Assume the last
|
* replace history) from oldest to newest. Assume the last
|
||||||
* history entry is a blank line. */
|
* history entry is a blank line. */
|
||||||
filestruct **history = &search_history;
|
filestruct **history = &search_history;
|
||||||
filestruct **historyage = &searchage;
|
|
||||||
filestruct **historybot = &searchbot;
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t buflen = 0;
|
size_t buflen = 0;
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
|
@ -2928,13 +2926,9 @@ void load_history(void)
|
||||||
}
|
}
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
unsunder(line, read);
|
unsunder(line, read);
|
||||||
update_history(history, historyage, historybot,
|
update_history(history, line);
|
||||||
line);
|
} else
|
||||||
} else {
|
|
||||||
history = &replace_history;
|
history = &replace_history;
|
||||||
historyage = &replaceage;
|
|
||||||
historybot = &replacebot;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(hist);
|
fclose(hist);
|
||||||
|
|
13
src/proto.h
13
src/proto.h
|
@ -322,6 +322,9 @@ char *histfilename(void);
|
||||||
void load_history(void);
|
void load_history(void);
|
||||||
bool writehist(FILE *hist, filestruct *histhead);
|
bool writehist(FILE *hist, filestruct *histhead);
|
||||||
void save_history(void);
|
void save_history(void);
|
||||||
|
#ifndef DISABLE_TABCOMP
|
||||||
|
char *get_history_completion(filestruct **h, char *s, size_t len);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Public functions in global.c. */
|
/* Public functions in global.c. */
|
||||||
|
@ -527,9 +530,9 @@ void do_find_bracket(void);
|
||||||
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
||||||
bool history_has_changed(void);
|
bool history_has_changed(void);
|
||||||
void history_init(void);
|
void history_init(void);
|
||||||
filestruct *find_history(filestruct *h, const char *s);
|
filestruct *find_history(filestruct *h_start, filestruct *h_end, const
|
||||||
void update_history(filestruct **h, filestruct **hage, filestruct
|
char *s, size_t len);
|
||||||
**hbot, const char *s);
|
void update_history(filestruct **h, const char *s);
|
||||||
char *get_history_older(filestruct **h);
|
char *get_history_older(filestruct **h);
|
||||||
char *get_history_newer(filestruct **h);
|
char *get_history_newer(filestruct **h);
|
||||||
#endif
|
#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);
|
void nanoget_repaint(const char *buf, const char *inputbuf, size_t x);
|
||||||
int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
||||||
filestruct *history_list,
|
filestruct **history_list,
|
||||||
#endif
|
#endif
|
||||||
const shortcut *s
|
const shortcut *s
|
||||||
#ifndef DISABLE_TABCOMP
|
#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,
|
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
|
||||||
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
||||||
filestruct *history_list,
|
filestruct **history_list,
|
||||||
#endif
|
#endif
|
||||||
const char *msg, ...);
|
const char *msg, ...);
|
||||||
void statusq_abort(void);
|
void statusq_abort(void);
|
||||||
|
|
102
src/search.c
102
src/search.c
|
@ -165,7 +165,7 @@ int search_init(bool replacing, bool use_answer)
|
||||||
i = statusq(FALSE, replacing ? replace_list : whereis_list,
|
i = statusq(FALSE, replacing ? replace_list : whereis_list,
|
||||||
backupstring,
|
backupstring,
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
search_history,
|
&search_history,
|
||||||
#endif
|
#endif
|
||||||
"%s%s%s%s%s%s", _("Search"),
|
"%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
|
/* If answer is not "", add this search string to the search history
|
||||||
* list. */
|
* list. */
|
||||||
if (answer[0] != '\0')
|
if (answer[0] != '\0')
|
||||||
update_history(&search_history, &searchage, &searchbot, answer);
|
update_history(&search_history, answer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
findnextstr_wrap_reset();
|
findnextstr_wrap_reset();
|
||||||
|
@ -905,14 +905,14 @@ void do_replace(void)
|
||||||
* copy answer into last_search. */
|
* copy answer into last_search. */
|
||||||
if (answer[0] != '\0') {
|
if (answer[0] != '\0') {
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
update_history(&search_history, &searchage, &searchbot, answer);
|
update_history(&search_history, answer);
|
||||||
#endif
|
#endif
|
||||||
last_search = mallocstrcpy(last_search, answer);
|
last_search = mallocstrcpy(last_search, answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = statusq(FALSE, replace_list_2, last_replace,
|
i = statusq(FALSE, replace_list_2, last_replace,
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
replace_history,
|
&replace_history,
|
||||||
#endif
|
#endif
|
||||||
_("Replace with"));
|
_("Replace with"));
|
||||||
|
|
||||||
|
@ -920,8 +920,7 @@ void do_replace(void)
|
||||||
/* Add this replace string to the replace history list. i == 0
|
/* Add this replace string to the replace history list. i == 0
|
||||||
* means that the string is not "". */
|
* means that the string is not "". */
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
update_history(&replace_history, &replaceage, &replacebot,
|
update_history(&replace_history, answer);
|
||||||
answer);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (i != 0 && i != -2) {
|
if (i != 0 && i != -2) {
|
||||||
|
@ -1140,32 +1139,42 @@ void history_init(void)
|
||||||
replacebot = replace_history;
|
replacebot = replace_history;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the first node containing the string s in the history list,
|
/* Return the first node containing the first len characters of the
|
||||||
* starting at h, or NULL if there isn't one. */
|
* string s in the history list, starting at h_start and ending at
|
||||||
filestruct *find_history(filestruct *h, const char *s)
|
* 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) {
|
for (p = h_start; p != h_end->next && p != NULL; p = p->next) {
|
||||||
if (strcmp(s, h->data) == 0)
|
if (strncmp(s, p->data, len) == 0)
|
||||||
return h;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update a history list. h should be the current position in the list,
|
/* Update a history list. h should be the current position in the
|
||||||
* hage should be the top of the list, and hbot should be the bottom of
|
* list. */
|
||||||
* the list. */
|
void update_history(filestruct **h, const char *s)
|
||||||
void update_history(filestruct **h, filestruct **hage, filestruct
|
|
||||||
**hbot, 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. */
|
/* 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) {
|
if (p != NULL) {
|
||||||
filestruct *foo, *bar;
|
filestruct *foo, *bar;
|
||||||
|
@ -1239,4 +1248,55 @@ char *get_history_newer(filestruct **h)
|
||||||
|
|
||||||
return (*h)->data;
|
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 */
|
#endif /* !NANO_SMALL && ENABLE_NANORC */
|
||||||
|
|
36
src/winio.c
36
src/winio.c
|
@ -2431,7 +2431,7 @@ void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
|
||||||
* statusq(). */
|
* statusq(). */
|
||||||
int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
||||||
filestruct *history_list,
|
filestruct **history_list,
|
||||||
#endif
|
#endif
|
||||||
const shortcut *s
|
const shortcut *s
|
||||||
#ifndef DISABLE_TABCOMP
|
#ifndef DISABLE_TABCOMP
|
||||||
|
@ -2447,6 +2447,13 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
/* Whether we've pressed Tab. */
|
/* Whether we've pressed Tab. */
|
||||||
#endif
|
#endif
|
||||||
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
#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;
|
char *history = NULL;
|
||||||
/* The current history string. */
|
/* The current history string. */
|
||||||
char *magichistory = NULL;
|
char *magichistory = NULL;
|
||||||
|
@ -2494,6 +2501,19 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
switch (kbinput) {
|
switch (kbinput) {
|
||||||
case NANO_TAB_KEY:
|
case NANO_TAB_KEY:
|
||||||
#ifndef DISABLE_TABCOMP
|
#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)
|
if (allow_tabs)
|
||||||
answer = input_tab(answer, &statusbar_x, &tabbed,
|
answer = input_tab(answer, &statusbar_x, &tabbed,
|
||||||
list);
|
list);
|
||||||
|
@ -2506,7 +2526,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
* history list, answer isn't blank, and
|
* history list, answer isn't blank, and
|
||||||
* magichistory isn't set, save answer in
|
* magichistory isn't set, save answer in
|
||||||
* magichistory. */
|
* magichistory. */
|
||||||
if (history_list->next == NULL &&
|
if ((*history_list)->next == NULL &&
|
||||||
answer[0] != '\0' && magichistory == NULL)
|
answer[0] != '\0' && magichistory == NULL)
|
||||||
magichistory = mallocstrcpy(NULL, answer);
|
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,
|
* save it in answer. If there is no older search,
|
||||||
* don't do anything. */
|
* don't do anything. */
|
||||||
if ((history =
|
if ((history =
|
||||||
get_history_older(&history_list)) != NULL) {
|
get_history_older(history_list)) != NULL) {
|
||||||
answer = mallocstrcpy(answer, history);
|
answer = mallocstrcpy(answer, history);
|
||||||
statusbar_x = strlen(answer);
|
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,
|
* save it in answer. If there is no newer search,
|
||||||
* don't do anything. */
|
* don't do anything. */
|
||||||
if ((history =
|
if ((history =
|
||||||
get_history_newer(&history_list)) != NULL) {
|
get_history_newer(history_list)) != NULL) {
|
||||||
answer = mallocstrcpy(answer, history);
|
answer = mallocstrcpy(answer, history);
|
||||||
statusbar_x = strlen(answer);
|
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
|
* the history list, answer is blank, and
|
||||||
* magichistory is set, save magichistory in
|
* magichistory is set, save magichistory in
|
||||||
* answer. */
|
* answer. */
|
||||||
if (history_list->next == NULL &&
|
if ((*history_list)->next == NULL &&
|
||||||
answer[0] == '\0' && magichistory != NULL) {
|
answer[0] == '\0' && magichistory != NULL) {
|
||||||
answer = mallocstrcpy(answer, magichistory);
|
answer = mallocstrcpy(answer, magichistory);
|
||||||
statusbar_x = strlen(answer);
|
statusbar_x = strlen(answer);
|
||||||
|
@ -2560,6 +2580,10 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
if (finished)
|
if (finished)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC) && !defined(DISABLE_TABCOMP)
|
||||||
|
last_kbinput = kbinput;
|
||||||
|
#endif
|
||||||
|
|
||||||
nanoget_repaint(buf, answer, statusbar_x);
|
nanoget_repaint(buf, answer, statusbar_x);
|
||||||
wrefresh(bottomwin);
|
wrefresh(bottomwin);
|
||||||
}
|
}
|
||||||
|
@ -2588,7 +2612,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
|
||||||
* interpreted. */
|
* interpreted. */
|
||||||
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
|
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
|
||||||
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
||||||
filestruct *history_list,
|
filestruct **history_list,
|
||||||
#endif
|
#endif
|
||||||
const char *msg, ...)
|
const char *msg, ...)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue