Blame


1 2051e653 2021-03-13 op /*
2 65c49665 2024-01-23 op * Copyright (c) 2021, 2024 Omar Polo <op@omarpolo.com>
3 2051e653 2021-03-13 op *
4 2051e653 2021-03-13 op * Permission to use, copy, modify, and distribute this software for any
5 2051e653 2021-03-13 op * purpose with or without fee is hereby granted, provided that the above
6 2051e653 2021-03-13 op * copyright notice and this permission notice appear in all copies.
7 2051e653 2021-03-13 op *
8 2051e653 2021-03-13 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 2051e653 2021-03-13 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 2051e653 2021-03-13 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 2051e653 2021-03-13 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 2051e653 2021-03-13 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 2051e653 2021-03-13 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 2051e653 2021-03-13 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 2051e653 2021-03-13 op */
16 2051e653 2021-03-13 op
17 786e6deb 2021-07-21 op #include "compat.h"
18 2051e653 2021-03-13 op
19 2051e653 2021-03-13 op #include <stdlib.h>
20 65c49665 2024-01-23 op #include <string.h>
21 2051e653 2021-03-13 op
22 65c49665 2024-01-23 op #include "hist.h"
23 786e6deb 2021-07-21 op
24 65c49665 2024-01-23 op struct hist {
25 65c49665 2024-01-23 op TAILQ_HEAD(mhist, hist_item) head;
26 65c49665 2024-01-23 op int flags;
27 65c49665 2024-01-23 op size_t size;
28 65c49665 2024-01-23 op ssize_t off;
29 65c49665 2024-01-23 op struct hist_item *cur;
30 65c49665 2024-01-23 op };
31 65c49665 2024-01-23 op
32 65c49665 2024-01-23 op struct hist_item {
33 65c49665 2024-01-23 op char *str;
34 65c49665 2024-01-23 op size_t line_off;
35 65c49665 2024-01-23 op size_t current_off;
36 65c49665 2024-01-23 op TAILQ_ENTRY(hist_item) entries;
37 65c49665 2024-01-23 op };
38 65c49665 2024-01-23 op
39 65c49665 2024-01-23 op struct hist *
40 65c49665 2024-01-23 op hist_new(int flags)
41 65c49665 2024-01-23 op {
42 65c49665 2024-01-23 op struct hist *hist;
43 65c49665 2024-01-23 op
44 65c49665 2024-01-23 op if ((hist = calloc(1, sizeof(*hist))) == NULL)
45 65c49665 2024-01-23 op return (NULL);
46 65c49665 2024-01-23 op
47 65c49665 2024-01-23 op TAILQ_INIT(&hist->head);
48 65c49665 2024-01-23 op hist->flags = flags;
49 65c49665 2024-01-23 op hist->off = -1;
50 65c49665 2024-01-23 op return (hist);
51 65c49665 2024-01-23 op }
52 65c49665 2024-01-23 op
53 2051e653 2021-03-13 op void
54 65c49665 2024-01-23 op hist_free(struct hist *hist)
55 bf935370 2022-01-05 op {
56 65c49665 2024-01-23 op if (hist == NULL)
57 65c49665 2024-01-23 op return;
58 bf935370 2022-01-05 op
59 65c49665 2024-01-23 op hist_erase(hist);
60 65c49665 2024-01-23 op free(hist);
61 65c49665 2024-01-23 op }
62 65c49665 2024-01-23 op
63 65c49665 2024-01-23 op static void
64 65c49665 2024-01-23 op hist_erase_from(struct hist *hist, struct hist_item *h)
65 65c49665 2024-01-23 op {
66 65c49665 2024-01-23 op struct hist_item *next;
67 65c49665 2024-01-23 op
68 65c49665 2024-01-23 op while (h != NULL) {
69 65c49665 2024-01-23 op next = TAILQ_NEXT(h, entries);
70 65c49665 2024-01-23 op
71 65c49665 2024-01-23 op hist->size--;
72 65c49665 2024-01-23 op TAILQ_REMOVE(&hist->head, h, entries);
73 65c49665 2024-01-23 op free(h->str);
74 bf935370 2022-01-05 op free(h);
75 65c49665 2024-01-23 op h = next;
76 bf935370 2022-01-05 op }
77 bf935370 2022-01-05 op }
78 bf935370 2022-01-05 op
79 bf935370 2022-01-05 op void
80 65c49665 2024-01-23 op hist_erase(struct hist *hist)
81 2051e653 2021-03-13 op {
82 65c49665 2024-01-23 op hist_erase_from(hist, TAILQ_FIRST(&hist->head));
83 eae77727 2022-01-05 op
84 65c49665 2024-01-23 op hist->size = 0;
85 65c49665 2024-01-23 op hist->off = -1;
86 65c49665 2024-01-23 op hist->cur = NULL;
87 65c49665 2024-01-23 op }
88 eae77727 2022-01-05 op
89 65c49665 2024-01-23 op size_t
90 65c49665 2024-01-23 op hist_size(struct hist *hist)
91 65c49665 2024-01-23 op {
92 65c49665 2024-01-23 op return (hist->size);
93 65c49665 2024-01-23 op }
94 65c49665 2024-01-23 op
95 65c49665 2024-01-23 op size_t
96 65c49665 2024-01-23 op hist_off(struct hist *hist)
97 65c49665 2024-01-23 op {
98 65c49665 2024-01-23 op if (hist->off == -1)
99 65c49665 2024-01-23 op return (0);
100 65c49665 2024-01-23 op return (hist->off);
101 65c49665 2024-01-23 op }
102 65c49665 2024-01-23 op
103 65c49665 2024-01-23 op const char *
104 65c49665 2024-01-23 op hist_cur(struct hist *hist)
105 65c49665 2024-01-23 op {
106 65c49665 2024-01-23 op if (hist->cur == NULL)
107 65c49665 2024-01-23 op return (NULL);
108 65c49665 2024-01-23 op return (hist->cur->str);
109 65c49665 2024-01-23 op }
110 65c49665 2024-01-23 op
111 65c49665 2024-01-23 op int
112 65c49665 2024-01-23 op hist_cur_offs(struct hist *hist, size_t *line, size_t *curr)
113 65c49665 2024-01-23 op {
114 65c49665 2024-01-23 op *line = 0;
115 65c49665 2024-01-23 op *curr = 0;
116 65c49665 2024-01-23 op
117 65c49665 2024-01-23 op if (hist->cur == NULL)
118 65c49665 2024-01-23 op return (-1);
119 65c49665 2024-01-23 op
120 65c49665 2024-01-23 op *line = hist->cur->line_off;
121 65c49665 2024-01-23 op *curr = hist->cur->current_off;
122 65c49665 2024-01-23 op return (0);
123 65c49665 2024-01-23 op }
124 65c49665 2024-01-23 op
125 65c49665 2024-01-23 op int
126 65c49665 2024-01-23 op hist_set_cur(struct hist *hist, const char *str)
127 65c49665 2024-01-23 op {
128 65c49665 2024-01-23 op char *d;
129 65c49665 2024-01-23 op
130 65c49665 2024-01-23 op if (hist->cur == NULL)
131 65c49665 2024-01-23 op return (-1);
132 65c49665 2024-01-23 op
133 65c49665 2024-01-23 op if ((d = strdup(str)) == NULL)
134 65c49665 2024-01-23 op return (-1);
135 65c49665 2024-01-23 op
136 65c49665 2024-01-23 op free(hist->cur->str);
137 65c49665 2024-01-23 op hist->cur->str = d;
138 65c49665 2024-01-23 op return (0);
139 65c49665 2024-01-23 op }
140 65c49665 2024-01-23 op
141 65c49665 2024-01-23 op int
142 65c49665 2024-01-23 op hist_set_offs(struct hist *hist, size_t line, size_t curr)
143 65c49665 2024-01-23 op {
144 65c49665 2024-01-23 op if (hist->cur == NULL)
145 65c49665 2024-01-23 op return (-1);
146 65c49665 2024-01-23 op
147 65c49665 2024-01-23 op hist->cur->line_off = line;
148 65c49665 2024-01-23 op hist->cur->current_off = line;
149 65c49665 2024-01-23 op return (0);
150 65c49665 2024-01-23 op }
151 65c49665 2024-01-23 op
152 65c49665 2024-01-23 op const char *
153 65c49665 2024-01-23 op hist_nth(struct hist *hist, size_t n)
154 65c49665 2024-01-23 op {
155 65c49665 2024-01-23 op size_t i;
156 65c49665 2024-01-23 op struct hist_item *h;
157 65c49665 2024-01-23 op
158 65c49665 2024-01-23 op i = 0;
159 65c49665 2024-01-23 op TAILQ_FOREACH(h, &hist->head, entries) {
160 65c49665 2024-01-23 op if (i++ == n)
161 65c49665 2024-01-23 op return (h->str);
162 eae77727 2022-01-05 op }
163 65c49665 2024-01-23 op return (NULL);
164 65c49665 2024-01-23 op }
165 eae77727 2022-01-05 op
166 65c49665 2024-01-23 op const char *
167 65c49665 2024-01-23 op hist_prev(struct hist *hist)
168 65c49665 2024-01-23 op {
169 65c49665 2024-01-23 op struct hist_item *h;
170 65c49665 2024-01-23 op int wrap = hist->flags & HIST_WRAP;
171 65c49665 2024-01-23 op
172 65c49665 2024-01-23 op if (hist->cur == NULL && !wrap)
173 65c49665 2024-01-23 op return (NULL);
174 65c49665 2024-01-23 op
175 65c49665 2024-01-23 op if (hist->cur == NULL ||
176 65c49665 2024-01-23 op (h = TAILQ_PREV(hist->cur, mhist, entries)) == NULL) {
177 65c49665 2024-01-23 op if (!wrap || (h = TAILQ_LAST(&hist->head, mhist)) == NULL)
178 65c49665 2024-01-23 op return (NULL);
179 65c49665 2024-01-23 op hist->off = hist->size - 1;
180 65c49665 2024-01-23 op } else
181 65c49665 2024-01-23 op hist->off--;
182 65c49665 2024-01-23 op
183 65c49665 2024-01-23 op hist->cur = h;
184 65c49665 2024-01-23 op return (h->str);
185 2051e653 2021-03-13 op }
186 2051e653 2021-03-13 op
187 65c49665 2024-01-23 op const char *
188 65c49665 2024-01-23 op hist_next(struct hist *hist)
189 2051e653 2021-03-13 op {
190 65c49665 2024-01-23 op struct hist_item *h;
191 65c49665 2024-01-23 op int wrap = hist->flags & HIST_WRAP;
192 65c49665 2024-01-23 op
193 65c49665 2024-01-23 op if (hist->cur == NULL && !wrap)
194 65c49665 2024-01-23 op return (NULL);
195 65c49665 2024-01-23 op
196 65c49665 2024-01-23 op if (hist->cur == NULL ||
197 65c49665 2024-01-23 op (h = TAILQ_NEXT(hist->cur, entries)) == NULL) {
198 65c49665 2024-01-23 op if (!wrap || (h = TAILQ_FIRST(&hist->head)) == NULL)
199 65c49665 2024-01-23 op return (NULL);
200 65c49665 2024-01-23 op hist->off = 0;
201 65c49665 2024-01-23 op } else
202 65c49665 2024-01-23 op hist->off++;
203 65c49665 2024-01-23 op
204 65c49665 2024-01-23 op hist->cur = h;
205 65c49665 2024-01-23 op return (h->str);
206 2051e653 2021-03-13 op }
207 fcd99a0d 2021-11-05 op
208 1040cc7f 2021-01-02 op void
209 65c49665 2024-01-23 op hist_seek_start(struct hist *hist)
210 1040cc7f 2021-01-02 op {
211 65c49665 2024-01-23 op hist->off = -1;
212 65c49665 2024-01-23 op hist->cur = NULL;
213 1040cc7f 2021-01-02 op }
214 1040cc7f 2021-01-02 op
215 65c49665 2024-01-23 op int
216 65c49665 2024-01-23 op hist_push(struct hist *hist, const char *str)
217 fcd99a0d 2021-11-05 op {
218 65c49665 2024-01-23 op struct hist_item *h;
219 fcd99a0d 2021-11-05 op
220 65c49665 2024-01-23 op if ((h = calloc(1, sizeof(*h))) == NULL)
221 65c49665 2024-01-23 op return (-1);
222 fcd99a0d 2021-11-05 op
223 65c49665 2024-01-23 op if ((h->str = strdup(str)) == NULL) {
224 65c49665 2024-01-23 op free(h);
225 65c49665 2024-01-23 op return (-1);
226 65c49665 2024-01-23 op }
227 65c49665 2024-01-23 op
228 65c49665 2024-01-23 op if (hist->cur != NULL)
229 65c49665 2024-01-23 op hist_erase_from(hist, TAILQ_NEXT(hist->cur, entries));
230 65c49665 2024-01-23 op hist->cur = h;
231 65c49665 2024-01-23 op hist->off++;
232 65c49665 2024-01-23 op hist->size++;
233 65c49665 2024-01-23 op TAILQ_INSERT_TAIL(&hist->head, h, entries);
234 65c49665 2024-01-23 op return (0);
235 fcd99a0d 2021-11-05 op }
236 65c49665 2024-01-23 op
237 65c49665 2024-01-23 op int
238 65c49665 2024-01-23 op hist_prepend(struct hist *hist, const char *str)
239 65c49665 2024-01-23 op {
240 65c49665 2024-01-23 op struct hist_item *h;
241 65c49665 2024-01-23 op
242 65c49665 2024-01-23 op if (hist->cur == NULL)
243 65c49665 2024-01-23 op return (-1);
244 65c49665 2024-01-23 op
245 65c49665 2024-01-23 op if ((h = calloc(1, sizeof(*h))) == NULL)
246 65c49665 2024-01-23 op return (-1);
247 65c49665 2024-01-23 op
248 65c49665 2024-01-23 op if ((h->str = strdup(str)) == NULL) {
249 65c49665 2024-01-23 op free(h);
250 65c49665 2024-01-23 op return (-1);
251 65c49665 2024-01-23 op }
252 65c49665 2024-01-23 op
253 65c49665 2024-01-23 op hist->size++;
254 65c49665 2024-01-23 op hist->off++;
255 65c49665 2024-01-23 op TAILQ_INSERT_BEFORE(hist->cur, h, entries);
256 65c49665 2024-01-23 op return (0);
257 65c49665 2024-01-23 op }
258 65c49665 2024-01-23 op
259 65c49665 2024-01-23 op int
260 65c49665 2024-01-23 op hist_append(struct hist *hist, const char *str)
261 65c49665 2024-01-23 op {
262 65c49665 2024-01-23 op struct hist_item *h;
263 65c49665 2024-01-23 op
264 65c49665 2024-01-23 op /*
265 65c49665 2024-01-23 op * Not sure. The minibuffer needs to append even when there
266 65c49665 2024-01-23 op * are no items.
267 65c49665 2024-01-23 op */
268 65c49665 2024-01-23 op if (hist->cur == NULL && !(hist->flags & HIST_WRAP))
269 65c49665 2024-01-23 op return (-1);
270 65c49665 2024-01-23 op
271 65c49665 2024-01-23 op if ((h = calloc(1, sizeof(*h))) == NULL)
272 65c49665 2024-01-23 op return (-1);
273 65c49665 2024-01-23 op
274 65c49665 2024-01-23 op if ((h->str = strdup(str)) == NULL) {
275 65c49665 2024-01-23 op free(h);
276 65c49665 2024-01-23 op return (-1);
277 65c49665 2024-01-23 op }
278 65c49665 2024-01-23 op
279 65c49665 2024-01-23 op hist->size++;
280 65c49665 2024-01-23 op TAILQ_INSERT_TAIL(&hist->head, h, entries);
281 65c49665 2024-01-23 op return (0);
282 65c49665 2024-01-23 op }