summaryrefslogtreecommitdiff
path: root/choices.c
diff options
context:
space:
mode:
Diffstat (limited to 'choices.c')
-rw-r--r--choices.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/choices.c b/choices.c
new file mode 100644
index 0000000..bd3f016
--- /dev/null
+++ b/choices.c
@@ -0,0 +1,89 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+
+#include "choices.h"
+#include "fzy.h"
+
+#define INITIAL_CAPACITY 1
+
+static int cmpchoice(size_t *idx1, size_t *idx2, double *choices_score) {
+ double score1 = choices_score[*idx1];
+ double score2 = choices_score[*idx2];
+
+ if(score1 == score2)
+ return 0;
+ else if(score1 < score2)
+ return 1;
+ else
+ return -1;
+}
+
+static void choices_resize(choices_t *c, int new_capacity){
+ c->strings = realloc(c->strings, new_capacity * sizeof(const char *));
+ c->scores = realloc(c->scores, new_capacity * sizeof(double));
+ c->sorted = realloc(c->sorted, new_capacity * sizeof(size_t));
+
+ for(int i = c->capacity; i < new_capacity; i++){
+ c->strings[i] = NULL;
+ }
+ c->capacity = new_capacity;
+}
+
+void choices_init(choices_t *c){
+ c->strings = NULL;
+ c->scores = NULL;
+ c->sorted = NULL;
+ c->capacity = c->size = 0;
+ c->selection = c->available = 0;
+ choices_resize(c, INITIAL_CAPACITY);
+}
+void choices_free(choices_t *c){
+ free(c->strings);
+ free(c->scores);
+ free(c->sorted);
+};
+
+void choices_add(choices_t *c, const char *choice){
+ if(c->size == c->capacity){
+ choices_resize(c, c->capacity * 2);
+ }
+ c->strings[c->size++] = choice;
+}
+
+size_t choices_available(choices_t *c){
+ return c->available;
+}
+
+void choices_search(choices_t *c, const char *search){
+ c->selection = 0;
+ c->available = 0;
+
+ for(size_t i = 0; i < c->size; i++){
+ if(has_match(search, c->strings[i])){
+ c->scores[i] = match(search, c->strings[i]);
+ c->sorted[c->available++] = i;
+ }
+ }
+
+ qsort_r(c->sorted, c->available, sizeof(size_t), (int (*)(const void *, const void *, void *))cmpchoice, c->scores);
+}
+
+const char *choices_get(choices_t *c, size_t n){
+ if(n < c->available){
+ return c->strings[c->sorted[n]];
+ }else{
+ return NULL;
+ }
+}
+double choices_getscore(choices_t *c, size_t n){
+ return c->scores[c->sorted[n]];;
+}
+
+void choices_prev(choices_t *c){
+ c->selection = (c->selection + c->available - 1) % c->available;
+}
+
+void choices_next(choices_t *c){
+ c->selection = (c->selection + 1) % c->available;
+}
+