diff options
| -rw-r--r-- | main.c | 5 | ||||
| -rw-r--r-- | sam.c | 15 | ||||
| -rw-r--r-- | vis-core.h | 10 | ||||
| -rw-r--r-- | vis-lua.c | 20 | ||||
| -rw-r--r-- | vis-motions.c | 13 | ||||
| -rw-r--r-- | vis-registers.c | 39 | ||||
| -rw-r--r-- | vis.c | 20 | ||||
| -rw-r--r-- | vis.h | 4 |
8 files changed, 81 insertions, 45 deletions
@@ -2042,7 +2042,10 @@ static const char *mark_set(Vis *vis, const char *keys, const Arg *arg) { return NULL; if (keys[1]) return vis_keys_next(vis, keys); - vis_mark_set(vis, vis_mark_from(vis, keys[0]), view_cursor_get(vis_view(vis))); + View *view = vis_view(vis); + Array sel = view_selections_get_all(view); + vis_register_selections_set(vis, vis_mark_from(vis, keys[0]), &sel); + array_release(&sel); return keys+1; } @@ -1005,7 +1005,7 @@ static Filerange address_line_evaluate(Address *addr, File *file, Filerange *ran return text_range_new(line, text_line_next(txt, line)); } -static Filerange address_evaluate(Address *addr, File *file, Filerange *range, int sign) { +static Filerange address_evaluate(Address *addr, File *file, Selection *sel, Filerange *range, int sign) { Filerange ret = text_range_empty(); do { @@ -1024,7 +1024,12 @@ static Filerange address_evaluate(Address *addr, File *file, Filerange *range, i break; case '\'': { - size_t pos = text_mark_get(file->text, file->marks[addr->number]); + size_t pos = EPOS; + Array *marks = &file->marks[addr->number]; + size_t idx = sel ? view_selections_number(sel) : 0; + SelectionRegion *sr = array_get(marks, idx); + if (sr) + pos = text_mark_get(file->text, sr->cursor); ret = text_range_new(pos, pos); break; } @@ -1057,7 +1062,7 @@ static Filerange address_evaluate(Address *addr, File *file, Filerange *range, i { Filerange left, right; if (addr->left) - left = address_evaluate(addr->left, file, range, 0); + left = address_evaluate(addr->left, file, sel, range, 0); else left = text_range_new(0, 0); @@ -1065,7 +1070,7 @@ static Filerange address_evaluate(Address *addr, File *file, Filerange *range, i range = &left; if (addr->right) { - right = address_evaluate(addr->right, file, range, 0); + right = address_evaluate(addr->right, file, sel, range, 0); } else { size_t size = text_size(file->text); right = text_range_new(size, size); @@ -1093,7 +1098,7 @@ static bool count_evaluate(Command *cmd) { static bool sam_execute(Vis *vis, Win *win, Command *cmd, Selection *sel, Filerange *range) { bool ret = true; if (cmd->address && win) - *range = address_evaluate(cmd->address, win->file, range, 0); + *range = address_evaluate(cmd->address, win->file, sel, range, 0); cmd->iteration++; switch (cmd->argv[0][0]) { @@ -40,7 +40,6 @@ struct Mode { }; typedef struct { - Array selections; Array values; bool linewise; /* place register content on a new line when inserting? */ bool append; @@ -75,7 +74,7 @@ typedef struct { /* Motion implementation, takes a cursor postion and returns a /* TODO: merge types / use union to save space */ size_t (*cur)(Selection*); size_t (*txt)(Text*, size_t pos); - size_t (*file)(Vis*, File*, size_t pos); + size_t (*file)(Vis*, File*, Selection*); size_t (*vis)(Vis*, Text*, size_t pos); size_t (*view)(Vis*, View*); size_t (*win)(Vis*, Win*, size_t pos); @@ -143,7 +142,7 @@ struct File { /* shared state among windows displaying the same file */ bool internal; /* whether it is an internal file (e.g. used for the prompt) */ struct stat stat; /* filesystem information when loaded/saved, used to detect changes outside the editor */ int refcount; /* how many windows are displaying this file? (always >= 1) */ - Mark marks[VIS_MARK_INVALID]; /* marks which are shared across windows */ + Array marks[VIS_MARK_INVALID]; /* marks which are shared across windows */ enum TextSaveMethod save_method; /* whether the file is saved using rename(2) or overwritten */ Transcript transcript; /* keeps track of changes performed by sam commands */ File *next, *prev; @@ -162,7 +161,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 */ + 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 */ @@ -277,6 +276,9 @@ void file_name_set(File*, const char *name); bool register_init(Register*); void register_release(Register*); +void marks_init(Array*); +void mark_release(Array*); + const char *register_get(Vis*, Register*, size_t *len); const char *register_slot_get(Vis*, Register*, size_t slot, size_t *len); @@ -512,7 +512,7 @@ static void pushpos(lua_State *L, size_t pos) { } static void pushrange(lua_State *L, Filerange *r) { - if (!text_range_valid(r)) { + if (!r || !text_range_valid(r)) { lua_pushnil(L); return; } @@ -2245,7 +2245,7 @@ static const struct luaL_Reg file_lines_funcs[] = { }; static int file_marks_index(lua_State *L) { - size_t pos = EPOS; + Filerange *range = NULL; Vis *vis = lua_touserdata(L, lua_upvalueindex(1)); File *file = obj_ref_check_containerof(L, 1, VIS_LUA_TYPE_MARKS, offsetof(File, marks)); if (!file) @@ -2256,9 +2256,11 @@ static int file_marks_index(lua_State *L) { enum VisMark mark = vis_mark_from(vis, symbol[0]); if (mark == VIS_MARK_INVALID) goto err; - pos = text_mark_get(file->text, file->marks[mark]); + Array arr = vis_register_selections_get(vis, mark); + range = array_get(&arr, 0); + array_release(&arr); err: - pushpos(L, pos); + pushrange(L, range); return 1; } @@ -2272,8 +2274,14 @@ static int file_marks_newindex(lua_State *L) { return 0; enum VisMark mark = vis_mark_from(vis, symbol[0]); size_t pos = luaL_checkunsigned(L, 3); - if (mark < LENGTH(file->marks)) - file->marks[mark] = text_mark_set(file->text, pos); + if (mark < LENGTH(file->marks)) { + Array arr; + array_init_sized(&arr, sizeof(Filerange)); + Filerange range = text_range_new(pos, pos); + array_add(&arr, &range); + vis_register_selections_set(vis, mark, &arr); + array_release(&arr); + } return 0; } diff --git a/vis-motions.c b/vis-motions.c index 9917ce5..b07585b 100644 --- a/vis-motions.c +++ b/vis-motions.c @@ -107,12 +107,17 @@ static size_t longword_next(Vis *vis, Text *txt, size_t pos) { return common_word_next(vis, txt, pos, VIS_MOVE_LONGWORD_END_NEXT); } -static size_t mark_goto(Vis *vis, File *file, size_t pos) { - return text_mark_get(file->text, file->marks[vis->action.mark]); +static size_t mark_goto(Vis *vis, File *file, Selection *sel) { + Array *marks = &file->marks[vis->action.mark]; + size_t idx = view_selections_number(sel); + SelectionRegion *sr = array_get(marks, idx); + if (!sr) + return EPOS; + return text_mark_get(file->text, sr->cursor); } -static size_t mark_line_goto(Vis *vis, File *file, size_t pos) { - return text_line_start(file->text, mark_goto(vis, file, pos)); +static size_t mark_line_goto(Vis *vis, File *file, Selection *sel) { + return text_line_start(file->text, mark_goto(vis, file, sel)); } static size_t to(Vis *vis, Text *txt, size_t pos) { diff --git a/vis-registers.c b/vis-registers.c index d20c76c..9976b3b 100644 --- a/vis-registers.c +++ b/vis-registers.c @@ -29,7 +29,6 @@ static ssize_t read_buffer(void *context, char *data, size_t len) { bool register_init(Register *reg) { Buffer buf; buffer_init(&buf); - array_init_sized(®->selections, sizeof(SelectionRegion)); array_init_sized(®->values, sizeof(Buffer)); return array_add(®->values, &buf); } @@ -37,13 +36,22 @@ bool register_init(Register *reg) { void register_release(Register *reg) { if (!reg) return; - array_release(®->selections); size_t n = array_capacity(®->values); for (size_t i = 0; i < n; i++) buffer_release(array_get(®->values, i)); array_release(®->values); } +void marks_init(Array *arr) { + array_init_sized(arr, sizeof(SelectionRegion)); +} + +void mark_release(Array *arr) { + if (!arr) + return; + array_release(arr); +} + const char *register_slot_get(Vis *vis, Register *reg, size_t slot, size_t *len) { if (len) *len = 0; @@ -220,9 +228,16 @@ enum VisRegister vis_register_used(Vis *vis) { return vis->action.reg - vis->registers; } +static Array *mark_from(Vis *vis, enum VisMark id) { + if (id == VIS_MARK_SELECTION && vis->win) + return &vis->win->saved_selections; + File *file = vis->win->file; + if (id < LENGTH(file->marks)) + return &file->marks[id]; + return NULL; +} + 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)) @@ -252,14 +267,14 @@ const char *vis_register_slot_get(Vis *vis, enum VisRegister id, size_t slot, si Array vis_register_selections_get(Vis *vis, enum VisRegister id) { Array sel; array_init_sized(&sel, sizeof(Filerange)); - Register *reg = register_from(vis, id); - if (!reg) + Array *mark = mark_from(vis, id); + if (!mark) return sel; View *view = vis->win->view; - size_t len = array_length(®->selections); + size_t len = array_length(mark); array_reserve(&sel, len); for (size_t i = 0; i < len; i++) { - SelectionRegion *sr = array_get(®->selections, i); + SelectionRegion *sr = array_get(mark, i); Filerange r = view_regions_restore(view, sr); if (text_range_valid(&r)) array_add(&sel, &r); @@ -269,16 +284,16 @@ Array vis_register_selections_get(Vis *vis, enum VisRegister id) { } void vis_register_selections_set(Vis *vis, enum VisRegister id, Array *sel) { - Register *reg = register_from(vis, id); - if (!reg) + Array *mark = mark_from(vis, id); + if (!mark) return; - array_clear(®->selections); + array_clear(mark); View *view = vis->win->view; for (size_t i = 0, len = array_length(sel); i < len; i++) { SelectionRegion ss; Filerange *r = array_get(sel, i); if (view_regions_save(view, r, &ss)) - array_add(®->selections, &ss); + array_add(mark, &ss); } } @@ -29,8 +29,8 @@ #include "sam.h" const MarkDef vis_marks[] = { - [VIS_MARK_SELECTION_START] = { '<', VIS_HELP("Last selection start") }, - [VIS_MARK_SELECTION_END] = { '>', VIS_HELP("Last selection end") }, + [VIS_MARK_DEFAULT] = { '"', VIS_HELP("Default mark") }, + [VIS_MARK_SELECTION] = { '^', VIS_HELP("Last selections") }, }; static void macro_replay(Vis *vis, const Macro *macro); @@ -119,6 +119,8 @@ static void file_free(Vis *vis, File *file) { return; } vis_event_emit(vis, VIS_EVENT_FILE_CLOSE, file); + for (size_t i = 0; i < LENGTH(file->marks); i++) + mark_release(&file->marks[i]); text_free(file->text); free((char*)file->name); @@ -138,6 +140,8 @@ static File *file_new_text(Vis *vis, Text *text) { file->fd = -1; file->text = text; file->stat = text_stat(text); + for (size_t i = 0; i < LENGTH(file->marks); i++) + marks_init(&file->marks[i]); if (vis->files) vis->files->prev = file; file->next = vis->files; @@ -266,7 +270,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); + mark_release(&win->saved_selections); free(win); } @@ -464,7 +468,7 @@ Win *window_new_file(Vis *vis, File *file, enum UiOption options) { window_free(win); return NULL; } - register_init(&win->reg_selections); + marks_init(&win->saved_selections); file->refcount++; view_options_set(win->view, view_options_get(win->view)); view_tabwidth_set(win->view, vis->tabwidth); @@ -883,7 +887,7 @@ void vis_do(Vis *vis) { else if (a->movement->cur) pos = a->movement->cur(sel); else if (a->movement->file) - pos = a->movement->file(vis, file, pos); + pos = a->movement->file(vis, file, sel); else if (a->movement->vis) pos = a->movement->vis(vis, txt, pos); else if (a->movement->view) @@ -1539,12 +1543,6 @@ enum VisMark vis_mark_from(Vis *vis, char mark) { return VIS_MARK_INVALID; } -void vis_mark_set(Vis *vis, enum VisMark mark, size_t pos) { - File *file = vis->win->file; - if (mark < LENGTH(file->marks)) - file->marks[mark] = text_mark_set(file->text, pos); -} - int vis_count_get(Vis *vis) { return vis->action.count; } @@ -671,8 +671,8 @@ bool vis_textobject(Vis*, enum VisTextObject); /** @} */ /** Mark specifiers. */ enum VisMark { - VIS_MARK_SELECTION_START, /* '< */ - VIS_MARK_SELECTION_END, /* '> */ + VIS_MARK_DEFAULT, + VIS_MARK_SELECTION, VIS_MARK_a, VIS_MARK_b, VIS_MARK_c, VIS_MARK_d, VIS_MARK_e, VIS_MARK_f, VIS_MARK_g, VIS_MARK_h, VIS_MARK_i, VIS_MARK_j, VIS_MARK_k, VIS_MARK_l, VIS_MARK_m, VIS_MARK_n, VIS_MARK_o, |
