-
Notifications
You must be signed in to change notification settings - Fork 0
/
suggestions.c
133 lines (111 loc) · 3.22 KB
/
suggestions.c
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#define _GNU_SOURCE
#include "suggestions.h"
#include "stdio.h"
#include "basic.h"
#include "journal.h"
#include "terminal.h"
#include "assert.h"
#include <string.h>
#define MAX_VIEWED_SUGGESTIONS 3
#define MAX_SUGGESTIONS 32
#define MAX_SUGGESTION_LENGTH 256
static char buffer[MAX_SUGGESTIONS][MAX_SUGGESTION_LENGTH];
static int position;
static int offset;
static int count;
static int cursor;
static int minimum_position;
static char* last_selected_suggestion;
static void update_offset() {
offset = compute_offset(position, offset, MAX_VIEWED_SUGGESTIONS, 0, 1);
}
static void update_pointer() {
last_selected_suggestion = (position >= 0) ? buffer[position] : 0;
}
void suggestion_up() {
position = max(position - 1, minimum_position);
update_offset();
update_pointer();
}
void suggestion_down() {
position = min(position + 1, count - 1);
update_offset();
update_pointer();
}
bool suggestion_active() {
return count > 0;
}
void set_suggestions_print_cursor(int x) {
cursor = x;
}
void set_suggestions_minimum_index(int index) {
minimum_position = index;
position = minimum_position;
}
bool add_suggestion(char* data, ...) {
if (count == MAX_SUGGESTIONS) return false;
char* dest = buffer[count++];
va_list arguments;
va_start(arguments, data);
int size = vsnprintf(dest, MAX_SUGGESTION_LENGTH - 1, data, arguments);
dest[size] = 0;
return true;
}
char* get_suggestion() {
// Makes it easier. No need to think about when to clear, when to get current suggestion, etc. Clear first, get at any time.
return last_selected_suggestion;
}
void clear_suggestions() {
if (count) {
last_selected_suggestion = (position >= 0) ? buffer[position] : 0;
position = minimum_position;
count = 0;
offset = 0;
// Erase previously displayed suggestions.
print("\r\n");
clear_all_right();
cursor_up(1);
} else {
last_selected_suggestion = 0;
}
}
void print_suggestions() {
int print_count = min(MAX_VIEWED_SUGGESTIONS, count - offset);
if (cursor < 2) print_count = 0;
// Make sure there is enough spaces for all suggestions. Prevent the terminal from suddenly scrolling.
for (int i = 0; i < MAX_VIEWED_SUGGESTIONS; i++) print("\n");
cursor_up(MAX_VIEWED_SUGGESTIONS);
for (int i = offset; i < offset + print_count; i++) {
print("\n");
clear_line();
set_x_cursor(cursor - 1);
if (i == position) invert();
print(" %s \033[0m", buffer[i]);
}
if (print_count) cursor_up(print_count);
}
void suggest_account(char* name, bool allow_cathegories) {
for (int i = 0; i < journal.account_count; i++) {
Account* account = &journal.accounts[i];
if (allow_cathegories == false && account->is_category) continue;
if (strcasestr(account->path, name)) {
if (!add_suggestion("%s", account->path)) return;
}
}
}
void suggest_description(char* name) {
for (int i = 0; i < journal.raw_transaction_count; i++) {
char* desc = journal.raw_transactions[i].description;
if (!desc) continue;
if (strcasestr(desc, name)) {
bool unique = true;
for (int j = 0; j < count; j++) {
if (!strcmp(buffer[j], desc)) {
unique = false;
break;
}
}
if (unique && !add_suggestion(desc)) break;
}
}
}