diff options
Diffstat (limited to 'src/compgen.c')
-rw-r--r-- | src/compgen.c | 98 |
1 files changed, 44 insertions, 54 deletions
diff --git a/src/compgen.c b/src/compgen.c index 8190a21..f514d66 100644 --- a/src/compgen.c +++ b/src/compgen.c @@ -4,74 +4,25 @@ #include <stdlib.h> #include <string.h> #include <sys/stat.h> +#include "history.h" #include "log.h" #include "string_vec.h" #include "xmalloc.h" -static const char *default_state_dir = ".local/state"; -static const char *histfile_basename = "tofi-history"; - -static char *get_histfile_path() { - char *histfile_name; - const char *state_path = getenv("XDG_STATE_HOME"); - if (state_path == NULL) { - const char *home = getenv("HOME"); - if (home == NULL) { - log_error("Couldn't retrieve HOME from environment.\n"); - exit(EXIT_FAILURE); - } - size_t len = strlen(home) + 1 - + strlen(default_state_dir) + 1 - + strlen(histfile_basename) + 1; - histfile_name = xmalloc(len); - snprintf( - histfile_name, - len, - "%s/%s/%s", - home, - default_state_dir, - histfile_basename); - } else { - size_t len = strlen(state_path) + 1 - + strlen(histfile_basename) + 1; - histfile_name = xmalloc(len); - snprintf( - histfile_name, - len, - "%s/%s", - state_path, - histfile_basename); - } - return histfile_name; - -} - -static void load_history() -{ - char *name = get_histfile_path(); - FILE *histfile = fopen(name, "rb"); - - free(name); - - if (histfile == NULL) { - return; - } - -} - -struct string_vec compgen() +struct string_vec compgen(struct history *history) { - load_history(); log_debug("Retrieving PATH.\n"); const char *env_path = getenv("PATH"); if (env_path == NULL) { log_error("Couldn't retrieve PATH from environment.\n"); exit(EXIT_FAILURE); } + struct string_vec programs = string_vec_create(); - char *path = strdup(env_path); + char *path = xstrdup(env_path); char *saveptr = NULL; char *path_entry = strtok_r(path, ":", &saveptr); + log_debug("Scanning PATH for binaries.\n"); while (path_entry != NULL) { DIR *dir = opendir(path_entry); @@ -96,10 +47,49 @@ struct string_vec compgen() path_entry = strtok_r(NULL, ":", &saveptr); } free(path); + log_debug("Sorting results.\n"); string_vec_sort(&programs); + log_debug("Making unique.\n"); string_vec_uniq(&programs); + + log_debug("Moving already known programs to the front.\n"); + /* + * Remove any programs in our history from the generated list, and + * store which ones we found in to_add. + * Removal is done without changing the count, as we're about to re-add + * them at the front. + */ + struct string_vec to_add = string_vec_create(); + for (size_t i = 0; i < history->count; i++) { + char **res = string_vec_find(&programs, history->buf[i].name); + if (res == NULL) { + continue; + } + free(*res); + *res = NULL; + string_vec_add(&to_add, history->buf[i].name); + } + + /* Sort the vector to push the removed entries to the end. */ + string_vec_sort(&programs); + + /* + * Move the results down by the number of items we want to add. There's + * guaranteed to be enough space to do this, as we just removed that + * many items. + */ + memmove( + &programs.buf[to_add.count], + programs.buf, + (programs.count - to_add.count) * sizeof(programs.buf[0])); + + /* Add our history to the front in order. */ + for (size_t i = 0; i < to_add.count; i++) { + programs.buf[i] = xstrdup(to_add.buf[i]); + } + string_vec_destroy(&to_add); log_debug("Done.\n"); return programs; } |