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
Этот коммит содержится в:
родитель
1726050ef9
Коммит
34bdc35d94
16
ChangeLog
16
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
|
||||
|
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
|
||||
* 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);
|
||||
|
13
src/proto.h
13
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);
|
||||
|
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,
|
||||
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 */
|
||||
|
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(). */
|
||||
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, ...)
|
||||
{
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user