diff options
| -rw-r--r-- | main.c | 7 | ||||
| -rw-r--r-- | vis-core.h | 15 | ||||
| -rw-r--r-- | vis-marks.c | 66 | ||||
| -rw-r--r-- | vis.c | 8 | ||||
| -rw-r--r-- | vis.h | 14 |
5 files changed, 45 insertions, 65 deletions
@@ -1247,12 +1247,7 @@ static KEY_ACTION_FN(ka_percent) static KEY_ACTION_FN(ka_jumplist) { - if (arg->i < 0) - vis_jumplist_prev(vis); - else if (arg->i > 0) - vis_jumplist_next(vis); - else - vis_jumplist_save(vis); + vis_jumplist(vis, arg->i); return keys; } @@ -161,9 +161,18 @@ struct Win { 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]; + /* NOTE: Selection Jump Cache + * Anytime the selection jumps the previous set of selections gets + * pushed into this cache. The user can navigate this cache to + * restore old selections and they can save their own selection + * sets into the cache. + * + * IMPORTANT: cursor is not kept in bounds. it is always used modulo VIS_MARK_SET_LRU_COUNT + */ + #define VIS_MARK_SET_LRU_COUNT (32) + size_t mark_set_lru_cursor; + Array mark_set_lru_regions[VIS_MARK_SET_LRU_COUNT]; + enum VisMode mark_set_lru_modes[VIS_MARK_SET_LRU_COUNT]; }; struct Vis { diff --git a/vis-marks.c b/vis-marks.c index a44e727..083d331 100644 --- a/vis-marks.c +++ b/vis-marks.c @@ -104,59 +104,39 @@ void vis_mark_set(Win *win, enum VisMark id, Array *sel) { mark_set(win, mark_from(win->vis, id), sel); } -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); - /* NOTE: avoid pushing duplicate sets into cache */ - done = vis_mark_equal(&top_sel, &sel); - array_release(&top_sel); - } - - if (!done) { - Array *arr = win->mark_set_lru + (win->mark_set_lru_cursor++ % LENGTH(win->mark_set_lru)); - mark_set(win, arr, &sel); - } - - array_release(&sel); -} - -void vis_jumplist_prev(Vis *vis) +void vis_jumplist(Vis *vis, int advance) { Win *win = vis->win; View *view = &win->view; Array cur = view_selections_get_all(view); - bool anchored = view_selections_primary_get(view)->anchored; - 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); - } - array_release(&cur); -} - -void vis_jumplist_next(Vis *vis) -{ - Win *win = vis->win; - View *view = &win->view; - bool anchored = view_selections_primary_get(view)->anchored; - Array *next = win->mark_set_lru + (win->mark_set_lru_cursor++ % LENGTH(win->mark_set_lru)); + size_t cursor = win->mark_set_lru_cursor; + win->mark_set_lru_cursor += advance; + if (advance < 0) + cursor = win->mark_set_lru_cursor; + cursor %= VIS_MARK_SET_LRU_COUNT; + Array *next = win->mark_set_lru_regions + cursor; + bool done = false; if (next->len) { Array sel = mark_get(win, next); - if (sel.len > 0) { - view_selections_set_all(view, &sel, anchored); - array_release(&sel); + done = vis_mark_equal(&sel, &cur); + if (advance && !done) { + /* NOTE: set cached selection */ + vis_mode_switch(vis, win->mark_set_lru_modes[cursor]); + view_selections_set_all(view, &sel, view_selections_primary_get(view)->anchored); } + array_release(&sel); + } + + if (!advance && !done) { + /* NOTE: save the current selection */ + mark_set(win, next, &cur); + win->mark_set_lru_modes[cursor] = vis->mode->id; + win->mark_set_lru_cursor++; } + + array_release(&cur); } enum VisMark vis_mark_from(Vis *vis, char mark) { @@ -204,8 +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); - for (int i = 0; i < LENGTH(win->mark_set_lru); i++) - free(win->mark_set_lru[i].items); + for (int i = 0; i < VIS_MARK_SET_LRU_COUNT; i++) + free(win->mark_set_lru_regions[i].items); mark_release(&win->saved_selections); free(win); } @@ -385,8 +385,8 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { return NULL; } - for (int i = 0; i < LENGTH(win->mark_set_lru); i++) - win->mark_set_lru[i].elem_size = sizeof(SelectionRegion); + for (int i = 0; i < VIS_MARK_SET_LRU_COUNT; i++) + win->mark_set_lru_regions[i].elem_size = sizeof(SelectionRegion); mark_init(&win->saved_selections); file->refcount++; @@ -957,20 +957,16 @@ VIS_EXPORT Array vis_mark_get(Win *win, enum VisMark id); */ VIS_EXPORT void vis_mark_normalize(Array *array); /** - * Add selections of focused window to jump list. + * Add selections of focused window to jump list. Equivalent to vis_jumplist(vis, 0). * @param vis The editor instance. */ -VIS_EXPORT void vis_jumplist_save(Vis*); +#define vis_jumplist_save(vis) vis_jumplist((vis), 0) /** - * Navigate jump list backwards. + * Navigate jump list by a specified amount. Wraps if advance exceeds list size. * @param vis The editor instance. + * @param advance The amount to advance the cursor by. 0 saves the current selections. */ -VIS_EXPORT void vis_jumplist_prev(Vis*); -/** - * Navigate jump list forwards. - * @param vis The editor instance. - */ -VIS_EXPORT void vis_jumplist_next(Vis*); +VIS_EXPORT void vis_jumplist(Vis *, int advance); /** @} */ /* |
