From 8b54d2c31410fcac43c8903007fe0738312834b0 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Wed, 14 Oct 2026 01:54:14 +0200 Subject: help topics no longer need to be unique and can be toggled through with the `?$` command. * This mirrors how the `FT$` command toggles through several results. * Some non-unique .SCITECO_TOPICs have been added to sciteco(1) and sciteco(7). * This works by inserting non-unique keys into the help topic RB tree - or rather by turning filename:pos also into keys since rb3ptr does not allow non-unique keys. When searching for a topic, we sort lower than any other entry with the same name. This way we can easily iterate all entries with the same name (search topic). The alternative would have been to maintain a linked list in each and every teco_help_topic_t. * teco_rb3str_auto_complete() now filters out possible duplicate keys. * Updated test case: check for non-unique topic names. --- src/rb3str.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'src/rb3str.c') diff --git a/src/rb3str.c b/src/rb3str.c index f4c16fa..367ff83 100644 --- a/src/rb3str.c +++ b/src/rb3str.c @@ -60,32 +60,37 @@ teco_rb3str_find(teco_rb3str_tree_t *tree, gboolean case_sensitive, const gchar return (teco_rb3str_head_t *)rb3_find(tree, cmp, &data); } -/** @memberof teco_rb3str_tree_t */ -teco_rb3str_head_t * -teco_rb3str_nfind(teco_rb3str_tree_t *tree, gboolean case_sensitive, const gchar *str, gsize len) +/* + * This is based on rb3_INLINE_find() in rb3ptr.h. + * FIXME: Should perhaps be in rb3ptr.c. + */ +struct rb3_head * +rb3_nfind(struct rb3_tree *tree, rb3_cmp cmp, void *data) { - rb3_cmp *cmp = case_sensitive ? (rb3_cmp *)teco_rb3str_cmp : (rb3_cmp *)teco_rb3str_casecmp; - teco_string_t data = {(gchar *)str, len}; - - /* - * This is based on rb3_INLINE_find() in rb3ptr.h. - * Alternatively, we might adapt/wrap teco_rb3str_cmp() in order to store - * the last element > data. - */ struct rb3_head *parent = rb3_get_base(tree); struct rb3_head *res = NULL; int dir = RB3_LEFT; + while (rb3_has_child(parent, dir)) { parent = rb3_get_child(parent, dir); - int r = cmp(parent, &data); + int r = cmp(parent, data); if (r == 0) - return (teco_rb3str_head_t *)parent; - dir = (r < 0) ? RB3_RIGHT : RB3_LEFT; + return parent; + dir = r < 0 ? RB3_RIGHT : RB3_LEFT; if (dir == RB3_LEFT) res = parent; } - return (teco_rb3str_head_t *)res; + return res; +} + +/** @memberof teco_rb3str_tree_t */ +teco_rb3str_head_t * +teco_rb3str_nfind(teco_rb3str_tree_t *tree, gboolean case_sensitive, const gchar *str, gsize len) +{ + rb3_cmp *cmp = case_sensitive ? (rb3_cmp *)teco_rb3str_cmp : (rb3_cmp *)teco_rb3str_casecmp; + teco_string_t data = {(gchar *)str, len}; + return (teco_rb3str_head_t *)rb3_nfind(tree, cmp, &data); } /** @@ -133,9 +138,14 @@ teco_rb3str_auto_complete(teco_rb3str_tree_t *tree, gboolean case_sensitive, if (prefix_len > 0) { teco_string_init(insert, first->key.data + str_len, prefix_len); } else if (prefixed_entries > 1) { + teco_rb3str_head_t *next; for (teco_rb3str_head_t *cur = first; cur && cur->key.len >= str_len && diff(cur->key, str, str_len) == str_len; - cur = teco_rb3str_get_next(cur)) { + cur = next) { + next = teco_rb3str_get_next(cur); + if (next && !teco_string_cmp(next->key, cur->key.data, cur->key.len)) + /* filter out duplicates */ + continue; if (restrict_len && g_utf8_strlen(cur->key.data, cur->key.len) != restrict_len) continue; -- cgit v1.2.3