aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c7
-rw-r--r--vis-core.h15
-rw-r--r--vis-marks.c66
-rw-r--r--vis.c8
-rw-r--r--vis.h14
5 files changed, 45 insertions, 65 deletions
diff --git a/main.c b/main.c
index e336916..1aade34 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
diff --git a/vis-core.h b/vis-core.h
index 6e601ab..82e684a 100644
--- a/vis-core.h
+++ b/vis-core.h
@@ -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) {
diff --git a/vis.c b/vis.c
index d38b367..5b5ce2f 100644
--- a/vis.c
+++ b/vis.c
@@ -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++;
diff --git a/vis.h b/vis.h
index 272df07..72f6ec5 100644
--- a/vis.h
+++ b/vis.h
@@ -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);
/** @} */
/*