aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2017-03-19 14:05:32 +0100
committerMarc André Tanner <mat@brain-dump.org>2017-03-19 14:58:07 +0100
commit5166e81e794c0faa80742ad6806745b13b967a51 (patch)
treed2f4cd3ece83311bbea9ea172ea12d8337225fa2
parent5fb583f035bb8e699e8980e63050ef1f41f94dd9 (diff)
downloadvis-5166e81e794c0faa80742ad6806745b13b967a51.tar.gz
vis-5166e81e794c0faa80742ad6806745b13b967a51.tar.xz
vis: add infrastructure for user specified operators
-rw-r--r--vis-core.h9
-rw-r--r--vis-operators.c23
-rw-r--r--vis.c3
-rw-r--r--vis.h5
4 files changed, 35 insertions, 5 deletions
diff --git a/vis-core.h b/vis-core.h
index f182e2a..9cc26f3 100644
--- a/vis-core.h
+++ b/vis-core.h
@@ -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);
diff --git a/vis.c b/vis.c
index 4c93872..06546ab 100644
--- a/vis.c
+++ b/vis.c
@@ -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;
diff --git a/vis.h b/vis.h
index 913a503..6c6e0fe 100644
--- a/vis.h
+++ b/vis.h
@@ -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,