diff options
Diffstat (limited to 'complete.c')
-rw-r--r-- | complete.c | 172 |
1 files changed, 97 insertions, 75 deletions
diff --git a/complete.c b/complete.c index 9e59db5..3552c7c 100644 --- a/complete.c +++ b/complete.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 C. McEnroe <june@causal.agency> +/* Copyright (C) 2020, 2022 June McEnroe <june@causal.agency> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +26,6 @@ */ #include <err.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sysexits.h> @@ -37,25 +36,26 @@ struct Node { uint id; char *str; enum Color color; + uint bits; struct Node *prev; struct Node *next; }; +static uint gen; +static struct Node *head; +static struct Node *tail; + static struct Node *alloc(uint id, const char *str, enum Color color) { - struct Node *node = malloc(sizeof(*node)); - if (!node) err(EX_OSERR, "malloc"); + struct Node *node = calloc(1, sizeof(*node)); + if (!node) err(EX_OSERR, "calloc"); node->id = id; node->str = strdup(str); - node->color = color; - node->prev = NULL; - node->next = NULL; if (!node->str) err(EX_OSERR, "strdup"); + node->color = color; + node->bits = 0; return node; } -static struct Node *head; -static struct Node *tail; - static struct Node *detach(struct Node *node) { if (node->prev) node->prev->next = node->next; if (node->next) node->next->prev = node->prev; @@ -86,76 +86,39 @@ static struct Node *append(struct Node *node) { static struct Node *find(uint id, const char *str) { for (struct Node *node = head; node; node = node->next) { - if (node->id != id) continue; - if (strcmp(node->str, str)) continue; - return node; + if (node->id == id && !strcmp(node->str, str)) return node; } return NULL; } -void completeAdd(uint id, const char *str, enum Color color) { - if (!find(id, str)) append(alloc(id, str, color)); -} - -void completeTouch(uint id, const char *str, enum Color color) { - struct Node *node = find(id, str); - if (node) node->color = color; - prepend(node ? detach(node) : alloc(id, str, color)); -} - -enum Color completeColor(uint id, const char *str) { +void completePush(uint id, const char *str, enum Color color) { struct Node *node = find(id, str); - return (node ? node->color : Default); -} - -static struct Node *match; - -const char *complete(uint id, const char *prefix) { - for (match = (match ? match->next : head); match; match = match->next) { - if (match->id && match->id != id) continue; - if (strncasecmp(match->str, prefix, strlen(prefix))) continue; - return match->str; - } - return NULL; -} - -const char *completeSubstr(uint id, const char *substr) { - for (match = (match ? match->next : head); match; match = match->next) { - if (match->id && match->id != id) continue; - if (!strstr(match->str, substr)) continue; - return match->str; + if (node) { + if (color != Default) node->color = color; + } else { + append(alloc(id, str, color)); } - return NULL; } -void completeAccept(void) { - if (match) prepend(detach(match)); - match = NULL; -} - -void completeReject(void) { - match = NULL; -} - -static struct Node *iter; - -uint completeID(const char *str) { - for (iter = (iter ? iter->next : head); iter; iter = iter->next) { - if (iter->id && !strcmp(iter->str, str)) return iter->id; +void completePull(uint id, const char *str, enum Color color) { + struct Node *node = find(id, str); + if (node) { + if (color != Default) node->color = color; + prepend(detach(node)); + } else { + prepend(alloc(id, str, color)); } - return None; } -void completeReplace(uint id, const char *old, const char *new) { +void completeReplace(const char *old, const char *new) { struct Node *next = NULL; for (struct Node *node = head; node; node = next) { next = node->next; - if (id && node->id != id) continue; if (strcmp(node->str, old)) continue; free(node->str); node->str = strdup(new); - prepend(detach(node)); if (!node->str) err(EX_OSERR, "strdup"); + prepend(detach(node)); } } @@ -164,24 +127,83 @@ void completeRemove(uint id, const char *str) { for (struct Node *node = head; node; node = next) { next = node->next; if (id && node->id != id) continue; - if (strcmp(node->str, str)) continue; - if (match == node) match = NULL; - if (iter == node) iter = NULL; + if (str && strcmp(node->str, str)) continue; detach(node); free(node->str); free(node); } + gen++; } -void completeClear(uint id) { - struct Node *next = NULL; - for (struct Node *node = head; node; node = next) { - next = node->next; - if (node->id != id) continue; - if (match == node) match = NULL; - if (iter == node) iter = NULL; - detach(node); - free(node->str); - free(node); +enum Color completeColor(uint id, const char *str) { + struct Node *node = find(id, str); + return (node ? node->color : Default); +} + +uint *completeBits(uint id, const char *str) { + struct Node *node = find(id, str); + return (node ? &node->bits : NULL); +} + +const char *completePrefix(struct Cursor *curs, uint id, const char *prefix) { + size_t len = strlen(prefix); + if (curs->gen != gen) curs->node = NULL; + for ( + curs->gen = gen, curs->node = (curs->node ? curs->node->next : head); + curs->node; + curs->node = curs->node->next + ) { + if (curs->node->id && curs->node->id != id) continue; + if (!strncasecmp(curs->node->str, prefix, len)) return curs->node->str; } + return NULL; +} + +const char *completeSubstr(struct Cursor *curs, uint id, const char *substr) { + if (curs->gen != gen) curs->node = NULL; + for ( + curs->gen = gen, curs->node = (curs->node ? curs->node->next : head); + curs->node; + curs->node = curs->node->next + ) { + if (curs->node->id && curs->node->id != id) continue; + if (strstr(curs->node->str, substr)) return curs->node->str; + } + return NULL; +} + +const char *completeEach(struct Cursor *curs, uint id) { + if (curs->gen != gen) curs->node = NULL; + for ( + curs->gen = gen, curs->node = (curs->node ? curs->node->next : head); + curs->node; + curs->node = curs->node->next + ) { + if (curs->node->id == id) return curs->node->str; + } + return NULL; +} + +uint completeEachID(struct Cursor *curs, const char *str) { + if (curs->gen != gen) curs->node = NULL; + for ( + curs->gen = gen, curs->node = (curs->node ? curs->node->next : head); + curs->node; + curs->node = curs->node->next + ) { + if (!curs->node->id) continue; + if (!strcmp(curs->node->str, str)) return curs->node->id; + } + return None; +} + +void completeAccept(struct Cursor *curs) { + if (curs->gen == gen && curs->node) { + prepend(detach(curs->node)); + } + curs->node = NULL; +} + +void completeReject(struct Cursor *curs) { + curs->node = NULL; } |