From 65d0847af82ba6189817dfab4485de111e299634 Mon Sep 17 00:00:00 2001 From: Randy Palamar Date: Wed, 17 Dec 2025 16:29:06 -0700 Subject: vis-marks: greatly simplify jumplist management As far as I could tell from the code this was supposed to be a fixed size LRU cache of sets of selection regions. The structure had a maximum size member but it was never set or used. Furthermore there was some very complicated management of 2 parallel sets of regions. Instead of that mess just treat the cache as a circular buffer. Note that this is really not that useful at the moment. While the selection regions are saved and restored the editor mode is not. Therefore the selection is visible but not in any way usable. That will be fixed in the next commit. --- array.c | 18 --------- array.h | 21 ---------- test/core/array-test.c | 8 +--- vis-core.h | 14 ++----- vis-marks.c | 108 +++++++++++++------------------------------------ vis.c | 8 +++- vis.h | 6 +-- 7 files changed, 41 insertions(+), 142 deletions(-) diff --git a/array.c b/array.c index a6de4b1..e60b78e 100644 --- a/array.c +++ b/array.c @@ -141,21 +141,3 @@ void array_sort(Array *arr, int (*compar)(const void*, const void*)) { if (arr->items) qsort(arr->items, arr->len, arr->elem_size, compar); } - -bool array_push(Array *arr, void *item) { - return array_add(arr, item); -} - -void *array_pop(Array *arr) { - void *item = array_peek(arr); - if (!item) - return NULL; - arr->len--; - return item; -} - -void *array_peek(const Array *arr) { - if (arr->len == 0) - return NULL; - return array_get(arr, arr->len - 1); -} diff --git a/array.h b/array.h index 9deac45..67fe7a5 100644 --- a/array.h +++ b/array.h @@ -101,26 +101,5 @@ VIS_INTERNAL bool array_resize(Array*, size_t length); * Sort array, the comparision function works as for `qsort(3)`. */ VIS_INTERNAL void array_sort(Array*, int (*compar)(const void*, const void*)); -/** - * Push item onto the top of the stack. - * @rst - * .. note:: Is equivalent to ``array_add(arr, item)``. - * @endrst - */ -VIS_INTERNAL bool array_push(Array*, void *item); -/** - * Get and remove item at the top of the stack. - * @rst - * .. warning:: The same ownership rules as for ``array_get`` apply. - * @endrst - */ -VIS_INTERNAL void *array_pop(Array*); -/** - * Get item at the top of the stack without removing it. - * @rst - * .. warning:: The same ownership rules as for ``array_get`` apply. - * @endrst - */ -VIS_INTERNAL void *array_peek(const Array*); #endif diff --git a/test/core/array-test.c b/test/core/array-test.c index 5944904..77d9d36 100644 --- a/test/core/array-test.c +++ b/test/core/array-test.c @@ -22,8 +22,6 @@ static void test_small_objects(void) { ok(arr.len == 0, "Initialization"); ok(!array_set(&arr, 0, NULL) && errno == EINVAL, "Set with invalid index"); ok(array_get(&arr, 0) == NULL && errno == EINVAL, "Get with invalid index"); - ok(array_peek(&arr) == NULL && arr.len == 0, "Peek empty array"); - ok(array_pop(&arr) == NULL && arr.len == 0, "Pop empty array"); for (size_t i = 0; i < len; i++) { int *v; @@ -44,11 +42,6 @@ static void test_small_objects(void) { "Get array element: %zu = %d", i, *v); } - int *v; - ok((v = array_peek(&arr)) && *v == values[0] && arr.len == len, "Peek populated array"); - ok((v = array_pop(&arr)) && *v == values[0] && arr.len == len-1, "Pop populated array"); - ok((v = array_peek(&arr)) && *v == values[1] && arr.len == len-1, "Peek after pop"); - array_clear(&arr); ok(arr.len == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Clear"); @@ -66,6 +59,7 @@ static void test_small_objects(void) { ok(!array_remove(&arr, arr.len) && errno == EINVAL, "Remove past end of array"); + int *v; size_t len_before = arr.len; ok(array_remove(&arr, 2) && arr.len == len_before-1 && (v = array_get(&arr, 0)) && *v == values[0] && diff --git a/vis-core.h b/vis-core.h index 6c54640..6e601ab 100644 --- a/vis-core.h +++ b/vis-core.h @@ -131,12 +131,6 @@ typedef struct { enum SamError error; /* non-zero in case something went wrong */ } Transcript; -typedef struct { - Array prev; - Array next; - size_t max; -} MarkList; - struct File { /* shared state among windows displaying the same file */ Text *text; /* data structure holding the file content */ const char *name; /* file name used when loading/saving */ @@ -161,12 +155,15 @@ struct Win { bool expandtab; /* whether typed tabs should be converted to spaces in this window*/ Vis *vis; /* editor instance to which this window belongs */ File *file; /* file being displayed in this window */ - MarkList jumplist; /* LRU jump management */ Array saved_selections; /* register used to store selections */ Mode modes[VIS_MODE_INVALID]; /* overlay mods used for per window key bindings */ Win *parent; /* window which was active when showing the command prompt */ Mode *parent_mode; /* mode which was active when showing the command prompt */ Win *prev, *next; /* neighbouring windows */ + + /* Jumplist LRU */ + size_t mark_set_lru_cursor; + Array mark_set_lru[32]; }; struct Vis { @@ -283,9 +280,6 @@ VIS_INTERNAL void register_release(Register*); VIS_INTERNAL void mark_init(Array*); VIS_INTERNAL void mark_release(Array*); -VIS_INTERNAL void marklist_init(MarkList*, size_t max); -VIS_INTERNAL void marklist_release(MarkList*); - VIS_INTERNAL const char *register_get(Vis*, Register*, size_t *len); VIS_INTERNAL const char *register_slot_get(Vis*, Register*, size_t slot, size_t *len); diff --git a/vis-marks.c b/vis-marks.c index 6d63877..a44e727 100644 --- a/vis-marks.c +++ b/vis-marks.c @@ -104,115 +104,61 @@ void vis_mark_set(Win *win, enum VisMark id, Array *sel) { mark_set(win, mark_from(win->vis, id), sel); } -void marklist_init(MarkList *list, size_t max) { - Array mark; - mark_init(&mark); - array_init_sized(&list->prev, sizeof(Array)); - array_reserve(&list->prev, max); - array_add(&list->prev, &mark); - array_init_sized(&list->next, sizeof(Array)); - array_reserve(&list->next, max); -} - -void marklist_release(MarkList *list) { - for (size_t i = 0, len = list->prev.len; i < len; i++) - array_release(array_get(&list->prev, i)); - array_release(&list->prev); - for (size_t i = 0, len = list->next.len; i < len; i++) - array_release(array_get(&list->next, i)); - array_release(&list->next); -} - -static bool marklist_push(Win *win, MarkList *list, Array *sel) { - Array *top = array_peek(&list->prev); - if (top) { +void vis_jumplist_save(Vis *vis) +{ + Win *win = vis->win; + Array sel = view_selections_get_all(&win->view); + Array *top = win->mark_set_lru + (win->mark_set_lru_cursor % LENGTH(win->mark_set_lru)); + bool done = false; + if (top->len) { Array top_sel = mark_get(win, top); - bool eq = vis_mark_equal(&top_sel, sel); + /* NOTE: avoid pushing duplicate sets into cache */ + done = vis_mark_equal(&top_sel, &sel); array_release(&top_sel); - if (eq) - return true; } - for (size_t i = 0, len = list->next.len; i < len; i++) - array_release(array_get(&list->next, i)); - array_clear(&list->next); - Array arr; - mark_init(&arr); - if (list->prev.len >= list->prev.count) { - Array *tmp = array_get(&list->prev, 0); - arr = *tmp; - array_remove(&list->prev, 0); + if (!done) { + Array *arr = win->mark_set_lru + (win->mark_set_lru_cursor++ % LENGTH(win->mark_set_lru)); + mark_set(win, arr, &sel); } - mark_set(win, &arr, sel); - return array_push(&list->prev, &arr); -} -bool vis_jumplist_save(Vis *vis) { - Array sel = view_selections_get_all(&vis->win->view); - bool ret = marklist_push(vis->win, &vis->win->jumplist, &sel); array_release(&sel); - return ret; } -static bool marklist_prev(Win *win, MarkList *list) { +void vis_jumplist_prev(Vis *vis) +{ + Win *win = vis->win; View *view = &win->view; - bool restore = false; Array cur = view_selections_get_all(view); bool anchored = view_selections_primary_get(view)->anchored; - Array *top = array_peek(&list->prev); - if (!top) - goto out; - Array top_sel = mark_get(win, top); - restore = !vis_mark_equal(&top_sel, &cur); - if (restore) - view_selections_set_all(view, &top_sel, anchored); - array_release(&top_sel); - if (restore) - goto out; - - while (list->prev.len > 1) { - Array *prev = array_pop(&list->prev); - array_push(&list->next, prev); - prev = array_peek(&list->prev); - Array sel = mark_get(win, prev); - restore = sel.len > 0; - if (restore) + + Array *top = win->mark_set_lru + (--win->mark_set_lru_cursor % LENGTH(win->mark_set_lru)); + if (top->len) { + Array sel = mark_get(win, top); + if (!vis_mark_equal(top, &cur)) { view_selections_set_all(view, &sel, anchored); + } array_release(&sel); - if (restore) - goto out; } -out: array_release(&cur); - return restore; } -static bool marklist_next(Win *win, MarkList *list) { +void vis_jumplist_next(Vis *vis) +{ + Win *win = vis->win; View *view = &win->view; bool anchored = view_selections_primary_get(view)->anchored; - for (;;) { - Array *next = array_pop(&list->next); - if (!next) - return false; + Array *next = win->mark_set_lru + (win->mark_set_lru_cursor++ % LENGTH(win->mark_set_lru)); + + if (next->len) { Array sel = mark_get(win, next); if (sel.len > 0) { view_selections_set_all(view, &sel, anchored); array_release(&sel); - array_push(&list->prev, next); - return true; } - array_release(next); } } -bool vis_jumplist_prev(Vis *vis) { - return marklist_prev(vis->win, &vis->win->jumplist); -} - -bool vis_jumplist_next(Vis *vis) { - return marklist_next(vis->win, &vis->win->jumplist); -} - enum VisMark vis_mark_from(Vis *vis, char mark) { if (mark >= 'a' && mark <= 'z') return VIS_MARK_a + mark - 'a'; diff --git a/vis.c b/vis.c index 5d1591d..d38b367 100644 --- a/vis.c +++ b/vis.c @@ -204,7 +204,8 @@ static void window_free(Win *win) { view_free(&win->view); for (size_t i = 0; i < LENGTH(win->modes); i++) map_free(win->modes[i].bindings); - marklist_release(&win->jumplist); + for (int i = 0; i < LENGTH(win->mark_set_lru); i++) + free(win->mark_set_lru[i].items); mark_release(&win->saved_selections); free(win); } @@ -383,7 +384,10 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { window_free(win); return NULL; } - marklist_init(&win->jumplist, 32); + + for (int i = 0; i < LENGTH(win->mark_set_lru); i++) + win->mark_set_lru[i].elem_size = sizeof(SelectionRegion); + mark_init(&win->saved_selections); file->refcount++; win_options_set(win, win->options); diff --git a/vis.h b/vis.h index 0b1c331..272df07 100644 --- a/vis.h +++ b/vis.h @@ -960,17 +960,17 @@ VIS_EXPORT void vis_mark_normalize(Array *array); * Add selections of focused window to jump list. * @param vis The editor instance. */ -VIS_EXPORT bool vis_jumplist_save(Vis*); +VIS_EXPORT void vis_jumplist_save(Vis*); /** * Navigate jump list backwards. * @param vis The editor instance. */ -VIS_EXPORT bool vis_jumplist_prev(Vis*); +VIS_EXPORT void vis_jumplist_prev(Vis*); /** * Navigate jump list forwards. * @param vis The editor instance. */ -VIS_EXPORT bool vis_jumplist_next(Vis*); +VIS_EXPORT void vis_jumplist_next(Vis*); /** @} */ /* -- cgit v1.2.3