aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c5
-rw-r--r--sam.c15
-rw-r--r--vis-core.h10
-rw-r--r--vis-lua.c20
-rw-r--r--vis-motions.c13
-rw-r--r--vis-registers.c39
-rw-r--r--vis.c20
-rw-r--r--vis.h4
8 files changed, 81 insertions, 45 deletions
diff --git a/main.c b/main.c
index fc6e0a0..3dd9d81 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
diff --git a/sam.c b/sam.c
index fdbc4e4..d5b7bf5 100644
--- a/sam.c
+++ b/sam.c
@@ -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]) {
diff --git a/vis-core.h b/vis-core.h
index 8d95f97..024261c 100644
--- a/vis-core.h
+++ b/vis-core.h
@@ -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);
diff --git a/vis-lua.c b/vis-lua.c
index 0866c1b..91ad645 100644
--- a/vis-lua.c
+++ b/vis-lua.c
@@ -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(&reg->selections, sizeof(SelectionRegion));
array_init_sized(&reg->values, sizeof(Buffer));
return array_add(&reg->values, &buf);
}
@@ -37,13 +36,22 @@ bool register_init(Register *reg) {
void register_release(Register *reg) {
if (!reg)
return;
- array_release(&reg->selections);
size_t n = array_capacity(&reg->values);
for (size_t i = 0; i < n; i++)
buffer_release(array_get(&reg->values, i));
array_release(&reg->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(&reg->selections);
+ size_t len = array_length(mark);
array_reserve(&sel, len);
for (size_t i = 0; i < len; i++) {
- SelectionRegion *sr = array_get(&reg->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(&reg->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(&reg->selections, &ss);
+ array_add(mark, &ss);
}
}
diff --git a/vis.c b/vis.c
index 1e25a1b..5424f40 100644
--- a/vis.c
+++ b/vis.c
@@ -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;
}
diff --git a/vis.h b/vis.h
index 4518b65..c53c245 100644
--- a/vis.h
+++ b/vis.h
@@ -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,