diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2017-03-19 14:05:32 +0100 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2017-03-19 14:58:07 +0100 |
| commit | 5166e81e794c0faa80742ad6806745b13b967a51 (patch) | |
| tree | d2f4cd3ece83311bbea9ea172ea12d8337225fa2 | |
| parent | 5fb583f035bb8e699e8980e63050ef1f41f94dd9 (diff) | |
| download | vis-5166e81e794c0faa80742ad6806745b13b967a51.tar.gz vis-5166e81e794c0faa80742ad6806745b13b967a51.tar.xz | |
vis: add infrastructure for user specified operators
| -rw-r--r-- | vis-core.h | 9 | ||||
| -rw-r--r-- | vis-operators.c | 23 | ||||
| -rw-r--r-- | vis.c | 3 | ||||
| -rw-r--r-- | vis.h | 5 |
4 files changed, 35 insertions, 5 deletions
@@ -37,7 +37,7 @@ struct Mode { bool visual; /* whether text selection is possible in this mode */ }; -typedef struct { +struct OperatorContext { int count; /* how many times should the command be executed? */ Register *reg; /* always non-NULL, set to a default register */ Filerange range; /* which part of the file should be affected by the operator */ @@ -45,12 +45,14 @@ typedef struct { size_t newpos; /* new position after motion or EPOS if none given */ bool linewise; /* should the changes always affect whole lines? */ const Arg *arg; /* arbitrary arguments */ -} OperatorContext; + void *context; /* used by user-registered operators */ +}; typedef struct { /* operator logic, returns new cursor position, if EPOS is * the cursor is disposed (except if it is the primary one) */ - size_t (*func)(Vis*, Text*, OperatorContext*); + VisOperatorFunction *func; + void *context; } Operator; typedef struct { /* Motion implementation, takes a cursor postion and returns a new one */ @@ -200,6 +202,7 @@ struct Vis { Array actions_user; /* dynamically allocated editor actions */ lua_State *lua; /* lua context used for syntax highligthing */ VisEvent *event; + Array operators; Array motions; Array textobjects; Array bindings; diff --git a/vis-operators.c b/vis-operators.c index 8038a2d..494774c 100644 --- a/vis-operators.c +++ b/vis-operators.c @@ -245,6 +245,18 @@ static size_t op_filter(Vis *vis, Text *txt, OperatorContext *c) { return text_size(txt) + 1; /* do not change cursor position, would destroy selection */ } +int vis_operator_register(Vis *vis, VisOperatorFunction *func, void *context) { + Operator *op = calloc(1, sizeof *op); + if (!op) + return -1; + op->func = func; + op->context = context; + if (array_add_ptr(&vis->operators, op)) + return VIS_OP_LAST + array_length(&vis->operators) - 1; + free(op); + return -1; +} + bool vis_operator(Vis *vis, enum VisOperator id, ...) { va_list ap; va_start(ap, id); @@ -292,9 +304,16 @@ bool vis_operator(Vis *vis, enum VisOperator id, ...) { default: break; } - if (id >= LENGTH(vis_operators)) + + const Operator *op = NULL; + if (id < LENGTH(vis_operators)) + op = &vis_operators[id]; + else + op = array_get_ptr(&vis->operators, id - VIS_OP_LAST); + + if (!op) goto err; - const Operator *op = &vis_operators[id]; + if (vis->mode->visual) { vis->action.op = op; vis_do(vis); @@ -676,6 +676,7 @@ Vis *vis_new(Ui *ui, VisEvent *event) { vis->change_colors = true; vis->registers[VIS_REG_BLACKHOLE].type = REGISTER_BLACKHOLE; vis->registers[VIS_REG_CLIPBOARD].type = REGISTER_CLIPBOARD; + array_init(&vis->operators); array_init(&vis->motions); array_init(&vis->textobjects); array_init(&vis->bindings); @@ -745,6 +746,7 @@ void vis_free(Vis *vis) { buffer_release(&vis->input_queue); for (int i = 0; i < VIS_MODE_INVALID; i++) map_free(vis_modes[i].bindings); + array_release_full(&vis->operators); array_release_full(&vis->motions); array_release_full(&vis->textobjects); while (array_length(&vis->bindings)) @@ -852,6 +854,7 @@ void vis_do(Vis *vis) { .reg = reg, .linewise = linewise, .arg = &a->arg, + .context = a->op ? a->op->context : NULL, }; bool err = false; @@ -224,6 +224,7 @@ enum VisOperator { VIS_OP_PUT_AFTER_END, VIS_OP_PUT_BEFORE, VIS_OP_PUT_BEFORE_END, + VIS_OP_LAST, /* has to be last enum member */ }; /* set operator to execute, has immediate effect if @@ -242,6 +243,10 @@ enum VisOperator { */ bool vis_operator(Vis*, enum VisOperator, ...); +typedef struct OperatorContext OperatorContext; +typedef size_t (VisOperatorFunction)(Vis*, Text*, OperatorContext*); +int vis_operator_register(Vis*, VisOperatorFunction*, void *context); + enum VisMotion { VIS_MOVE_LINE_DOWN, VIS_MOVE_LINE_UP, |
