From acced3c57142eb2ad389b0aa247bc361bc627beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Sat, 7 Nov 2015 08:38:36 +0100 Subject: vis: move modes into separate file --- vis-core.h | 5 ++ vis-modes.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vis.c | 283 +----------------------------------------------------------- 3 files changed, 287 insertions(+), 282 deletions(-) create mode 100644 vis-modes.c diff --git a/vis-core.h b/vis-core.h index a667a4d..8d12518 100644 --- a/vis-core.h +++ b/vis-core.h @@ -167,4 +167,9 @@ const char *expandtab(Vis *vis); void macro_operator_stop(Vis *vis); void macro_operator_record(Vis *vis); +void action_reset(Vis*, Action *a); + +void mode_set(Vis *vis, Mode *new_mode); +Mode *mode_get(Vis *vis, enum VisMode mode); + #endif \ No newline at end of file diff --git a/vis-modes.c b/vis-modes.c new file mode 100644 index 0000000..08acec7 --- /dev/null +++ b/vis-modes.c @@ -0,0 +1,281 @@ +#include "vis-core.h" +#include "util.h" + +Mode *mode_get(Vis *vis, enum VisMode mode) { + if (mode < LENGTH(vis_modes)) + return &vis_modes[mode]; + return NULL; +} + +void mode_set(Vis *vis, Mode *new_mode) { + if (vis->mode == new_mode) + return; + if (vis->mode->leave) + vis->mode->leave(vis, new_mode); + if (vis->mode->isuser) + vis->mode_prev = vis->mode; + vis->mode = new_mode; + if (new_mode->enter) + new_mode->enter(vis, vis->mode_prev); + 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); +} + +bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *name, KeyBinding *binding) { + Mode *mode = mode_get(vis, modeid); + return mode && map_put(mode->bindings, name, binding); +} + +bool vis_mode_bindings(Vis *vis, enum VisMode modeid, KeyBinding **bindings) { + Mode *mode = mode_get(vis, modeid); + if (!mode) + return false; + bool success = true; + for (KeyBinding *kb = *bindings; kb->key; kb++) { + if (!mode_map(mode, kb->key, kb)) + success = false; + } + return success; +} + +bool vis_mode_unmap(Vis *vis, enum VisMode modeid, const char *name) { + Mode *mode = mode_get(vis, modeid); + return mode && map_delete(mode->bindings, name); +} + +/** mode switching event handlers */ + +static void vis_mode_operator_enter(Vis *vis, Mode *old) { + vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_OPERATOR_OPTION]; +} + +static void vis_mode_operator_leave(Vis *vis, Mode *new) { + vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE]; +} + +static void vis_mode_operator_input(Vis *vis, const char *str, size_t len) { + /* invalid operator */ + action_reset(vis, &vis->action); + mode_set(vis, vis->mode_prev); +} + +static void vis_mode_visual_enter(Vis *vis, Mode *old) { + if (!old->visual) { + for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c)) + view_cursors_selection_start(c); + vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_TEXTOBJ]; + } +} + +static void vis_mode_visual_line_enter(Vis *vis, Mode *old) { + if (!old->visual) { + for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c)) + view_cursors_selection_start(c); + vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_TEXTOBJ]; + } + vis_motion(vis, MOVE_LINE_END); +} + +static void vis_mode_visual_line_leave(Vis *vis, Mode *new) { + if (!new->visual) { + view_selections_clear(vis->win->view); + vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE]; + } else { + view_cursor_to(vis->win->view, view_cursor_get(vis->win->view)); + } +} + +static void vis_mode_visual_leave(Vis *vis, Mode *new) { + if (!new->visual) { + view_selections_clear(vis->win->view); + vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE]; + } +} + +static void vis_mode_prompt_input(Vis *vis, const char *str, size_t len) { + vis_insert_key(vis, str, len); +} + +static void vis_mode_prompt_enter(Vis *vis, Mode *old) { + if (old->isuser && old != &vis_modes[VIS_MODE_PROMPT]) + vis->mode_before_prompt = old; +} + +static void vis_mode_prompt_leave(Vis *vis, Mode *new) { + if (new->isuser) + vis_prompt_hide(vis); +} + +static void vis_mode_insert_enter(Vis *vis, Mode *old) { + if (!vis->macro_operator) { + macro_operator_record(vis); + action_reset(vis, &vis->action_prev); + vis->action_prev.macro = vis->macro_operator; + vis->action_prev.op = &ops[OP_INSERT]; + } +} + +static void vis_mode_insert_leave(Vis *vis, Mode *new) { + /* make sure we can recover the current state after an editing operation */ + text_snapshot(vis->win->file->text); + if (new == mode_get(vis, VIS_MODE_NORMAL)) + macro_operator_stop(vis); +} + +static void vis_mode_insert_idle(Vis *vis) { + text_snapshot(vis->win->file->text); +} + +static void vis_mode_insert_input(Vis *vis, const char *str, size_t len) { + vis_insert_key(vis, str, len); +} + +static void vis_mode_replace_enter(Vis *vis, Mode *old) { + if (!vis->macro_operator) { + macro_operator_record(vis); + action_reset(vis, &vis->action_prev); + vis->action_prev.macro = vis->macro_operator; + vis->action_prev.op = &ops[OP_REPLACE]; + } +} + +static void vis_mode_replace_leave(Vis *vis, Mode *new) { + /* make sure we can recover the current state after an editing operation */ + text_snapshot(vis->win->file->text); + if (new == mode_get(vis, VIS_MODE_NORMAL)) + macro_operator_stop(vis); +} + +static void vis_mode_replace_input(Vis *vis, const char *str, size_t len) { + vis_replace_key(vis, str, len); +} + + + +/* + * the tree of modes currently looks like this. the double line between OPERATOR-OPTION + * and OPERATOR is only in effect once an operator is detected. that is when entering the + * OPERATOR mode its parent is set to OPERATOR-OPTION which makes {INNER-,}TEXTOBJ + * reachable. once the operator is processed (i.e. the OPERATOR mode is left) its parent + * mode is reset back to MOVE. + * + * Similarly the +-ed line between OPERATOR and TEXTOBJ is only active within the visual + * modes. + * + * + * BASIC + * (arrow keys etc.) + * / | + * /-------------------/ | + * READLINE MOVE + * / \ (h,j,k,l ...) + * / \ | \-----------------\ + * / \ | | + * INSERT PROMPT OPERATOR ++++ INNER-TEXTOBJ + * | (history etc) (d,c,y,p ..) + (i [wsp[]()b<>{}B"'`] ) + * | | \\ + | + * | | \\ + | + * REPLACE NORMAL \\ + TEXTOBJ + * | \\ + (a [wsp[]()b<>{}B"'`] ) + * | \\ + + | + * | \\ + + | + * VISUAL \\ OPERATOR-OPTION + * | \\ (v,V) + * | \\ // + * | \\======// + * VISUAL-LINE + */ + +Mode vis_modes[] = { + [VIS_MODE_BASIC] = { + .name = "BASIC", + .parent = NULL, + }, + [VIS_MODE_MOVE] = { + .name = "MOVE", + .parent = &vis_modes[VIS_MODE_BASIC], + }, + [VIS_MODE_TEXTOBJ] = { + .name = "TEXT-OBJECTS", + .parent = &vis_modes[VIS_MODE_MOVE], + }, + [VIS_MODE_OPERATOR_OPTION] = { + .name = "OPERATOR-OPTION", + .parent = &vis_modes[VIS_MODE_TEXTOBJ], + }, + [VIS_MODE_OPERATOR] = { + .name = "OPERATOR", + .parent = &vis_modes[VIS_MODE_MOVE], + .enter = vis_mode_operator_enter, + .leave = vis_mode_operator_leave, + .input = vis_mode_operator_input, + }, + [VIS_MODE_NORMAL] = { + .name = "NORMAL", + .status = "", + .help = "", + .isuser = true, + .parent = &vis_modes[VIS_MODE_OPERATOR], + }, + [VIS_MODE_VISUAL] = { + .name = "VISUAL", + .status = "--VISUAL--", + .help = "", + .isuser = true, + .parent = &vis_modes[VIS_MODE_OPERATOR], + .enter = vis_mode_visual_enter, + .leave = vis_mode_visual_leave, + .visual = true, + }, + [VIS_MODE_VISUAL_LINE] = { + .name = "VISUAL LINE", + .status = "--VISUAL LINE--", + .help = "", + .isuser = true, + .parent = &vis_modes[VIS_MODE_VISUAL], + .enter = vis_mode_visual_line_enter, + .leave = vis_mode_visual_line_leave, + .visual = true, + }, + [VIS_MODE_READLINE] = { + .name = "READLINE", + .parent = &vis_modes[VIS_MODE_BASIC], + }, + [VIS_MODE_PROMPT] = { + .name = "PROMPT", + .help = "", + .isuser = true, + .parent = &vis_modes[VIS_MODE_READLINE], + .input = vis_mode_prompt_input, + .enter = vis_mode_prompt_enter, + .leave = vis_mode_prompt_leave, + }, + [VIS_MODE_INSERT] = { + .name = "INSERT", + .status = "--INSERT--", + .help = "", + .isuser = true, + .parent = &vis_modes[VIS_MODE_READLINE], + .enter = vis_mode_insert_enter, + .leave = vis_mode_insert_leave, + .input = vis_mode_insert_input, + .idle = vis_mode_insert_idle, + .idle_timeout = 3, + }, + [VIS_MODE_REPLACE] = { + .name = "REPLACE", + .status = "--REPLACE--", + .help = "", + .isuser = true, + .parent = &vis_modes[VIS_MODE_INSERT], + .enter = vis_mode_replace_enter, + .leave = vis_mode_replace_leave, + .input = vis_mode_replace_input, + .idle = vis_mode_insert_idle, + .idle_timeout = 3, + }, +}; + diff --git a/vis.c b/vis.c index 2505d7a..07bcd3c 100644 --- a/vis.c +++ b/vis.c @@ -41,8 +41,6 @@ #include "util.h" #include "vis-core.h" -static void mode_set(Vis *vis, Mode *new_mode); -static Mode *mode_get(Vis *vis, enum VisMode mode); static Macro *macro_get(Vis *vis, enum VisMacro m); static void macro_replay(Vis *vis, const Macro *macro); @@ -496,272 +494,6 @@ static TextObject textobjs[] = { [TEXT_OBJ_INNER_LINE] = { text_object_line_inner, }, }; - - -static void action_reset(Vis*, Action *a); - -static void vis_mode_operator_enter(Vis *vis, Mode *old) { - vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_OPERATOR_OPTION]; -} - -static void vis_mode_operator_leave(Vis *vis, Mode *new) { - vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE]; -} - -static void vis_mode_operator_input(Vis *vis, const char *str, size_t len) { - /* invalid operator */ - action_reset(vis, &vis->action); - mode_set(vis, vis->mode_prev); -} - -static void vis_mode_visual_enter(Vis *vis, Mode *old) { - if (!old->visual) { - for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c)) - view_cursors_selection_start(c); - vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_TEXTOBJ]; - } -} - -static void vis_mode_visual_line_enter(Vis *vis, Mode *old) { - if (!old->visual) { - for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c)) - view_cursors_selection_start(c); - vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_TEXTOBJ]; - } - vis_motion(vis, MOVE_LINE_END); -} - -static void vis_mode_visual_line_leave(Vis *vis, Mode *new) { - if (!new->visual) { - view_selections_clear(vis->win->view); - vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE]; - } else { - view_cursor_to(vis->win->view, view_cursor_get(vis->win->view)); - } -} - -static void vis_mode_visual_leave(Vis *vis, Mode *new) { - if (!new->visual) { - view_selections_clear(vis->win->view); - vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_MOVE]; - } -} - -static void vis_mode_prompt_input(Vis *vis, const char *str, size_t len) { - vis_insert_key(vis, str, len); -} - -static void vis_mode_prompt_enter(Vis *vis, Mode *old) { - if (old->isuser && old != &vis_modes[VIS_MODE_PROMPT]) - vis->mode_before_prompt = old; -} - -static void vis_mode_prompt_leave(Vis *vis, Mode *new) { - if (new->isuser) - vis_prompt_hide(vis); -} - -static void vis_mode_insert_enter(Vis *vis, Mode *old) { - if (!vis->macro_operator) { - macro_operator_record(vis); - action_reset(vis, &vis->action_prev); - vis->action_prev.macro = vis->macro_operator; - vis->action_prev.op = &ops[OP_INSERT]; - } -} - -static void vis_mode_insert_leave(Vis *vis, Mode *new) { - /* make sure we can recover the current state after an editing operation */ - text_snapshot(vis->win->file->text); - if (new == mode_get(vis, VIS_MODE_NORMAL)) - macro_operator_stop(vis); -} - -static void vis_mode_insert_idle(Vis *vis) { - text_snapshot(vis->win->file->text); -} - -static void vis_mode_insert_input(Vis *vis, const char *str, size_t len) { - vis_insert_key(vis, str, len); -} - -static void vis_mode_replace_enter(Vis *vis, Mode *old) { - if (!vis->macro_operator) { - macro_operator_record(vis); - action_reset(vis, &vis->action_prev); - vis->action_prev.macro = vis->macro_operator; - vis->action_prev.op = &ops[OP_REPLACE]; - } -} - -static void vis_mode_replace_leave(Vis *vis, Mode *new) { - /* make sure we can recover the current state after an editing operation */ - text_snapshot(vis->win->file->text); - if (new == mode_get(vis, VIS_MODE_NORMAL)) - macro_operator_stop(vis); -} - -static void vis_mode_replace_input(Vis *vis, const char *str, size_t len) { - vis_replace_key(vis, str, len); -} - -/* - * the tree of modes currently looks like this. the double line between OPERATOR-OPTION - * and OPERATOR is only in effect once an operator is detected. that is when entering the - * OPERATOR mode its parent is set to OPERATOR-OPTION which makes {INNER-,}TEXTOBJ - * reachable. once the operator is processed (i.e. the OPERATOR mode is left) its parent - * mode is reset back to MOVE. - * - * Similarly the +-ed line between OPERATOR and TEXTOBJ is only active within the visual - * modes. - * - * - * BASIC - * (arrow keys etc.) - * / | - * /-------------------/ | - * READLINE MOVE - * / \ (h,j,k,l ...) - * / \ | \-----------------\ - * / \ | | - * INSERT PROMPT OPERATOR ++++ INNER-TEXTOBJ - * | (history etc) (d,c,y,p ..) + (i [wsp[]()b<>{}B"'`] ) - * | | \\ + | - * | | \\ + | - * REPLACE NORMAL \\ + TEXTOBJ - * | \\ + (a [wsp[]()b<>{}B"'`] ) - * | \\ + + | - * | \\ + + | - * VISUAL \\ OPERATOR-OPTION - * | \\ (v,V) - * | \\ // - * | \\======// - * VISUAL-LINE - */ - -Mode vis_modes[] = { - [VIS_MODE_BASIC] = { - .name = "BASIC", - .parent = NULL, - }, - [VIS_MODE_MOVE] = { - .name = "MOVE", - .parent = &vis_modes[VIS_MODE_BASIC], - }, - [VIS_MODE_TEXTOBJ] = { - .name = "TEXT-OBJECTS", - .parent = &vis_modes[VIS_MODE_MOVE], - }, - [VIS_MODE_OPERATOR_OPTION] = { - .name = "OPERATOR-OPTION", - .parent = &vis_modes[VIS_MODE_TEXTOBJ], - }, - [VIS_MODE_OPERATOR] = { - .name = "OPERATOR", - .parent = &vis_modes[VIS_MODE_MOVE], - .enter = vis_mode_operator_enter, - .leave = vis_mode_operator_leave, - .input = vis_mode_operator_input, - }, - [VIS_MODE_NORMAL] = { - .name = "NORMAL", - .status = "", - .help = "", - .isuser = true, - .parent = &vis_modes[VIS_MODE_OPERATOR], - }, - [VIS_MODE_VISUAL] = { - .name = "VISUAL", - .status = "--VISUAL--", - .help = "", - .isuser = true, - .parent = &vis_modes[VIS_MODE_OPERATOR], - .enter = vis_mode_visual_enter, - .leave = vis_mode_visual_leave, - .visual = true, - }, - [VIS_MODE_VISUAL_LINE] = { - .name = "VISUAL LINE", - .status = "--VISUAL LINE--", - .help = "", - .isuser = true, - .parent = &vis_modes[VIS_MODE_VISUAL], - .enter = vis_mode_visual_line_enter, - .leave = vis_mode_visual_line_leave, - .visual = true, - }, - [VIS_MODE_READLINE] = { - .name = "READLINE", - .parent = &vis_modes[VIS_MODE_BASIC], - }, - [VIS_MODE_PROMPT] = { - .name = "PROMPT", - .help = "", - .isuser = true, - .parent = &vis_modes[VIS_MODE_READLINE], - .input = vis_mode_prompt_input, - .enter = vis_mode_prompt_enter, - .leave = vis_mode_prompt_leave, - }, - [VIS_MODE_INSERT] = { - .name = "INSERT", - .status = "--INSERT--", - .help = "", - .isuser = true, - .parent = &vis_modes[VIS_MODE_READLINE], - .enter = vis_mode_insert_enter, - .leave = vis_mode_insert_leave, - .input = vis_mode_insert_input, - .idle = vis_mode_insert_idle, - .idle_timeout = 3, - }, - [VIS_MODE_REPLACE] = { - .name = "REPLACE", - .status = "--REPLACE--", - .help = "", - .isuser = true, - .parent = &vis_modes[VIS_MODE_INSERT], - .enter = vis_mode_replace_enter, - .leave = vis_mode_replace_leave, - .input = vis_mode_replace_input, - .idle = vis_mode_insert_idle, - .idle_timeout = 3, - }, -}; - - -static Mode *mode_get(Vis *vis, enum VisMode mode) { - if (mode < LENGTH(vis_modes)) - return &vis_modes[mode]; - return NULL; -} - -static bool mode_map(Mode *mode, const char *name, KeyBinding *binding) { - return map_put(mode->bindings, name, binding); -} - -bool vis_mode_map(Vis *vis, enum VisMode modeid, const char *name, KeyBinding *binding) { - Mode *mode = mode_get(vis, modeid); - return mode && map_put(mode->bindings, name, binding); -} - -bool vis_mode_bindings(Vis *vis, enum VisMode modeid, KeyBinding **bindings) { - Mode *mode = mode_get(vis, modeid); - if (!mode) - return false; - bool success = true; - for (KeyBinding *kb = *bindings; kb->key; kb++) { - if (!mode_map(mode, kb->key, kb)) - success = false; - } - return success; -} - -bool vis_mode_unmap(Vis *vis, enum VisMode modeid, const char *name) { - Mode *mode = mode_get(vis, modeid); - return mode && map_delete(mode->bindings, name); -} - bool vis_action_register(Vis *vis, KeyAction *action) { if (!vis->actions) vis->actions = map_new(); @@ -932,23 +664,10 @@ static void action_do(Vis *vis, Action *a) { } } -static void action_reset(Vis *vis, Action *a) { +void action_reset(Vis *vis, Action *a) { memset(a, 0, sizeof(*a)); } -static void mode_set(Vis *vis, Mode *new_mode) { - if (vis->mode == new_mode) - return; - if (vis->mode->leave) - vis->mode->leave(vis, new_mode); - if (vis->mode->isuser) - vis->mode_prev = vis->mode; - vis->mode = new_mode; - if (new_mode->enter) - new_mode->enter(vis, vis->mode_prev); - vis->win->ui->draw_status(vis->win->ui); -} - static bool prompt_cmd(Vis *vis, char type, const char *cmd) { if (!cmd || !cmd[0]) return true; -- cgit v1.2.3