From 26b56bc3090e9ad6ffd71f216a53805c5e894807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Sat, 7 Nov 2015 08:51:26 +0100 Subject: vis: API documentation and cleanup --- main.c | 6 +- ui-curses.c | 1 - ui.h | 1 - vis-core.h | 3 +- vis-modes.c | 12 ++-- vis.c | 19 +++--- vis.h | 208 ++++++++++++++++++++++++++++++++++++++---------------------- 7 files changed, 151 insertions(+), 99 deletions(-) diff --git a/main.c b/main.c index 9d6cd10..21cc04e 100644 --- a/main.c +++ b/main.c @@ -1194,7 +1194,7 @@ static const char *cursors_remove(Vis *vis, const char *keys, const Arg *arg) { static const char *replace(Vis *vis, const char *keys, const Arg *arg) { if (!keys[0]) return NULL; - const char *next = vis_key_next(vis, keys); + const char *next = vis_keys_next(vis, keys); if (!next) return NULL; size_t len = next - keys; @@ -1243,7 +1243,7 @@ static const char *movement_key(Vis *vis, const char *keys, const Arg *arg) { if (!keys[0]) return NULL; char key[32]; - const char *next = vis_key_next(vis, keys); + const char *next = vis_keys_next(vis, keys); strncpy(key, keys, next - keys + 1); key[sizeof(key)-1] = '\0'; vis_motion(vis, arg->i, key); @@ -1274,7 +1274,7 @@ static const char *selection_restore(Vis *vis, const char *keys, const Arg *arg) } static const char *key2register(Vis *vis, const char *keys, enum VisRegister *reg) { - *reg = VIS_REGISTER_INVALID; + *reg = VIS_REG_INVALID; if (!keys[0]) return NULL; if (keys[0] >= 'a' && keys[0] <= 'z') diff --git a/ui-curses.c b/ui-curses.c index ea4aac7..7c1f5b3 100644 --- a/ui-curses.c +++ b/ui-curses.c @@ -1024,7 +1024,6 @@ Ui *ui_curses_new(void) { .free = ui_curses_free, .termkey_get = ui_termkey_get, .suspend = ui_suspend, - .resume = ui_resize, .resize = ui_resize, .update = ui_update, .window_new = ui_window_new, diff --git a/ui.h b/ui.h index 0549db3..8c94d51 100644 --- a/ui.h +++ b/ui.h @@ -47,7 +47,6 @@ struct Ui { void (*draw)(Ui*); void (*update)(Ui*); void (*suspend)(Ui*); - void (*resume)(Ui*); const char* (*getkey)(Ui*); bool (*haskey)(Ui*); void (*terminal_save)(Ui*); diff --git a/vis-core.h b/vis-core.h index 549b817..4321a80 100644 --- a/vis-core.h +++ b/vis-core.h @@ -1,6 +1,7 @@ #ifndef VIS_CORE_H #define VIS_CORE_H +#include #include "vis.h" #include "text.h" #include "text-regex.h" @@ -123,7 +124,7 @@ struct Vis { Win *windows; /* list of windows */ Win *win; /* currently active window */ Syntax *syntaxes; /* NULL terminated array of syntax definitions */ - Register registers[VIS_REGISTER_INVALID]; /* register used for copy and paste */ + Register registers[VIS_REG_INVALID]; /* register used for copy and paste */ Macro macros[VIS_MACRO_INVALID]; /* recorded macros */ Macro *recording, *last_recording;/* currently and least recently recorded macro */ Macro *macro_operator; diff --git a/vis-modes.c b/vis-modes.c index 7d2f7e5..b53aeb7 100644 --- a/vis-modes.c +++ b/vis-modes.c @@ -20,13 +20,13 @@ void mode_set(Vis *vis, Mode *new_mode) { vis->win->ui->draw_status(vis->win->ui); } -static bool mode_map(Mode *mode, const char *name, KeyBinding *binding) { - return map_put(mode->bindings, name, binding); +static bool mode_map(Mode *mode, const char *key, KeyBinding *binding) { + return map_put(mode->bindings, key, binding); } -bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *name, KeyBinding *binding) { +bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *key, KeyBinding *binding) { Mode *mode = mode_get(vis, modeid); - return mode && map_put(mode->bindings, name, binding); + return mode && mode_map(mode, key, binding); } bool vis_mode_bindings(Vis *vis, enum VisMode modeid, KeyBinding **bindings) { @@ -41,9 +41,9 @@ bool vis_mode_bindings(Vis *vis, enum VisMode modeid, KeyBinding **bindings) { return success; } -bool vis_mode_unmap(Vis *vis, enum VisMode modeid, const char *name) { +bool vis_mode_unmap(Vis *vis, enum VisMode modeid, const char *key) { Mode *mode = mode_get(vis, modeid); - return mode && map_delete(mode->bindings, name); + return mode && map_delete(mode->bindings, key); } /** mode switching event handlers */ diff --git a/vis.c b/vis.c index 82532b6..be8f727 100644 --- a/vis.c +++ b/vis.c @@ -225,10 +225,6 @@ bool vis_window_split(Win *original) { return true; } -void vis_resize(Vis *vis) { - vis->ui->resize(vis->ui); -} - void vis_window_next(Vis *vis) { Win *sel = vis->win; if (!sel) @@ -535,7 +531,7 @@ static void action_do(Vis *vis, Action *a) { next = view_cursors_next(cursor); size_t pos = view_cursors_pos(cursor); - Register *reg = a->reg ? a->reg : &vis->registers[REG_DEFAULT]; + Register *reg = a->reg ? a->reg : &vis->registers[VIS_REG_DEFAULT]; if (multiple_cursors) reg = view_cursors_register(cursor); @@ -694,7 +690,7 @@ void vis_die(Vis *vis, const char *msg, ...) { va_end(ap); } -const char *vis_key_next(Vis *vis, const char *keys) { +const char *vis_keys_next(Vis *vis, const char *keys) { TermKeyKey key; TermKey *termkey = vis->ui->termkey_get(vis->ui); const char *next = NULL; @@ -727,7 +723,7 @@ static const char *vis_keys_raw(Vis *vis, Buffer *buf, const char *input) { while (cur && *cur) { - if (!(end = (char*)vis_key_next(vis, cur))) + if (!(end = (char*)vis_keys_next(vis, cur))) goto err; // XXX: can't parse key this should never happen char tmp = *end; @@ -801,7 +797,7 @@ bool vis_keys_inject(Vis *vis, const char *pos, const char *input) { return true; } -const char *vis_keys(Vis *vis, const char *input) { +const char *vis_keys_push(Vis *vis, const char *input) { if (!input) return NULL; @@ -958,7 +954,7 @@ int vis_run(Vis *vis, int argc, char *argv[]) { const char *key; while ((key = getkey(vis))) - vis_keys(vis, key); + vis_keys_push(vis, key); if (vis->mode->idle) timeout = &idle; @@ -1087,7 +1083,7 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) { case MOVE_MARK_LINE: { int mark = va_arg(ap, int); - if (MARK_a <= mark && mark < VIS_MARK_INVALID) + if (VIS_MARK_a <= mark && mark < VIS_MARK_INVALID) vis->action.mark = mark; else goto err; @@ -1221,7 +1217,8 @@ int vis_count_get(Vis *vis) { } void vis_count_set(Vis *vis, int count) { - vis->action.count = count; + if (count >= 0) + vis->action.count = count; } void vis_register_set(Vis *vis, enum VisRegister reg) { diff --git a/vis.h b/vis.h index 8e69806..01c1358 100644 --- a/vis.h +++ b/vis.h @@ -4,7 +4,6 @@ #include #include #include -#include typedef struct Vis Vis; typedef struct File File; @@ -15,35 +14,41 @@ typedef struct Win Win; #include "register.h" #include "syntax.h" -typedef union { +typedef union { /* various types of arguments passed to key action functions */ bool b; int i; const char *s; - void (*w)(View*); /* generic window commands */ - void (*f)(Vis*); /* generic editor commands */ + void (*w)(View*); + void (*f)(Vis*); } Arg; -typedef struct { - const char *name; - const char *help; +typedef struct { /* a KeyAction can be bound to a key binding */ + const char *name; /* aliases can refer to this action by means of a pseudo key */ + const char *help; /* short (one line) human readable description, displayed by :help */ + /* action handling function, keys refers to the next characters found in the input queue + * (an empty string "" indicates an empty queue). The return value of func has to point to + * the first non consumed key. Returning NULL indicates that not enough keys were available + * to complete the action. In this case the function will be called again when more input + * becomes available */ const char* (*func)(Vis*, const char *keys, const Arg*); - /* returns a pointer to the first not consumed character in keys - * or NULL if not enough input was available to complete the command */ - const Arg arg; - + const Arg arg; /* additional arguments which will be passed as to func */ } KeyAction; -typedef struct { - const char *key; - KeyAction *action; - const char *alias; +typedef struct { /* a key binding either refers to an action or an alias */ + const char *key; /* symbolic key to trigger this binding */ + KeyAction *action; /* action to launch upon triggering this binding */ + const char *alias; /* replaces key with alias in the input queue */ } KeyBinding; +/* creates a new editor instance using the specified user interface */ Vis *vis_new(Ui*); +/* frees all resources associated with this editor instance, terminates ui */ void vis_free(Vis*); -void vis_resize(Vis*); +/* instructs the user interface to draw to an internal buffer */ void vis_draw(Vis*); +/* flushes the state of the internal buffer to the output device */ void vis_update(Vis*); +/* temporarily supsend the editor process, resumes upon receiving SIGCONT */ void vis_suspend(Vis*); /* load a set of syntax highlighting definitions which will be associated @@ -61,18 +66,20 @@ void vis_syntax_unload(Vis*); bool vis_window_new(Vis*, const char *filename); /* reload the file currently displayed in the window from disk */ bool vis_window_reload(Win*); +/* close window, redraw user interface */ void vis_window_close(Win*); /* split the given window. changes to the displayed text will be reflected * in both windows */ bool vis_window_split(Win*); +/* change file name associated with this window, affects syntax coloring */ void vis_window_name(Win*, const char *filename); /* focus the next / previous window */ void vis_window_next(Vis*); void vis_window_prev(Vis*); /* display a user prompt with a certain title and default text */ void vis_prompt_show(Vis*, const char *title, const char *text); -/* TODO: bad abstraction */ -void vis_prompt_enter(Vis*); +/* execute current prompt content as command, as if the user had pressed */ +void vis_prompt_enter(Vis*); /* TODO: bad abstraction */ /* hide the user prompt if it is currently shown */ void vis_prompt_hide(Vis*); /* return the content of the command prompt in a malloc(3)-ed string @@ -87,18 +94,29 @@ void vis_info_hide(Vis*); /* these function operate on the currently focused window but make sure * that all windows which show the affected region are redrawn too. */ -void vis_insert_key(Vis*, const char *data, size_t len); -void vis_replace_key(Vis*, const char *data, size_t len); void vis_insert(Vis*, size_t pos, const char *data, size_t len); void vis_delete(Vis*, size_t pos, size_t len); void vis_replace(Vis*, size_t pos, const char *data, size_t len); +/* these functions perform their operation at the current cursor position(s) */ +void vis_insert_key(Vis*, const char *data, size_t len); +void vis_replace_key(Vis*, const char *data, size_t len); +/* inserts a tab (peforms tab expansion based on current editing settings), + * at all current cursor positions */ void vis_insert_tab(Vis*); +/* inserts a new line sequence (depending on the file type this might be \n or + * \r\n) at all current cursor positions */ void vis_insert_nl(Vis*); +/* processes the given command line arguments and starts the main loop, won't + * return until editing session is terminated */ int vis_run(Vis*, int argc, char *argv[]); +/* terminate editing session, given status will be the return value of vis_run */ void vis_exit(Vis*, int status); +/* emergency exit, print given message, perform minimal ui cleanup and exit process */ void vis_die(Vis*, const char *msg, ...); +/* user facing modes are: NORMAL, VISUAL, VISUAL_LINE, PROMPT, INSERT, REPLACE. + * the others should be considered as implementation details (TODO: do not expose them?) */ enum VisMode { VIS_MODE_BASIC, VIS_MODE_MOVE, @@ -116,18 +134,20 @@ enum VisMode { }; void vis_mode_switch(Vis*, enum VisMode); -bool vis_mode_map(Vis*, enum VisMode, const char *name, KeyBinding*); -bool vis_mode_unmap(Vis*, enum VisMode, const char *name); +/* in the specified mode: map a given key to a binding (binding->key is ignored), + * fails if key is already mapped */ +bool vis_mode_map(Vis*, enum VisMode, const char *key, KeyBinding*); +/* in the specified mode: unmap a given key, fails if the key is not currently mapped */ +bool vis_mode_unmap(Vis*, enum VisMode, const char *key); +/* map a NULL-terminated array of key bindings, return value indicates whether *all* + * bindings were succesfully performed */ bool vis_mode_bindings(Vis*, enum VisMode, KeyBinding **bindings); +/* get the current mode's status line indicator */ const char *vis_mode_status(Vis*); - +/* associates the special pseudo key name> with the given key action. + * after successfull registration the pseudo key can be used key binding aliases */ bool vis_action_register(Vis*, KeyAction*); -/* TODO: overhaul repeatable infrastructure: - * - put is not really an operator, but should still be repeatable - * and respect count - " - review OP_REPEAT_{REPLACE,INSERT} - */ enum VisOperator { OP_DELETE, OP_CHANGE, @@ -140,7 +160,7 @@ enum VisOperator { OP_REPLACE, OP_CURSOR_SOL, OP_CASE_SWAP, - OP_INVALID, + OP_INVALID, /* denotes the end of the "real" operators */ /* pseudo operators: keep them at the end to save space in array definition */ OP_CASE_LOWER, OP_CASE_UPPER, @@ -150,6 +170,13 @@ enum VisOperator { OP_PUT_BEFORE_END, }; +/* set operator to execute, has immediate effect if + * - a visual mode is active + * - the same operator was already set (range will be the current line) + * otherwise waits until a range is determinded i.e. + * - a motion is provided (see vis_motion) + * - a text object is provided (vis_textobject) + */ bool vis_operator(Vis*, enum VisOperator); enum VisMotion { @@ -210,7 +237,7 @@ enum VisMotion { MOVE_JUMPLIST_NEXT, MOVE_JUMPLIST_PREV, MOVE_NOP, - MOVE_INVALID, + MOVE_INVALID, /* denotes the end of the "real" motions */ /* pseudo motions: keep them at the end to save space in array definition */ MOVE_TOTILL_REPEAT, MOVE_TOTILL_REVERSE, @@ -218,8 +245,25 @@ enum VisMotion { MOVE_SEARCH_BACKWARD, }; +/* set motion to perform, the following take an additional argument: + * + * - MOVE_SEARCH_FORWARD and MOVE_SEARCH_BACKWARD + * + * expect the search pattern as const char * + * + * - MOVE_{LEFT,RIGHT}_{TO,TILL} + * + * expect the character to search for as const char * + * + * - MOVE_MARK and MOVE_MARK_LINE + * + * expect a valid enum VisMark + */ bool vis_motion(Vis*, enum VisMotion, ...); +/* a count of zero indicates that so far no special count was given. + * operators, motions and text object will always perform their function + * as if a minimal count of 1 was given */ int vis_count_get(Vis*); void vis_count_set(Vis*, int count); @@ -227,7 +271,7 @@ enum VisMotionType { VIS_MOTIONTYPE_LINEWISE = 1 << 0, VIS_MOTIONTYPE_CHARWISE = 1 << 1, }; - +/* force certain motion to behave in line or character wise mode */ void vis_motion_type(Vis *vis, enum VisMotionType); enum VisTextObject { @@ -261,77 +305,89 @@ enum VisTextObject { void vis_textobject(Vis*, enum VisTextObject); +/* macro REPEAT and INVALID should be considered as implementation details (TODO: hide them?) */ enum VisMacro { - /* XXX: TEMPORARY */ - VIS_MACRO_LAST_RECORDED = 26, - VIS_MACRO_REPEAT, - VIS_MACRO_OPERATOR, - VIS_MACRO_INVALID, /* hast to be the last enum member */ + VIS_MACRO_a, VIS_MACRO_b, VIS_MACRO_c, VIS_MACRO_d, VIS_MACRO_e, + VIS_MACRO_f, VIS_MACRO_g, VIS_MACRO_h, VIS_MACRO_i, VIS_MACRO_j, + VIS_MACRO_k, VIS_MACRO_l, VIS_MACRO_m, VIS_MACRO_n, VIS_MACRO_o, + VIS_MACRO_p, VIS_MACRO_q, VIS_MACRO_r, VIS_MACRO_s, VIS_MACRO_t, + VIS_MACRO_u, VIS_MACRO_v, VIS_MACRO_w, VIS_MACRO_x, VIS_MACRO_y, + VIS_MACRO_z, + VIS_MACRO_OPERATOR, /* records entered keys after an operator */ + VIS_MACRO_REPEAT, /* copy of the above macro once the recording is finished */ + VIS_MACRO_INVALID, /* denotes the end of "real" macros */ + VIS_MACRO_LAST_RECORDED, /* pseudo macro referring to last recorded one */ }; +/* start a macro recording, fails if a recording is already on going */ bool vis_macro_record(Vis*, enum VisMacro); +/* stop recording, fails if there is nothing to stop */ bool vis_macro_record_stop(Vis*); +/* check whether a recording is currently on going */ bool vis_macro_recording(Vis*); +/* replay a macro. a macro currently being recorded can't be replayed */ bool vis_macro_replay(Vis*, enum VisMacro); enum VisMark { - MARK_a, - MARK_b, - MARK_c, - MARK_d, - MARK_e, - MARK_f, - MARK_g, - MARK_h, - MARK_i, - MARK_j, - MARK_k, - MARK_l, - MARK_m, - MARK_n, - MARK_o, - MARK_p, - MARK_q, - MARK_r, - MARK_s, - MARK_t, - MARK_u, - MARK_v, - MARK_w, - MARK_x, - MARK_y, - MARK_z, - MARK_SELECTION_START, - MARK_SELECTION_END, - VIS_MARK_INVALID, + VIS_MARK_a, VIS_MARK_b, VIS_MARK_c, VIS_MARK_d, VIS_MARK_e, + VIS_MARK_f, VIS_MARK_g, VIS_MARK_h, VIS_MARK_i, VIS_MARK_j, + VIS_MARK_k, VIS_MARK_l, VIS_MARK_m, VIS_MARK_n, VIS_MARK_o, + VIS_MARK_p, VIS_MARK_q, VIS_MARK_r, VIS_MARK_s, VIS_MARK_t, + VIS_MARK_u, VIS_MARK_v, VIS_MARK_w, VIS_MARK_x, VIS_MARK_y, + VIS_MARK_z, + MARK_SELECTION_START, /* '< */ + MARK_SELECTION_END, /* '> */ + VIS_MARK_INVALID, /* has to be the last enum member */ }; void vis_mark_set(Vis*, enum VisMark mark, size_t pos); enum VisRegister { - REG_a, REG_b, REG_c, REG_d, REG_e, REG_f, REG_g, REG_h, REG_i, - REG_j, REG_k, REG_l, REG_m, REG_n, REG_o, REG_p, REG_q, REG_r, - REG_s, REG_t, REG_u, REG_v, REG_w, REG_x, REG_y, REG_z, - REG_DEFAULT, - VIS_REGISTER_INVALID, + VIS_REG_a, VIS_REG_b, VIS_REG_c, VIS_REG_d, VIS_REG_e, + VIS_REG_f, VIS_REG_g, VIS_REG_h, VIS_REG_i, VIS_REG_j, + VIS_REG_k, VIS_REG_l, VIS_REG_m, VIS_REG_n, VIS_REG_o, + VIS_REG_p, VIS_REG_q, VIS_REG_r, VIS_REG_s, VIS_REG_t, + VIS_REG_u, VIS_REG_v, VIS_REG_w, VIS_REG_x, VIS_REG_y, + VIS_REG_z, + VIS_REG_DEFAULT, /* used when no other register is specified */ + VIS_REG_INVALID, /* has to be the last enum member */ }; +/* set the register to use, if none is given the DEFAULT register is used */ void vis_register_set(Vis*, enum VisRegister); Register *vis_register_get(Vis*, enum VisRegister); +/* repeat last operator, possibly with a new count if one was provided in the meantime */ void vis_repeat(Vis*); + +/* cancel pending operator, reset count, motion, text object, register etc. */ void vis_cancel(Vis*); -/* execute a :-command (call without without leading ':') */ +/* execute a :-command (including an optinal range specifier) */ bool vis_cmd(Vis*, const char *cmd); -const char *vis_key_next(Vis*, const char *keys); -const char *vis_keys(Vis*, const char *input); +/* given the start of a key, returns a pointer to the start of the one immediately + * following as will be processed by the input system. skips over special keys + * such as as well as pseudo keys registered via vis_action_register. */ +const char *vis_keys_next(Vis*, const char *keys); +/* vis operates as a finite state machine (FSM), feeding keys from an input + * queue (or a previously recorded macro) to key handling functions (see struct + * KeyAction) which consume the input. + * + * this functions pushes/appends further input to the end of the input queue + * and immediately tries to interpret them */ +const char *vis_keys_push(Vis*, const char *input); +/* inject new input keys at the position indicated by a pointer to a valid, not + * yet consumed key from the current input queue. does not try to interpret the + * new queue content. + * + * typically only called from within key handling functions */ bool vis_keys_inject(Vis*, const char *pos, const char *input); +/* inform vis that a signal occured, the return value indicates whether the signal + * was handled by vis */ +bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, const void *context); -bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, - const void *context); - +/* TODO: expose proper API to iterate through files etc */ Text *vis_text(Vis*); View *vis_view(Vis*); Text *vis_file_text(File*); -- cgit v1.2.3