build: create empty config.mk if it does not exist
[vis.git] / vis-modes.c
blob177b0346caedbab34dd46bc926f17b93b90cb908
1 #include <string.h>
2 #include "vis-core.h"
3 #include "util.h"
5 static Mode *mode_get(Vis *vis, enum VisMode mode) {
6 if (mode < LENGTH(vis_modes))
7 return &vis_modes[mode];
8 return NULL;
11 void mode_set(Vis *vis, Mode *new_mode) {
12 if (vis->mode == new_mode)
13 return;
14 if (vis->mode->leave)
15 vis->mode->leave(vis, new_mode);
16 if (vis->mode != &vis_modes[VIS_MODE_OPERATOR_PENDING])
17 vis->mode_prev = vis->mode;
18 vis->mode = new_mode;
19 if (new_mode->enter)
20 new_mode->enter(vis, vis->mode_prev);
21 vis->win->ui->draw_status(vis->win->ui);
24 void vis_mode_switch(Vis *vis, enum VisMode mode) {
25 mode_set(vis, &vis_modes[mode]);
28 static bool mode_map(Mode *mode, const char *key, const KeyBinding *binding) {
29 if (!mode)
30 return false;
31 if (binding->alias && key[0] != '<' && strncmp(key, binding->alias, strlen(key)) == 0)
32 return false;
33 if (!mode->bindings) {
34 mode->bindings = map_new();
35 if (!mode->bindings)
36 return false;
38 return map_put(mode->bindings, key, binding);
41 bool vis_mode_map(Vis *vis, enum VisMode id, const char *key, const KeyBinding *binding) {
42 return id < LENGTH(vis_modes) && mode_map(&vis_modes[id], key, binding);
45 bool vis_window_mode_map(Win *win, enum VisMode id, const char *key, const KeyBinding *binding) {
46 return id < LENGTH(win->modes) && mode_map(&win->modes[id], key, binding);
49 static bool mode_unmap(Mode *mode, const char *key) {
50 return mode && mode->bindings && map_delete(mode->bindings, key);
53 bool vis_mode_unmap(Vis *vis, enum VisMode id, const char *key) {
54 return id < LENGTH(vis_modes) && mode_unmap(&vis_modes[id], key);
57 bool vis_window_mode_unmap(Win *win, enum VisMode id, const char *key) {
58 return id < LENGTH(win->modes) && mode_unmap(&win->modes[id], key);
61 /** mode switching event handlers */
63 static void vis_mode_operator_input(Vis *vis, const char *str, size_t len) {
64 /* invalid operator */
65 vis_cancel(vis);
66 mode_set(vis, vis->mode_prev);
69 static void vis_mode_visual_enter(Vis *vis, Mode *old) {
70 if (!old->visual) {
71 for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c))
72 view_cursors_selection_start(c);
76 static void vis_mode_visual_line_enter(Vis *vis, Mode *old) {
77 if (!old->visual) {
78 for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c))
79 view_cursors_selection_start(c);
81 vis_motion(vis, VIS_MOVE_NOP);
84 static void vis_mode_visual_line_leave(Vis *vis, Mode *new) {
85 if (!new->visual) {
86 window_selection_save(vis->win);
87 view_selections_clear(vis->win->view);
88 } else {
89 view_cursor_to(vis->win->view, view_cursor_get(vis->win->view));
93 static void vis_mode_visual_leave(Vis *vis, Mode *new) {
94 if (!new->visual) {
95 window_selection_save(vis->win);
96 view_selections_clear(vis->win->view);
100 static void vis_mode_insert_enter(Vis *vis, Mode *old) {
101 if (!vis->macro_operator) {
102 macro_operator_record(vis);
103 action_reset(&vis->action_prev);
104 vis->action_prev.macro = vis->macro_operator;
105 vis->action_prev.op = &vis_operators[VIS_OP_INSERT];
109 static void vis_mode_insert_leave(Vis *vis, Mode *new) {
110 /* make sure we can recover the current state after an editing operation */
111 text_snapshot(vis->win->file->text);
112 if (new == mode_get(vis, VIS_MODE_NORMAL))
113 macro_operator_stop(vis);
116 static void vis_mode_insert_idle(Vis *vis) {
117 text_snapshot(vis->win->file->text);
120 static void vis_mode_insert_input(Vis *vis, const char *str, size_t len) {
121 vis_insert_key(vis, str, len);
124 static void vis_mode_replace_enter(Vis *vis, Mode *old) {
125 if (!vis->macro_operator) {
126 macro_operator_record(vis);
127 action_reset(&vis->action_prev);
128 vis->action_prev.macro = vis->macro_operator;
129 vis->action_prev.op = &vis_operators[VIS_OP_REPLACE];
133 static void vis_mode_replace_leave(Vis *vis, Mode *new) {
134 /* make sure we can recover the current state after an editing operation */
135 text_snapshot(vis->win->file->text);
136 if (new == mode_get(vis, VIS_MODE_NORMAL))
137 macro_operator_stop(vis);
140 static void vis_mode_replace_input(Vis *vis, const char *str, size_t len) {
141 vis_replace_key(vis, str, len);
144 Mode vis_modes[] = {
145 [VIS_MODE_OPERATOR_PENDING] = {
146 .id = VIS_MODE_OPERATOR_PENDING,
147 .name = "OPERATOR-PENDING",
148 .input = vis_mode_operator_input,
149 .help = "",
151 [VIS_MODE_NORMAL] = {
152 .id = VIS_MODE_NORMAL,
153 .name = "NORMAL",
154 .status = "",
155 .help = "",
157 [VIS_MODE_VISUAL] = {
158 .id = VIS_MODE_VISUAL,
159 .name = "VISUAL",
160 .status = "--VISUAL--",
161 .help = "",
162 .enter = vis_mode_visual_enter,
163 .leave = vis_mode_visual_leave,
164 .visual = true,
166 [VIS_MODE_VISUAL_LINE] = {
167 .id = VIS_MODE_VISUAL_LINE,
168 .name = "VISUAL LINE",
169 .parent = &vis_modes[VIS_MODE_VISUAL],
170 .status = "--VISUAL LINE--",
171 .help = "",
172 .enter = vis_mode_visual_line_enter,
173 .leave = vis_mode_visual_line_leave,
174 .visual = true,
176 [VIS_MODE_INSERT] = {
177 .id = VIS_MODE_INSERT,
178 .name = "INSERT",
179 .status = "--INSERT--",
180 .help = "",
181 .enter = vis_mode_insert_enter,
182 .leave = vis_mode_insert_leave,
183 .input = vis_mode_insert_input,
184 .idle = vis_mode_insert_idle,
185 .idle_timeout = 3,
187 [VIS_MODE_REPLACE] = {
188 .id = VIS_MODE_REPLACE,
189 .name = "REPLACE",
190 .parent = &vis_modes[VIS_MODE_INSERT],
191 .status = "--REPLACE--",
192 .help = "",
193 .enter = vis_mode_replace_enter,
194 .leave = vis_mode_replace_leave,
195 .input = vis_mode_replace_input,
196 .idle = vis_mode_insert_idle,
197 .idle_timeout = 3,