From 0c10a699f2be44665c6e7aa7ec82c0b07a71d743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Wennerstr=C3=B6m?= Date: Sat, 13 Jul 2019 19:08:10 +0200 Subject: [PATCH] Always check for directory changes with sendfile auto completion Instead of only checking for files when 'last_directory' has changed, do it every time. Add autocomplete_update function that updates the items while retaining last_found and search_str. Fixes #1099 --- src/command/cmd_ac.c | 97 +++++++++++++++++++++------------------- src/tools/autocomplete.c | 35 ++++++++++++++- src/tools/autocomplete.h | 1 + 3 files changed, 85 insertions(+), 48 deletions(-) diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 1ce20862..619ec55d 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -1290,11 +1290,15 @@ cmd_ac_uninit(void) autocomplete_free(statusbar_show_ac); } +static void +_filepath_item_free(char **ptr) { + char *item = *ptr; + free(item); +} + char* cmd_ac_complete_filepath(const char *const input, char *const startstr, gboolean previous) { - static char* last_directory = NULL; - unsigned int output_off = 0; char *result = NULL; @@ -1339,56 +1343,57 @@ cmd_ac_complete_filepath(const char *const input, char *const startstr, gboolean free(inpcp); free(inpcp2); - if (!last_directory || strcmp(last_directory, directory) != 0) { - free(last_directory); - last_directory = directory; - autocomplete_reset(filepath_ac); + struct dirent *dir; + GArray *files = g_array_new(TRUE, FALSE, sizeof(char *)); + g_array_set_clear_func(files, (GDestroyNotify)_filepath_item_free); - struct dirent *dir; - - DIR *d = opendir(directory); - if (d) { - while ((dir = readdir(d)) != NULL) { - if (strcmp(dir->d_name, ".") == 0) { - continue; - } else if (strcmp(dir->d_name, "..") == 0) { - continue; - } else if (*(dir->d_name) == '.' && *foofile != '.') { - // only show hidden files on explicit request - continue; - } - char * acstring; - if (output_off) { - if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { - free(foofile); - return NULL; - } - if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { - free(foofile); - return NULL; - } - free(tmp); - } else if (strcmp(directory, "/") == 0) { - if (asprintf(&acstring, "/%s", dir->d_name) == -1) { - free(foofile); - return NULL; - } - } else { - if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { - free(foofile); - return NULL; - } - } - autocomplete_add(filepath_ac, acstring); - free(acstring); + DIR *d = opendir(directory); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strcmp(dir->d_name, ".") == 0) { + continue; + } else if (strcmp(dir->d_name, "..") == 0) { + continue; + } else if (*(dir->d_name) == '.' && *foofile != '.') { + // only show hidden files on explicit request + continue; } - closedir(d); + + char *acstring; + if (output_off) { + if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { + free(foofile); + return NULL; + } + if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { + free(foofile); + return NULL; + } + free(tmp); + } else if (strcmp(directory, "/") == 0) { + if (asprintf(&acstring, "/%s", dir->d_name) == -1) { + free(foofile); + return NULL; + } + } else { + if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { + free(foofile); + return NULL; + } + } + + char *acstring_cpy = strdup(acstring); + g_array_append_val(files, acstring_cpy); + free(acstring); } - } else { - free(directory); + closedir(d); } + free(directory); free(foofile); + autocomplete_update(filepath_ac, (char **)files->data); + g_array_free(files, TRUE); + result = autocomplete_param_with_ac(input, startstr, filepath_ac, TRUE, previous); if (result) { return result; diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index 79312e53..03a30553 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -66,8 +66,10 @@ void autocomplete_clear(Autocomplete ac) { if (ac) { - g_list_free_full(ac->items, free); - ac->items = NULL; + if (ac->items) { + g_list_free_full(ac->items, free); + ac->items = NULL; + } autocomplete_reset(ac); } @@ -101,6 +103,35 @@ autocomplete_length(Autocomplete ac) } } +void +autocomplete_update(Autocomplete ac, char **items) +{ + gchar *last_found = NULL; + gchar *search_str = NULL; + + if (ac->last_found) { + last_found = strdup(ac->last_found->data); + } + + if (ac->search_str) { + search_str = strdup(ac->search_str); + } + + autocomplete_clear(ac); + autocomplete_add_all(ac, items); + + if (last_found) { + // NULL if last_found was removed on update. + ac->last_found = g_list_find_custom(ac->items, last_found, (GCompareFunc)strcmp); + free(last_found); + } + + if (search_str) { + ac->search_str = strdup(search_str); + free(search_str); + } +} + void autocomplete_add(Autocomplete ac, const char *item) { diff --git a/src/tools/autocomplete.h b/src/tools/autocomplete.h index 78bec44d..a8797369 100644 --- a/src/tools/autocomplete.h +++ b/src/tools/autocomplete.h @@ -51,6 +51,7 @@ void autocomplete_free(Autocomplete ac); void autocomplete_add(Autocomplete ac, const char *item); void autocomplete_add_all(Autocomplete ac, char **items); +void autocomplete_update(Autocomplete ac, char **items); void autocomplete_remove(Autocomplete ac, const char *const item); void autocomplete_remove_all(Autocomplete ac, char **items);