aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README5
-rw-r--r--config.def.h2
-rw-r--r--editor.c28
-rw-r--r--editor.h9
-rw-r--r--text.c12
-rw-r--r--text.h3
-rw-r--r--vis.c14
7 files changed, 70 insertions, 3 deletions
diff --git a/README b/README
index 9874fbe..45d5045 100644
--- a/README
+++ b/README
@@ -480,8 +480,9 @@ and their current support in vis.
Jump list and change list
-------------------------
- A per window, fixed size, file local jump list is implemented.
- The change list is currently not supported.
+ A per window, file local jump list (navigate with CTRL+O and CTRL+I)
+ and change list (navigate with g; and g,) is supported. The jump
+ list is implemented as a fixed sized ring buffer.
Mouse support
-------------
diff --git a/config.def.h b/config.def.h
index 655671f..db41216 100644
--- a/config.def.h
+++ b/config.def.h
@@ -384,6 +384,8 @@ static KeyBinding vis_mode_normal[] = {
{ { CONTROL('Y') }, wslide, { .i = +1 } },
{ { CONTROL('O') }, jumplist, { .i = -1 } },
{ { CONTROL('I') }, jumplist, { .i = +1 } },
+ { { NONE('g'), NONE(';') }, changelist, { .i = -1 } },
+ { { NONE('g'), NONE(',') }, changelist, { .i = +1 } },
{ { NONE('a') }, insertmode, { .i = MOVE_CHAR_NEXT } },
{ { NONE('A') }, insertmode, { .i = MOVE_LINE_END } },
{ { NONE('C') }, change, { .i = MOVE_LINE_END } },
diff --git a/editor.c b/editor.c
index ef59242..e472351 100644
--- a/editor.c
+++ b/editor.c
@@ -172,6 +172,34 @@ void editor_window_jumplist_invalidate(EditorWin *win) {
ringbuf_invalidate(win->jumplist);
}
+size_t editor_window_changelist_prev(EditorWin *win) {
+ size_t pos = window_cursor_get(win->win);
+ if (pos != win->changelist.pos)
+ win->changelist.index = 0;
+ else
+ win->changelist.index++;
+ size_t newpos = text_history_get(win->text, win->changelist.index);
+ if (newpos == EPOS)
+ win->changelist.index--;
+ else
+ win->changelist.pos = newpos;
+ return win->changelist.pos;
+}
+
+size_t editor_window_changelist_next(EditorWin *win) {
+ size_t pos = window_cursor_get(win->win);
+ if (pos != win->changelist.pos)
+ win->changelist.index = 0;
+ else if (win->changelist.index > 0)
+ win->changelist.index--;
+ size_t newpos = text_history_get(win->text, win->changelist.index);
+ if (newpos == EPOS)
+ win->changelist.index++;
+ else
+ win->changelist.pos = newpos;
+ return win->changelist.pos;
+}
+
void editor_resize(Editor *ed, int width, int height) {
ed->width = width;
ed->height = height;
diff --git a/editor.h b/editor.h
index 2cc097f..2be3fa6 100644
--- a/editor.h
+++ b/editor.h
@@ -13,11 +13,17 @@
typedef struct Editor Editor;
typedef struct EditorWin EditorWin;
+typedef struct {
+ size_t index; /* #number of changes */
+ size_t pos; /* where the current change occured */
+} ChangeList;
+
struct EditorWin {
Editor *editor; /* editor instance to which this window belongs */
Text *text; /* underlying text management */
Win *win; /* window for the text area */
RingBuffer *jumplist; /* LRU jump management */
+ ChangeList changelist; /* state for iterating through least recently changes */
WINDOW *statuswin; /* curses window for the statusbar */
int width, height; /* window size including the statusbar */
EditorWin *prev, *next; /* neighbouring windows */
@@ -158,6 +164,9 @@ void editor_window_jumplist_add(EditorWin*, size_t pos);
size_t editor_window_jumplist_prev(EditorWin*);
size_t editor_window_jumplist_next(EditorWin*);
void editor_window_jumplist_invalidate(EditorWin*);
+
+size_t editor_window_changelist_prev(EditorWin*);
+size_t editor_window_changelist_next(EditorWin*);
/* rearrange all windows either vertically or horizontally */
void editor_windows_arrange_vertical(Editor*);
void editor_windows_arrange_horizontal(Editor*);
diff --git a/text.c b/text.c
index 7d17bbf..9afab01 100644
--- a/text.c
+++ b/text.c
@@ -1177,6 +1177,18 @@ void text_mark_intern_clear_all(Text *txt) {
text_mark_intern_clear(txt, mark);
}
+size_t text_history_get(Text *txt, size_t index) {
+ for (Action *a = txt->current_action ? txt->current_action : txt->undo; a; a = a->next) {
+ if (index-- == 0) {
+ Change *c = a->change;
+ while (c && c->next)
+ c = c->next;
+ return c ? c->pos : EPOS;
+ }
+ }
+ return EPOS;
+}
+
int text_fd_get(Text *txt) {
return txt->fd;
}
diff --git a/text.h b/text.h
index 5156d84..faa340c 100644
--- a/text.h
+++ b/text.h
@@ -83,6 +83,9 @@ size_t text_mark_intern_get(Text*, MarkIntern);
void text_mark_intern_clear(Text*, MarkIntern);
void text_mark_intern_clear_all(Text*);
+/* get position of change denoted by index, where 0 indicates the most recent */
+size_t text_history_get(Text*, size_t index);
+
size_t text_size(Text*);
bool text_modified(Text*);
/* test whether the underlying file uses UNIX style \n or Windows style \r\n newlines */
diff --git a/vis.c b/vis.c
index c0da6ac..aa37cb8 100644
--- a/vis.c
+++ b/vis.c
@@ -385,8 +385,10 @@ static TextObject *moves_linewise[] = {
};
/** functions to be called from keybindings */
-/* navigate jumplist either in forward (arg->i>0) or backward (arg->i<0) direction */
+/* navigate jump list either in forward (arg->i>0) or backward (arg->i<0) direction */
static void jumplist(const Arg *arg);
+/* navigate change list either in forward (arg->i>0) or backward (arg->i<0) direction */
+static void changelist(const Arg *arg);
static void macro_record(const Arg *arg);
static void macro_replay(const Arg *arg);
/* temporarily suspend the editor and return to the shell, type 'fg' to get back */
@@ -810,6 +812,16 @@ static void jumplist(const Arg *arg) {
window_cursor_to(vis->win->win, pos);
}
+static void changelist(const Arg *arg) {
+ size_t pos;
+ if (arg->i > 0)
+ pos = editor_window_changelist_next(vis->win);
+ else
+ pos = editor_window_changelist_prev(vis->win);
+ if (pos != EPOS)
+ window_cursor_to(vis->win->win, pos);
+}
+
static Macro *key2macro(const Arg *arg) {
if (arg->i)
return &vis->macros[arg->i];