summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.c3
-rw-r--r--src/string_vec.c33
-rw-r--r--src/string_vec.h3
3 files changed, 37 insertions, 2 deletions
diff --git a/src/main.c b/src/main.c
index 448c164..9d9f4d9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1351,9 +1351,8 @@ int main(int argc, char *argv[])
if (tofi.history_file[0] == 0) {
tofi.use_history = false;
} else {
- string_vec_sort(&tofi.window.entry.commands);
tofi.window.entry.history = history_load(tofi.history_file);
- compgen_history_sort(&tofi.window.entry.commands, &tofi.window.entry.history);
+ string_vec_history_sort(&tofi.window.entry.commands, &tofi.window.entry.history);
}
}
}
diff --git a/src/string_vec.c b/src/string_vec.c
index 4607727..f5cf899 100644
--- a/src/string_vec.c
+++ b/src/string_vec.c
@@ -1,3 +1,4 @@
+#include <glib.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -5,6 +6,7 @@
#include <string.h>
#include <sys/mman.h>
#include "fuzzy_match.h"
+#include "history.h"
#include "string_vec.h"
#include "unicode.h"
#include "xmalloc.h"
@@ -36,6 +38,14 @@ static int cmpscorep(const void *restrict a, const void *restrict b)
return hist_diff + search_diff;
}
+static int cmphistoryp(const void *restrict a, const void *restrict b)
+{
+ struct scored_string *restrict str1 = (struct scored_string *)a;
+ struct scored_string *restrict str2 = (struct scored_string *)b;
+
+ return str2->history_score - str1->history_score;
+}
+
struct string_vec string_vec_create(void)
{
struct string_vec vec = {
@@ -91,6 +101,29 @@ void string_vec_sort(struct string_vec *restrict vec)
qsort(vec->buf, vec->count, sizeof(vec->buf[0]), cmpstringp);
}
+void string_vec_history_sort(struct string_vec *restrict vec, struct history *history)
+{
+ /*
+ * To find elements without assuming the vector is pre-sorted, we use a
+ * hash table, which results in O(N+M) work (rather than O(N*M) for
+ * linear search.
+ */
+ GHashTable *hash = g_hash_table_new(g_str_hash, g_str_equal);
+ for (size_t i = 0; i < vec->count; i++) {
+ g_hash_table_insert(hash, vec->buf[i].string, &vec->buf[i]);
+ }
+ for (size_t i = 0; i < history->count; i++) {
+ struct scored_string *res = g_hash_table_lookup(hash, history->buf[i].name);
+ if (res == NULL) {
+ continue;
+ }
+ res->history_score = history->buf[i].run_count;
+ }
+ g_hash_table_unref(hash);
+
+ qsort(vec->buf, vec->count, sizeof(vec->buf[0]), cmphistoryp);
+}
+
void string_vec_uniq(struct string_vec *restrict vec)
{
size_t count = vec->count;
diff --git a/src/string_vec.h b/src/string_vec.h
index f3e840c..f8ca3e0 100644
--- a/src/string_vec.h
+++ b/src/string_vec.h
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
+#include "history.h"
struct scored_string {
char *string;
@@ -30,6 +31,8 @@ void string_vec_add(struct string_vec *restrict vec, const char *restrict str);
void string_vec_sort(struct string_vec *restrict vec);
+void string_vec_history_sort(struct string_vec *restrict vec, struct history *history);
+
void string_vec_uniq(struct string_vec *restrict vec);
struct scored_string *string_vec_find(struct string_vec *restrict vec, const char *str);