aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-09-03 21:35:16 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-09-03 21:35:16 +0200
commit2deb344c3122e91a745734ce77b3e0967f169c2a (patch)
treea01b11949d741cb85219b99176ee0090f8e6817d
parent87ffbb9c0ab201efc3e729876455bc4ca9921124 (diff)
downloadvis-2deb344c3122e91a745734ce77b3e0967f169c2a.tar.gz
vis-2deb344c3122e91a745734ce77b3e0967f169c2a.tar.xz
Rudimentary support for copy / paste via registers
-rw-r--r--config.def.h68
-rw-r--r--register.c6
-rw-r--r--register.h7
-rw-r--r--vis.c1
-rw-r--r--vis.h16
5 files changed, 69 insertions, 29 deletions
diff --git a/config.def.h b/config.def.h
index 1996ecf..fa08c98 100644
--- a/config.def.h
+++ b/config.def.h
@@ -12,6 +12,7 @@
static Mode *mode, *mode_prev;
static Vis *vis;
static Mode vis_modes[];
+static Action action = { .count = 1 }, action_prev = { .count = 1 };
static void switchmode(const Arg *arg);
static void switchmode_to(Mode *new_mode);
@@ -22,6 +23,7 @@ enum {
VIS_MODE_TEXTOBJ,
VIS_MODE_OPERATOR,
VIS_MODE_OPERATOR_OPTION,
+ VIS_MODE_REGISTER,
VIS_MODE_NORMAL,
VIS_MODE_VISUAL,
VIS_MODE_INSERT,
@@ -32,15 +34,14 @@ enum {
OP_DELETE,
OP_CHANGE,
OP_YANK,
+ OP_PASTE,
};
void op_delete(OperatorContext *c) {
- if (c->range.start == (size_t)-1)
- return;
size_t len = c->range.end - c->range.start;
+ register_put(c->reg, vis->win->text, &c->range);
vis_delete(vis, c->range.start, len);
window_cursor_to(vis->win->win, c->range.start);
- vis_draw(vis);
}
void op_change(OperatorContext *c) {
@@ -48,12 +49,21 @@ void op_change(OperatorContext *c) {
switchmode(&(const Arg){ .i = VIS_MODE_INSERT });
}
-void op_yank(OperatorContext *c) {}
+void op_yank(OperatorContext *c) {
+ register_put(c->reg, vis->win->text, &c->range);
+}
+
+void op_paste(OperatorContext *c) {
+ size_t pos = window_cursor_get(vis->win->win);
+ vis_insert(vis, pos, c->reg->data, c->reg->len);
+ window_cursor_to(vis->win->win, pos + c->reg->len);
+}
-static Operator *ops[] = {
- [OP_DELETE] = op_delete,
- [OP_CHANGE] = op_change,
- [OP_YANK] = op_yank,
+static Operator ops[] = {
+ [OP_DELETE] = { op_delete, false },
+ [OP_CHANGE] = { op_change, false },
+ [OP_YANK] = { op_yank, false },
+ [OP_PASTE] = { op_paste, true },
};
enum {
@@ -182,7 +192,7 @@ static void mark_goto(const Arg *arg) {
vis_mark_goto(vis, arg->i);
}
-static Action action, action_prev;
+
void action_do(Action *a);
void action_reset(Action *a);
@@ -200,7 +210,7 @@ static void linewise(const Arg *arg) {
static void operator(const Arg *arg) {
switchmode(&(const Arg){ .i = VIS_MODE_OPERATOR });
- Operator *op = ops[arg->i];
+ Operator *op = &ops[arg->i];
if (action.op == op) {
/* hacky way to handle double operators i.e. things like
* dd, yy etc where the second char isn't a movement */
@@ -208,6 +218,8 @@ static void operator(const Arg *arg) {
action_do(&action);
} else {
action.op = op;
+ if (op->selfcontained)
+ action_do(&action);
}
}
@@ -230,8 +242,12 @@ static void textobj(const Arg *arg) {
action_do(&action);
}
+static void reg(const Arg *arg) {
+ action.reg = &vis->registers[arg->i];
+}
+
void action_reset(Action *a) {
- a->count = 0;
+ a->count = 1;
a->linewise = false;
a->op = NULL;
a->movement = NULL;
@@ -242,11 +258,13 @@ void action_reset(Action *a) {
void action_do(Action *a) {
Text *txt = vis->win->text;
Win *win = vis->win->win;
- OperatorContext c;
size_t pos = window_cursor_get(win);
- c.pos = pos;
- if (a->count == 0)
- a->count = 1;
+ OperatorContext c = {
+ .count = a->count,
+ .pos = pos,
+ .reg = a->reg ? a->reg : &vis->registers[REG_DEFAULT],
+ };
+
if (a->movement) {
size_t start = pos;
for (int i = 0; i < a->count; i++) {
@@ -292,9 +310,8 @@ void action_do(Action *a) {
}
}
- c.count = a->count;
if (a->op) {
- a->op(&c);
+ a->op->func(&c);
if (mode == &vis_modes[VIS_MODE_OPERATOR])
switchmode_to(mode_prev);
}
@@ -304,7 +321,6 @@ void action_do(Action *a) {
action_prev = *a;
action_reset(a);
}
-
}
/* use vim's
@@ -419,6 +435,7 @@ static KeyBinding vis_operators[] = {
{ { NONE('d') }, operator, { .i = OP_DELETE } },
{ { NONE('c') }, operator, { .i = OP_CHANGE } },
{ { NONE('y') }, operator, { .i = OP_YANK } },
+ { { NONE('p') }, operator, { .i = OP_PASTE } },
{ /* empty last element, array terminator */ },
};
@@ -437,7 +454,9 @@ static KeyBinding vis_operator_options[] = {
};
static KeyBinding vis_registers[] = { /* {a-zA-Z0-9.%#:-"} */
-// { { NONE('"'), NONE('a') }, reg, { .i = 1 } },
+ { { NONE('"'), NONE('a') }, reg, { .i = REG_a } },
+ { { NONE('"'), NONE('b') }, reg, { .i = REG_b } },
+ { { NONE('"'), NONE('c') }, reg, { .i = REG_c } },
{ /* empty last element, array terminator */ },
};
@@ -530,14 +549,19 @@ static Mode vis_modes[] = {
.leave = vis_operators_leave,
.input = operator_invalid,
},
+ [VIS_MODE_REGISTER] = {
+ .name = "REGISTER",
+ .parent = &vis_modes[VIS_MODE_OPERATOR],
+ .bindings = vis_registers,
+ },
[VIS_MODE_NORMAL] = {
.name = "NORMAL",
- .parent = &vis_modes[VIS_MODE_OPERATOR],
+ .parent = &vis_modes[VIS_MODE_REGISTER],
.bindings = vis_normal,
},
[VIS_MODE_VISUAL] = {
.name = "VISUAL",
- .parent = &vis_modes[VIS_MODE_OPERATOR],
+ .parent = &vis_modes[VIS_MODE_REGISTER],
.bindings = vis_visual,
.enter = vis_visual_enter,
.leave = vis_visual_leave,
@@ -557,6 +581,8 @@ static Mode vis_modes[] = {
};
static void switchmode_to(Mode *new_mode) {
+ if (mode == new_mode)
+ return;
if (mode->leave)
mode->leave();
mode_prev = mode;
diff --git a/register.c b/register.c
index 65de14d..bcce594 100644
--- a/register.c
+++ b/register.c
@@ -6,12 +6,6 @@
#define REG_SIZE 1024
-struct Register {
- char *data;
- size_t len;
- size_t size;
-};
-
bool register_alloc(Register *reg, size_t size) {
if (size < REG_SIZE)
size = REG_SIZE;
diff --git a/register.h b/register.h
index c6bdf4a..43be959 100644
--- a/register.h
+++ b/register.h
@@ -5,7 +5,12 @@
#include <stdbool.h>
#include "text.h"
-typedef struct Register Register;
+typedef struct {
+ char *data;
+ size_t len;
+ size_t size;
+ bool linewise;
+} Register;
bool register_alloc(Register *reg, size_t size);
void register_free(Register *reg);
diff --git a/vis.c b/vis.c
index e83908a..a83db2c 100644
--- a/vis.c
+++ b/vis.c
@@ -216,6 +216,7 @@ static void vis_windows_invalidate(Vis *vis, size_t start, size_t end) {
vis_window_draw(win);
}
}
+ vis_window_draw(vis->win);
}
diff --git a/vis.h b/vis.h
index ea77a65..9c88c4e 100644
--- a/vis.h
+++ b/vis.h
@@ -22,11 +22,22 @@ struct VisWin {
typedef void (*vis_statusbar_t)(WINDOW *win, bool active, const char *filename, size_t line, size_t col);
+enum Reg {
+ REG_a,
+ REG_b,
+ REG_c,
+ // ...
+ REG_z,
+ REG_DEFAULT,
+ REG_LAST,
+};
+
struct Vis {
int width, height; /* terminal size, available for all windows */
VisWin *windows; /* list of windows */
VisWin *win; /* currently active window */
Syntax *syntaxes; /* NULL terminated array of syntax definitions */
+ Register registers[REG_LAST];
void (*windows_arrange)(Vis*); /* current layout which places the windows */
vis_statusbar_t statusbar; /* configurable user hook to draw statusbar */
};
@@ -74,7 +85,10 @@ typedef struct {
size_t pos;
} OperatorContext;
-typedef void (Operator)(OperatorContext*);
+typedef struct {
+ void (*func)(OperatorContext*); /* function implementing the operator logic */
+ bool selfcontained; /* is this operator followed by movements/text-objects */
+} Operator;
typedef struct {
size_t (*win)(Win*);