diff --git a/config.def.h b/config.def.h index 0ea03c993..e106b521e 100644 --- a/config.def.h +++ b/config.def.h @@ -247,7 +247,7 @@ static const KeyBinding bindings_normal[] = { { "g+", ACTION(LATER) }, { "gn", ALIAS("vgn") }, { "gN", ALIAS("vgN") }, - { "gv", ACTION(SELECTION_RESTORE) }, + { "gv", ALIAS("\"^Sv") }, { "I", ACTION(INSERT_LINE_START) }, { "i", ACTION(MODE_INSERT) }, { "J", ACTION(JOIN_LINES) }, diff --git a/main.c b/main.c index bbba81cc0..a9e965815 100644 --- a/main.c +++ b/main.c @@ -114,8 +114,6 @@ static const char *movement(Vis*, const char *keys, const Arg *arg); static const char *textobj(Vis*, const char *keys, const Arg *arg); /* move to the other end of selected text */ static const char *selection_end(Vis*, const char *keys, const Arg *arg); -/* restore least recently used selection */ -static const char *selection_restore(Vis*, const char *keys, const Arg *arg); /* use register indicated by keys for the current operator */ static const char *reg(Vis*, const char *keys, const Arg *arg); /* perform arg->i motion with a mark indicated by keys as argument */ @@ -265,7 +263,6 @@ enum { VIS_ACTION_PROMPT_SHOW, VIS_ACTION_REPEAT, VIS_ACTION_SELECTION_FLIP, - VIS_ACTION_SELECTION_RESTORE, VIS_ACTION_WINDOW_REDRAW_TOP, VIS_ACTION_WINDOW_REDRAW_CENTER, VIS_ACTION_WINDOW_REDRAW_BOTTOM, @@ -913,11 +910,6 @@ static const KeyAction vis_action[] = { VIS_HELP("Flip selection, move cursor to other end") selection_end, }, - [VIS_ACTION_SELECTION_RESTORE] = { - "vis-selection-restore", - VIS_HELP("Restore last selection") - selection_restore, - }, [VIS_ACTION_WINDOW_REDRAW_TOP] = { "vis-window-redraw-top", VIS_HELP("Redraw cursor line at the top of the window") @@ -2025,19 +2017,6 @@ static const char *selection_end(Vis *vis, const char *keys, const Arg *arg) { return keys; } -static const char *selection_restore(Vis *vis, const char *keys, const Arg *arg) { - Text *txt = vis_text(vis); - View *view = vis_view(vis); - for (Selection *s = view_selections(view); s; s = view_selections_next(s)) - view_selections_restore(s); - Filerange sel = view_selection_get(view); - if (text_range_is_linewise(txt, &sel)) - vis_mode_switch(vis, VIS_MODE_VISUAL_LINE); - else - vis_mode_switch(vis, VIS_MODE_VISUAL); - return keys; -} - static const char *reg(Vis *vis, const char *keys, const Arg *arg) { if (!keys[0]) return NULL; diff --git a/view.c b/view.c index 4a3e18cc4..40ae9f147 100644 --- a/view.c +++ b/view.c @@ -49,7 +49,6 @@ struct Selection { Line *line; /* screen line on which cursor currently resides */ int generation; /* used to filter out newly created cursors during iteration */ int number; /* how many cursors are located before this one */ - SelectionRegion region; /* saved selection region */ View *view; /* associated view to which this cursor belongs */ Selection *prev, *next; /* previous/next cursors ordered by location at creation time */ }; @@ -1230,11 +1229,6 @@ bool view_selections_set(Selection *s, const Filerange *r) { return true; } -void view_selections_save(Selection *s) { - s->region.cursor = s->cursor; - s->region.anchor = s->anchor; -} - Filerange view_regions_restore(View *view, SelectionRegion *s) { Text *txt = view->text; size_t anchor = text_mark_get(txt, s->anchor); @@ -1258,20 +1252,6 @@ bool view_regions_save(View *view, Filerange *r, SelectionRegion *s) { return true; } -bool view_selections_restore(Selection *s) { - Text *txt = s->view->text; - size_t pos = text_mark_get(txt, s->region.cursor); - if (pos == EPOS) - return false; - if (s->region.anchor != s->region.cursor && text_mark_get(txt, s->region.anchor) == EPOS) - return false; - s->cursor = s->region.cursor; - s->anchor = s->region.anchor; - s->anchored = true; - view_cursors_to(s, pos); - return true; -} - void view_selections_set_all(View *view, Array *arr) { Selection *s; Filerange *r; diff --git a/view.h b/view.h index 4d473aa3f..60a41f913 100644 --- a/view.h +++ b/view.h @@ -346,16 +346,6 @@ Filerange view_selection_get(View*); * @defgroup view_save * @{ */ -/** Save selection which can later be restored. */ -void view_selections_save(Selection*); -/** - * Restore a previously active selection. - * @rst - * .. note:: Fails if selection boundaries no longer exist. - * @endrst - */ -bool view_selections_restore(Selection*); - Filerange view_regions_restore(View*, SelectionRegion*); bool view_regions_save(View*, Filerange*, SelectionRegion*); /** diff --git a/vis-core.h b/vis-core.h index cd93096a3..8d95f9724 100644 --- a/vis-core.h +++ b/vis-core.h @@ -162,6 +162,7 @@ struct Win { View *view; /* currently displayed part of underlying text */ RingBuffer *jumplist; /* LRU jump management */ ChangeList changelist; /* state for iterating through least recently changes */ + Register reg_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 */ diff --git a/vis-modes.c b/vis-modes.c index 6fd05b7a5..d6ea13491 100644 --- a/vis-modes.c +++ b/vis-modes.c @@ -201,7 +201,8 @@ static void vis_mode_visual_line_enter(Vis *vis, Mode *old) { static void vis_mode_visual_line_leave(Vis *vis, Mode *new) { if (!new->visual) { - window_selection_save(vis->win); + if (!vis->action.op) + window_selection_save(vis->win); view_selections_clear_all(vis->win->view); } else { view_cursor_to(vis->win->view, view_cursor_get(vis->win->view)); @@ -210,7 +211,8 @@ static void vis_mode_visual_line_leave(Vis *vis, Mode *new) { static void vis_mode_visual_leave(Vis *vis, Mode *new) { if (!new->visual) { - window_selection_save(vis->win); + if (!vis->action.op) + window_selection_save(vis->win); view_selections_clear_all(vis->win->view); } } diff --git a/vis-registers.c b/vis-registers.c index 595bb5b64..d20c76cea 100644 --- a/vis-registers.c +++ b/vis-registers.c @@ -221,6 +221,8 @@ enum VisRegister vis_register_used(Vis *vis) { } static Register *register_from(Vis *vis, enum VisRegister id) { + if (id == VIS_REG_SELECTION && vis->win) + return &vis->win->reg_selections; if (VIS_REG_A <= id && id <= VIS_REG_Z) id = VIS_REG_a + id - VIS_REG_A; if (id < LENGTH(vis->registers)) @@ -300,4 +302,5 @@ const RegisterDef vis_registers[] = { [VIS_REG_COMMAND] = { ':', VIS_HELP("Last :-command") }, [VIS_REG_SHELL] = { '!', VIS_HELP("Last shell command given to either <, >, |, or !") }, [VIS_REG_NUMBER] = { '#', VIS_HELP("Register number") }, + [VIS_REG_SELECTION] = { '^', VIS_HELP("Last selections") }, }; diff --git a/vis.c b/vis.c index 969a74d76..1e25a1b1d 100644 --- a/vis.c +++ b/vis.c @@ -246,14 +246,10 @@ void vis_window_status(Win *win, const char *status) { void window_selection_save(Win *win) { Vis *vis = win->vis; - File *file = win->file; - Filerange sel = view_selections_get(view_selections(win->view)); - file->marks[VIS_MARK_SELECTION_START] = text_mark_set(file->text, sel.start); - file->marks[VIS_MARK_SELECTION_END] = text_mark_set(file->text, sel.end); - if (!vis->action.op) { - for (Selection *s = view_selections(win->view); s; s = view_selections_next(s)) - view_selections_save(s); - } + View *view = win->view; + Array sel = view_selections_get_all(view); + vis_register_selections_set(vis, VIS_REG_SELECTION, &sel); + array_release(&sel); } static void window_free(Win *win) { @@ -270,6 +266,7 @@ static void window_free(Win *win) { for (size_t i = 0; i < LENGTH(win->modes); i++) map_free(win->modes[i].bindings); ringbuf_free(win->jumplist); + register_release(&win->reg_selections); free(win); } @@ -467,6 +464,7 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { window_free(win); return NULL; } + register_init(&win->reg_selections); file->refcount++; view_options_set(win->view, view_options_get(win->view)); view_tabwidth_set(win->view, vis->tabwidth); @@ -845,6 +843,9 @@ void vis_do(Vis *vis) { if (a->op == &vis_operators[VIS_OP_PUT_AFTER] && multiple_cursors && vis_register_count(vis, reg) == 1) reg_slot = 0; + if (vis->mode->visual && a->op) + window_selection_save(win); + for (Selection *sel = view_selections(view), *next; sel; sel = next) { if (vis->interrupted) break; @@ -982,11 +983,8 @@ void vis_do(Vis *vis) { if (pos == EPOS) { view_selections_dispose(sel); } else if (pos <= text_size(txt)) { - if (vis->mode->visual) - view_selections_save(sel); + view_selection_clear(sel); view_cursors_to(sel, pos); - if (vis->mode->visual) - view_selection_clear(sel); } } } diff --git a/vis.h b/vis.h index 32dce8091..4518b65d1 100644 --- a/vis.h +++ b/vis.h @@ -719,6 +719,7 @@ enum VisRegister { VIS_REG_COMMAND, /* last used :-command ": */ VIS_REG_SHELL, /* last used shell command given to either <, >, |, or ! */ VIS_REG_NUMBER, /* cursor number */ + VIS_REG_SELECTION, /* last used selections */ VIS_REG_a, VIS_REG_b, VIS_REG_c, VIS_REG_d, VIS_REG_e, VIS_REG_f, VIS_REG_g, VIS_REG_h, VIS_REG_i, VIS_REG_j, VIS_REG_k, VIS_REG_l, VIS_REG_m, VIS_REG_n, VIS_REG_o,