Skip to content

Commit 20eecbf

Browse files
committed
a simple small cli tool
1 parent f297259 commit 20eecbf

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ else
1111
TARGET := libfzf.so
1212
endif
1313

14-
all: build/$(TARGET)
14+
all: build/$(TARGET) build/cli
15+
16+
build/cli: src/fzf.c src/fzf.h src/cli.c
17+
$(MKD) build
18+
$(CC) -Ofast -Wall -Werror src/fzf.c src/cli.c -o build/cli
1519

1620
build/$(TARGET): src/fzf.c src/fzf.h
1721
$(MKD) build

src/cli.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <stdbool.h>
5+
6+
#include "fzf.h"
7+
8+
// sorting
9+
typedef struct {
10+
char *str;
11+
int32_t score;
12+
size_t len;
13+
} fzf_tuple_t;
14+
15+
typedef struct {
16+
fzf_tuple_t *data;
17+
size_t len;
18+
size_t cap;
19+
} heap_t;
20+
21+
heap_t *new_heap() {
22+
heap_t *res = (heap_t *)malloc(sizeof(heap_t));
23+
res->cap = 512;
24+
res->data = malloc(sizeof(fzf_tuple_t) * res->cap);
25+
res->len = 0;
26+
return res;
27+
}
28+
29+
void free_heap(heap_t *heap) {
30+
free(heap->data);
31+
free(heap);
32+
}
33+
34+
static size_t parent(size_t i) {
35+
return (i - 1) / 2;
36+
}
37+
38+
static size_t left_child(size_t i) {
39+
return 2 * i + 1;
40+
}
41+
42+
static size_t right_child(size_t i) {
43+
return 2 * i + 2;
44+
}
45+
46+
void swap(fzf_tuple_t *x, fzf_tuple_t *y) {
47+
fzf_tuple_t temp = *x;
48+
*x = *y;
49+
*y = temp;
50+
}
51+
52+
static bool smaller(fzf_tuple_t *lhs, fzf_tuple_t *rhs) {
53+
return (lhs->score == rhs->score && lhs->len > rhs->len) ||
54+
lhs->score < rhs->score;
55+
}
56+
57+
bool greater(fzf_tuple_t *lhs, fzf_tuple_t *rhs) {
58+
return (lhs->score == rhs->score && lhs->len < rhs->len) ||
59+
lhs->score > rhs->score;
60+
}
61+
62+
static void insert(heap_t *heap, fzf_tuple_t data) {
63+
if (heap->len >= heap->cap) {
64+
heap->cap *= 2;
65+
heap->data = realloc(heap->data, sizeof(fzf_tuple_t) * heap->cap);
66+
}
67+
size_t i = heap->len;
68+
heap->data[heap->len++] = data;
69+
while (i != 0 && smaller(&heap->data[parent(i)], &heap->data[i])) {
70+
swap(&heap->data[parent(i)], &heap->data[i]);
71+
i = parent(i);
72+
}
73+
}
74+
75+
static void max_heapify(heap_t *heap, size_t i) {
76+
size_t left = left_child(i);
77+
size_t right = right_child(i);
78+
size_t largest = i;
79+
80+
if (left <= heap->len && greater(&heap->data[left], &heap->data[largest])) {
81+
largest = left;
82+
}
83+
84+
if (right <= heap->len && greater(&heap->data[right], &heap->data[largest])) {
85+
largest = right;
86+
}
87+
88+
if (largest != i) {
89+
swap(&heap->data[i], &heap->data[largest]);
90+
max_heapify(heap, largest);
91+
}
92+
}
93+
94+
static fzf_tuple_t extract_max(heap_t *heap) {
95+
fzf_tuple_t max_item = heap->data[0];
96+
heap->data[0] = heap->data[--heap->len];
97+
max_heapify(heap, 0);
98+
return max_item;
99+
}
100+
101+
int main(int argc, char **argv) {
102+
fzf_slab_t *slab = fzf_make_default_slab();
103+
fzf_pattern_t *pattern = fzf_parse_pattern(CaseSmart, false, argv[1], true);
104+
heap_t *heap = new_heap();
105+
106+
char *line = NULL;
107+
size_t len = 0;
108+
ssize_t read;
109+
while ((read = getline(&line, &len, stdin)) != -1) {
110+
line[read - 1] = '\0';
111+
int32_t score = fzf_get_score(line, pattern, slab);
112+
if (score > 0) {
113+
char *copy = (char *)malloc(sizeof(char) * read);
114+
strncpy(copy, line, read - 1);
115+
copy[read - 1] = '\0';
116+
insert(heap, (fzf_tuple_t){.str = copy, .score = score, .len = read - 1});
117+
}
118+
}
119+
120+
while (heap->len > 0) {
121+
fzf_tuple_t el = extract_max(heap);
122+
printf("%s\n", el.str);
123+
free(el.str);
124+
}
125+
free_heap(heap);
126+
fzf_free_pattern(pattern);
127+
fzf_free_slab(slab);
128+
free(line);
129+
return 0;
130+
}

0 commit comments

Comments
 (0)