vis-lua: expose win.syntax
[vis.git] / vis-modes.c
blobf519b5bd05783a4a3df2bef9f66506f1c3ce1733
1 #include "vis-core.h"
2 #include "util.h"
4 static Mode *mode_get(Vis *vis, enum VisMode mode) {
5 if (mode < LENGTH(vis_modes))
6 return &vis_modes[mode];
7 return NULL;
10 void mode_set(Vis *vis, Mode *new_mode) {
11 if (vis->mode == new_mode)
12 return;
13 if (vis->mode->leave)
14 vis->mode->leave(vis, new_mode);
15 if (vis->mode != &vis_modes[VIS_MODE_OPERATOR_PENDING])
16 vis->mode_prev = vis->mode;
17 vis->mode = new_mode;
18 if (new_mode->enter)
19 new_mode->enter(vis, vis->mode_prev);
20 vis->win->ui->draw_status(vis->win->ui);
23 void vis_mode_switch(Vis *vis, enum VisMode mode) {
24 mode_set(vis, &vis_modes[mode]);
27 static bool mode_map(Mode *mode, const char *key, const KeyBinding *binding) {
28 if (!mode)
29 return false;
30 if (!mode->bindings) {
31 mode->bindings = map_new();
32 if (!mode->bindings)
33 return false;
35 return map_put(mode->bindings, key, binding);
38 bool vis_mode_map(Vis *vis, enum VisMode id, const char *key, const KeyBinding *binding) {
39 return id < LENGTH(vis_modes) && mode_map(&vis_modes[id], key, binding);
42 bool vis_window_mode_map(Win *win, enum VisMode id, const char *key, const KeyBinding *binding) {
43 return id < LENGTH(win->modes) && mode_map(&win->modes[id], key, binding);
46 static bool mode_unmap(Mode *mode, const char *key) {
47 return mode && mode->bindings && map_delete(mode->bindings, key);
50 bool vis_mode_unmap(Vis *vis, enum VisMode id, const char *key) {
51 return id < LENGTH(vis_modes) && mode_unmap(&vis_modes[id], key);
54 bool vis_window_mode_unmap(Win *win, enum VisMode id, const char *key) {
55 return id < LENGTH(win->modes) && mode_unmap(&win->modes[id], key);
58 /** mode switching event handlers */
60 static void vis_mode_operator_input(Vis *vis, const char *str, size_t len) {
61 /* invalid operator */
62 vis_cancel(vis);
63 mode_set(vis, vis->mode_prev);
66 static void vis_mode_visual_enter(Vis *vis, Mode *old) {
67 if (!old->visual) {
68 for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c))
69 view_cursors_selection_start(c);
73 static void vis_mode_visual_line_enter(Vis *vis, Mode *old) {
74 if (!old->visual) {
75 for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c))
76 view_cursors_selection_start(c);
78 vis_motion(vis, VIS_MOVE_NOP);
81 static void vis_mode_visual_line_leave(Vis *vis, Mode *new) {
82 if (!new->visual) {
83 window_selection_save(vis->win);
84 view_selections_clear(vis->win->view);
85 } else {
86 view_cursor_to(vis->win->view, view_cursor_get(vis->win->view));
90 static void vis_mode_visual_leave(Vis *vis, Mode *new) {
91 if (!new->visual) {
92 window_selection_save(vis->win);
93 view_selections_clear(vis->win->view);
97 static void vis_mode_insert_enter(Vis *vis, Mode *old) {
98 if (!vis->macro_operator) {
99 macro_operator_record(vis);
100 action_reset(&vis->action_prev);
101 vis->action_prev.macro = vis->macro_operator;
102 vis->action_prev.op = &vis_operators[VIS_OP_INSERT];
106 static void vis_mode_insert_leave(Vis *vis, Mode *new) {
107 /* make sure we can recover the current state after an editing operation */
108 text_snapshot(vis->win->file->text);
109 if (new == mode_get(vis, VIS_MODE_NORMAL))
110 macro_operator_stop(vis);
113 static void vis_mode_insert_idle(Vis *vis) {
114 text_snapshot(vis->win->file->text);
117 static void vis_mode_insert_input(Vis *vis, const char *str, size_t len) {
118 vis_insert_key(vis, str, len);
121 static void vis_mode_replace_enter(Vis *vis, Mode *old) {
122 if (!vis->macro_operator) {
123 macro_operator_record(vis);
124 action_reset(&vis->action_prev);
125 vis->action_prev.macro = vis->macro_operator;
126 vis->action_prev.op = &vis_operators[VIS_OP_REPLACE];
130 static void vis_mode_replace_leave(Vis *vis, Mode *new) {
131 /* make sure we can recover the current state after an editing operation */
132 text_snapshot(vis->win->file->text);
133 if (new == mode_get(vis, VIS_MODE_NORMAL))
134 macro_operator_stop(vis);
137 static void vis_mode_replace_input(Vis *vis, const char *str, size_t len) {
138 vis_replace_key(vis, str, len);
141 Mode vis_modes[] = {
142 [VIS_MODE_OPERATOR_PENDING] = {
143 .id = VIS_MODE_OPERATOR_PENDING,
144 .name = "OPERATOR-PENDING",
145 .input = vis_mode_operator_input,
146 .help = "",
148 [VIS_MODE_NORMAL] = {
149 .id = VIS_MODE_NORMAL,
150 .name = "NORMAL",
151 .status = "",
152 .help = "",
154 [VIS_MODE_VISUAL] = {
155 .id = VIS_MODE_VISUAL,
156 .name = "VISUAL",
157 .status = "--VISUAL--",
158 .help = "",
159 .enter = vis_mode_visual_enter,
160 .leave = vis_mode_visual_leave,
161 .visual = true,
163 [VIS_MODE_VISUAL_LINE] = {
164 .id = VIS_MODE_VISUAL_LINE,
165 .name = "VISUAL LINE",
166 .parent = &vis_modes[VIS_MODE_VISUAL],
167 .status = "--VISUAL LINE--",
168 .help = "",
169 .enter = vis_mode_visual_line_enter,
170 .leave = vis_mode_visual_line_leave,
171 .visual = true,
173 [VIS_MODE_INSERT] = {
174 .id = VIS_MODE_INSERT,
175 .name = "INSERT",
176 .status = "--INSERT--",
177 .help = "",
178 .enter = vis_mode_insert_enter,
179 .leave = vis_mode_insert_leave,
180 .input = vis_mode_insert_input,
181 .idle = vis_mode_insert_idle,
182 .idle_timeout = 3,
184 [VIS_MODE_REPLACE] = {
185 .id = VIS_MODE_REPLACE,
186 .name = "REPLACE",
187 .parent = &vis_modes[VIS_MODE_INSERT],
188 .status = "--REPLACE--",
189 .help = "",
190 .enter = vis_mode_replace_enter,
191 .leave = vis_mode_replace_leave,
192 .input = vis_mode_replace_input,
193 .idle = vis_mode_insert_idle,
194 .idle_timeout = 3,