summaryrefslogtreecommitdiff
path: root/src/compgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compgen.c')
-rw-r--r--src/compgen.c98
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;
}