vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

commit 3c9244d4dbafa9a6fbd7105b2e34eae14e6980a1
parent 22681295ca6d6def3ab14f19f65b528153db09c9
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Wed, 17 Feb 2016 21:34:00 +0100

Add infrastructure to register custom text object functions

Diffstat:
Mvis-core.h | 3+++
Mvis-text-objects.c | 29++++++++++++++++++++++++-----
Mvis.c | 7+++++--
Mvis.h | 5+++++
4 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/vis-core.h b/vis-core.h @@ -76,11 +76,13 @@ typedef struct { * representing the text object containing the position. */ Filerange (*txt)(Text*, size_t pos); Filerange (*vis)(Vis*, Text*, size_t pos); + Filerange (*user)(Vis*, Win*, void *data, size_t pos); enum { INNER = 1 << 0, /* whether the object should include */ OUTER = 1 << 1, /* the delimiting symbols or not */ SPLIT = 1 << 2, /* whether multiple applications will yield a split range */ } type; + void *data; } TextObject; /* a macro is just a sequence of symbolic keys as received from ui->getkey */ @@ -169,6 +171,7 @@ struct Vis { lua_State *lua; /* lua context used for syntax highligthing */ VisEvent *event; Array motions; + Array textobjects; }; /** stuff used by multiple of the vis-* files */ diff --git a/vis-text-objects.c b/vis-text-objects.c @@ -2,13 +2,32 @@ #include "text-objects.h" #include "util.h" +int vis_textobject_register(Vis *vis, int type, void *data, + Filerange (*textobject)(Vis*, Win*, void*, size_t pos)) { + + TextObject *obj = calloc(1, sizeof *obj); + if (!obj) + return -1; + + obj->user = textobject; + obj->type = type; + obj->data = data; + + if (array_add(&vis->textobjects, obj)) + return LENGTH(vis_textobjects) + array_length(&vis->textobjects) - 1; + free(obj); + return -1; +} + bool vis_textobject(Vis *vis, enum VisTextObject id) { - if (id < LENGTH(vis_textobjects)) { + if (id < LENGTH(vis_textobjects)) vis->action.textobj = &vis_textobjects[id]; - action_do(vis, &vis->action); - return true; - } - return false; + else + vis->action.textobj = array_get(&vis->textobjects, id - LENGTH(vis_textobjects)); + if (!vis->action.textobj) + return false; + action_do(vis, &vis->action); + return true; } static Filerange search_forward(Vis *vis, Text *txt, size_t pos) { diff --git a/vis.c b/vis.c @@ -378,6 +378,7 @@ void vis_free(Vis *vis) { for (int i = 0; i < VIS_MODE_INVALID; i++) map_free(vis_modes[i].bindings); array_release_full(&vis->motions); + array_release_full(&vis->textobjects); free(vis); } @@ -524,11 +525,13 @@ void action_do(Vis *vis, Action *a) { else c.range.start = c.range.end = pos; for (int i = 0; i < count; i++) { - Filerange r; + Filerange r = text_range_empty(); if (a->textobj->txt) r = a->textobj->txt(txt, pos); - else + else if (a->textobj->vis) r = a->textobj->vis(vis, txt, pos); + else if (a->textobj->user) + r = a->textobj->user(vis, win, a->textobj->data, pos); if (!text_range_valid(&r)) break; if (a->textobj->type & OUTER) { diff --git a/vis.h b/vis.h @@ -317,6 +317,11 @@ enum VisTextObject { bool vis_textobject(Vis*, enum VisTextObject); +/* register a new text object, if successful the returned id is positive + * and can be used as argument for the vis_textobject function. */ +int vis_textobject_register(Vis*, int type, void *data, + Filerange (*textobject)(Vis*, Win*, void*, size_t pos)); + /* macro REPEAT and INVALID should be considered as implementation details (TODO: hide them?) */ enum VisMacro { VIS_MACRO_a, VIS_MACRO_b, VIS_MACRO_c, VIS_MACRO_d, VIS_MACRO_e,