From 2deb344c3122e91a745734ce77b3e0967f169c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Wed, 3 Sep 2014 21:35:16 +0200 Subject: Rudimentary support for copy / paste via registers --- config.def.h | 68 +++++++++++++++++++++++++++++++++++++++++------------------- register.c | 6 ------ register.h | 7 ++++++- vis.c | 1 + vis.h | 16 +++++++++++++- 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 #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*); -- cgit v1.2.3