1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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;
}
|