diff --git a/vis-core.h b/vis-core.h index a2018282f..b1330c78f 100644 --- a/vis-core.h +++ b/vis-core.h @@ -8,6 +8,7 @@ #include "text-regex.h" #include "map.h" #include "ring-buffer.h" +#include "array.h" /* a mode contains a set of key bindings which are currently valid. * @@ -59,6 +60,7 @@ typedef struct { /* Motion implementation, takes a cursor postion and returns a size_t (*vis)(Vis*, Text*, size_t pos); size_t (*view)(Vis*, View*); size_t (*win)(Vis*, Win*, size_t pos); + size_t (*user)(Vis*, Win*, void*, size_t pos); enum { LINEWISE = VIS_MOTIONTYPE_LINEWISE, /* should the covered range be extended to whole lines? */ CHARWISE = VIS_MOTIONTYPE_CHARWISE, /* scrolls window content until position is visible */ @@ -66,6 +68,7 @@ typedef struct { /* Motion implementation, takes a cursor postion and returns a IDEMPOTENT = 1 << 3, /* does the returned postion remain the same if called multiple times? */ JUMP = 1 << 4, } type; + void *data; } Movement; typedef struct { @@ -165,6 +168,7 @@ struct Vis { Map *actions; /* registered editor actions / special keys commands */ lua_State *lua; /* lua context used for syntax highligthing */ VisEvent *event; + Array motions; }; /** stuff used by multiple of the vis-* files */ diff --git a/vis-motions.c b/vis-motions.c index e0db0483e..6111d3ecb 100644 --- a/vis-motions.c +++ b/vis-motions.c @@ -5,6 +5,7 @@ #include "text-motions.h" #include "text-objects.h" #include "text-util.h" +#include "util.h" /** utility functions */ @@ -210,6 +211,23 @@ void vis_motion_type(Vis *vis, enum VisMotionType type) { vis->action.type = type; } +int vis_motion_register(Vis *vis, enum VisMotionType type, void *data, + size_t (*motion)(Vis*, Win*, void*, size_t pos)) { + + Movement *move = calloc(1, sizeof *move); + if (!move) + return -1; + + move->user = motion; + move->type = type; + move->data = data; + + if (array_add(&vis->motions, move)) + return VIS_MOVE_LAST + array_length(&vis->motions) - 1; + free(move); + return -1; +} + bool vis_motion(Vis *vis, enum VisMotion motion, ...) { va_list ap; va_start(ap, motion); @@ -287,7 +305,14 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) { break; } - vis->action.movement = &vis_motions[motion]; + if (motion < LENGTH(vis_motions)) + vis->action.movement = &vis_motions[motion]; + else + vis->action.movement = array_get(&vis->motions, motion - VIS_MOVE_LAST); + + if (!vis->action.movement) + goto err; + va_end(ap); action_do(vis, &vis->action); return true; diff --git a/vis.c b/vis.c index 35516dee7..ccea1f188 100644 --- a/vis.c +++ b/vis.c @@ -377,6 +377,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->motions); free(vis); } @@ -488,6 +489,8 @@ void action_do(Vis *vis, Action *a) { pos = a->movement->view(vis, view); else if (a->movement->win) pos = a->movement->win(vis, win, pos); + else if (a->movement->user) + pos = a->movement->user(vis, win, a->movement->data, pos); if (pos == EPOS || a->movement->type & IDEMPOTENT) break; } diff --git a/vis.h b/vis.h index 19cdb4358..42bd88a13 100644 --- a/vis.h +++ b/vis.h @@ -242,6 +242,7 @@ enum VisMotion { VIS_MOVE_TOTILL_REVERSE, VIS_MOVE_SEARCH_FORWARD, VIS_MOVE_SEARCH_BACKWARD, + VIS_MOVE_LAST, /* denotes the end of all motions */ }; /* set motion to perform, the following take an additional argument: @@ -275,6 +276,12 @@ enum VisMotionType { /* force certain motion to behave in line or character wise mode */ void vis_motion_type(Vis *vis, enum VisMotionType); +/* register a motion function, if positive the return value can be used + * as an id for the vis_motion funntion. A negative return value indicates + * an error */ +int vis_motion_register(Vis*, enum VisMotionType, void *data, + size_t (*motion)(Vis*, Win*, void*, size_t pos)); + enum VisTextObject { VIS_TEXTOBJECT_INNER_WORD, VIS_TEXTOBJECT_OUTER_WORD,