10 #include "text-util.h"
11 #include "text-motions.h"
12 #include "text-objects.h"
17 #define PAGE_HALF (INT_MAX-1)
19 /** functions to be called from keybindings */
20 /* ignore key, do nothing */
21 static const char *nop(Vis
*, const char *keys
, const Arg
*arg
);
22 /* record/replay macro indicated by keys */
23 static const char *macro_record(Vis
*, const char *keys
, const Arg
*arg
);
24 static const char *macro_replay(Vis
*, const char *keys
, const Arg
*arg
);
25 /* temporarily suspend the editor and return to the shell, type 'fg' to get back */
26 static const char *suspend(Vis
*, const char *keys
, const Arg
*arg
);
27 /* switch to mode indicated by arg->i */
28 static const char *switchmode(Vis
*, const char *keys
, const Arg
*arg
);
29 /* switch to insert mode after performing movement indicated by arg->i */
30 static const char *insertmode(Vis
*, const char *keys
, const Arg
*arg
);
31 /* set mark indicated by keys to current cursor position */
32 static const char *mark_set(Vis
*, const char *keys
, const Arg
*arg
);
33 /* add a new line either before or after the one where the cursor currently is */
34 static const char *openline(Vis
*, const char *keys
, const Arg
*arg
);
35 /* join lines from current cursor position to movement indicated by arg */
36 static const char *join(Vis
*, const char *keys
, const Arg
*arg
);
37 /* perform last action i.e. action_prev again */
38 static const char *repeat(Vis
*, const char *keys
, const Arg
*arg
);
39 /* replace character at cursor with one from keys */
40 static const char *replace(Vis
*, const char *keys
, const Arg
*arg
);
41 /* create a new cursor on the previous (arg->i < 0) or next (arg->i > 0) line */
42 static const char *cursors_new(Vis
*, const char *keys
, const Arg
*arg
);
43 /* try to align all cursors on the same column */
44 static const char *cursors_align(Vis
*, const char *keys
, const Arg
*arg
);
45 /* try to align all cursors by inserting the correct amount of white spaces */
46 static const char *cursors_align_indent(Vis
*, const char *keys
, const Arg
*arg
);
47 /* remove all but the primary cursor and their selections */
48 static const char *cursors_clear(Vis
*, const char *keys
, const Arg
*arg
);
49 /* remove the least recently added cursor */
50 static const char *cursors_remove(Vis
*, const char *keys
, const Arg
*arg
);
51 /* move to the previous (arg->i < 0) or next (arg->i > 0) cursor */
52 static const char *cursors_navigate(Vis
*, const char *keys
, const Arg
*arg
);
53 /* select the word the cursor is currently over */
54 static const char *cursors_select(Vis
*, const char *keys
, const Arg
*arg
);
55 /* select the next region matching the current selection */
56 static const char *cursors_select_next(Vis
*, const char *keys
, const Arg
*arg
);
57 /* clear current selection but select next match */
58 static const char *cursors_select_skip(Vis
*, const char *keys
, const Arg
*arg
);
59 /* adjust current used count according to keys */
60 static const char *count(Vis
*, const char *keys
, const Arg
*arg
);
61 /* move to the count-th line or if not given either to the first (arg->i < 0)
62 * or last (arg->i > 0) line of file */
63 static const char *gotoline(Vis
*, const char *keys
, const Arg
*arg
);
64 /* set motion type either LINEWISE or CHARWISE via arg->i */
65 static const char *motiontype(Vis
*, const char *keys
, const Arg
*arg
);
66 /* make the current action use the operator indicated by arg->i */
67 static const char *operator(Vis
*, const char *keys
, const Arg
*arg
);
68 /* use arg->s as command for the filter operator */
69 static const char *operator_filter(Vis
*, const char *keys
, const Arg
*arg
);
70 /* blocks to read a key and performs movement indicated by arg->i which
71 * should be one of VIS_MOVE_{RIGHT,LEFT}_{TO,TILL} */
72 static const char *movement_key(Vis
*, const char *keys
, const Arg
*arg
);
73 /* perform the movement as indicated by arg->i */
74 static const char *movement(Vis
*, const char *keys
, const Arg
*arg
);
75 /* let the current operator affect the range indicated by the text object arg->i */
76 static const char *textobj(Vis
*, const char *keys
, const Arg
*arg
);
77 /* move to the other end of selected text */
78 static const char *selection_end(Vis
*, const char *keys
, const Arg
*arg
);
79 /* restore least recently used selection */
80 static const char *selection_restore(Vis
*, const char *keys
, const Arg
*arg
);
81 /* use register indicated by keys for the current operator */
82 static const char *reg(Vis
*, const char *keys
, const Arg
*arg
);
83 /* perform arg->i motion with a mark indicated by keys as argument */
84 static const char *mark_motion(Vis
*, const char *keys
, const Arg
*arg
);
85 /* {un,re}do last action, redraw window */
86 static const char *undo(Vis
*, const char *keys
, const Arg
*arg
);
87 static const char *redo(Vis
*, const char *keys
, const Arg
*arg
);
88 /* earlier, later action chronologically, redraw window */
89 static const char *earlier(Vis
*, const char *keys
, const Arg
*arg
);
90 static const char *later(Vis
*, const char *keys
, const Arg
*arg
);
91 /* delete from the current cursor position to the end of
92 * movement as indicated by arg->i */
93 static const char *delete(Vis
*, const char *keys
, const Arg
*arg
);
94 /* insert register content indicated by keys at current cursor position */
95 static const char *insert_register(Vis
*, const char *keys
, const Arg
*arg
);
96 /* show a user prompt to get input with title arg->s */
97 static const char *prompt_show(Vis
*, const char *keys
, const Arg
*arg
);
98 /* blocks to read 3 consecutive digits and inserts the corresponding byte value */
99 static const char *insert_verbatim(Vis
*, const char *keys
, const Arg
*arg
);
100 /* scroll window content according to arg->i which can be either PAGE, PAGE_HALF,
101 * or an arbitrary number of lines. a multiplier overrides what is given in arg->i.
102 * negative values scroll back, positive forward. */
103 static const char *wscroll(Vis
*, const char *keys
, const Arg
*arg
);
104 /* similar to scroll, but do only move window content not cursor position */
105 static const char *wslide(Vis
*, const char *keys
, const Arg
*arg
);
106 /* call editor function as indicated by arg->f */
107 static const char *call(Vis
*, const char *keys
, const Arg
*arg
);
108 /* call window function as indicated by arg->w */
109 static const char *window(Vis
*, const char *keys
, const Arg
*arg
);
110 /* show info about Unicode character at cursor position */
111 static const char *unicode_info(Vis
*, const char *keys
, const Arg
*arg
);
112 /* either go to count % of ile or to matching item */
113 static const char *percent(Vis
*, const char *keys
, const Arg
*arg
);
114 /* either increment (arg->i > 0) or decrement (arg->i < 0) number under cursor */
115 static const char *number_increment_decrement(Vis
*, const char *keys
, const Arg
*arg
);
116 /* open a filename under cursor in same (!arg->b) or new (arg->b) window */
117 static const char *open_file_under_cursor(Vis
*, const char *keys
, const Arg
*arg
);
120 VIS_ACTION_EDITOR_SUSPEND
,
121 VIS_ACTION_CURSOR_CHAR_PREV
,
122 VIS_ACTION_CURSOR_CHAR_NEXT
,
123 VIS_ACTION_CURSOR_WORD_START_PREV
,
124 VIS_ACTION_CURSOR_WORD_START_NEXT
,
125 VIS_ACTION_CURSOR_WORD_END_PREV
,
126 VIS_ACTION_CURSOR_WORD_END_NEXT
,
127 VIS_ACTION_CURSOR_LONGWORD_START_PREV
,
128 VIS_ACTION_CURSOR_LONGWORD_START_NEXT
,
129 VIS_ACTION_CURSOR_LONGWORD_END_PREV
,
130 VIS_ACTION_CURSOR_LONGWORD_END_NEXT
,
131 VIS_ACTION_CURSOR_LINE_UP
,
132 VIS_ACTION_CURSOR_LINE_DOWN
,
133 VIS_ACTION_CURSOR_LINE_START
,
134 VIS_ACTION_CURSOR_LINE_FINISH
,
135 VIS_ACTION_CURSOR_LINE_BEGIN
,
136 VIS_ACTION_CURSOR_LINE_END
,
137 VIS_ACTION_CURSOR_LINE_LASTCHAR
,
138 VIS_ACTION_CURSOR_SCREEN_LINE_UP
,
139 VIS_ACTION_CURSOR_SCREEN_LINE_DOWN
,
140 VIS_ACTION_CURSOR_SCREEN_LINE_BEGIN
,
141 VIS_ACTION_CURSOR_SCREEN_LINE_MIDDLE
,
142 VIS_ACTION_CURSOR_SCREEN_LINE_END
,
143 VIS_ACTION_CURSOR_PERCENT
,
144 VIS_ACTION_CURSOR_PARAGRAPH_PREV
,
145 VIS_ACTION_CURSOR_PARAGRAPH_NEXT
,
146 VIS_ACTION_CURSOR_SENTENCE_PREV
,
147 VIS_ACTION_CURSOR_SENTENCE_NEXT
,
148 VIS_ACTION_CURSOR_FUNCTION_START_PREV
,
149 VIS_ACTION_CURSOR_FUNCTION_END_PREV
,
150 VIS_ACTION_CURSOR_FUNCTION_START_NEXT
,
151 VIS_ACTION_CURSOR_FUNCTION_END_NEXT
,
152 VIS_ACTION_CURSOR_COLUMN
,
153 VIS_ACTION_CURSOR_LINE_FIRST
,
154 VIS_ACTION_CURSOR_LINE_LAST
,
155 VIS_ACTION_CURSOR_WINDOW_LINE_TOP
,
156 VIS_ACTION_CURSOR_WINDOW_LINE_MIDDLE
,
157 VIS_ACTION_CURSOR_WINDOW_LINE_BOTTOM
,
158 VIS_ACTION_CURSOR_SEARCH_NEXT
,
159 VIS_ACTION_CURSOR_SEARCH_PREV
,
160 VIS_ACTION_CURSOR_SEARCH_WORD_FORWARD
,
161 VIS_ACTION_CURSOR_SEARCH_WORD_BACKWARD
,
162 VIS_ACTION_WINDOW_PAGE_UP
,
163 VIS_ACTION_WINDOW_PAGE_DOWN
,
164 VIS_ACTION_WINDOW_HALFPAGE_UP
,
165 VIS_ACTION_WINDOW_HALFPAGE_DOWN
,
166 VIS_ACTION_MODE_NORMAL
,
167 VIS_ACTION_MODE_VISUAL
,
168 VIS_ACTION_MODE_VISUAL_LINE
,
169 VIS_ACTION_MODE_INSERT
,
170 VIS_ACTION_MODE_REPLACE
,
171 VIS_ACTION_MODE_OPERATOR_PENDING
,
172 VIS_ACTION_DELETE_CHAR_PREV
,
173 VIS_ACTION_DELETE_CHAR_NEXT
,
174 VIS_ACTION_DELETE_LINE_BEGIN
,
175 VIS_ACTION_DELETE_WORD_PREV
,
176 VIS_ACTION_JUMPLIST_PREV
,
177 VIS_ACTION_JUMPLIST_NEXT
,
178 VIS_ACTION_CHANGELIST_PREV
,
179 VIS_ACTION_CHANGELIST_NEXT
,
184 VIS_ACTION_MACRO_RECORD
,
185 VIS_ACTION_MACRO_REPLAY
,
187 VIS_ACTION_MARK_GOTO
,
188 VIS_ACTION_MARK_GOTO_LINE
,
190 VIS_ACTION_REPLACE_CHAR
,
191 VIS_ACTION_TOTILL_REPEAT
,
192 VIS_ACTION_TOTILL_REVERSE
,
193 VIS_ACTION_PROMPT_SEARCH_FORWARD
,
194 VIS_ACTION_PROMPT_SEARCH_BACKWARD
,
195 VIS_ACTION_TILL_LEFT
,
196 VIS_ACTION_TILL_RIGHT
,
200 VIS_ACTION_OPERATOR_CHANGE
,
201 VIS_ACTION_OPERATOR_DELETE
,
202 VIS_ACTION_OPERATOR_YANK
,
203 VIS_ACTION_OPERATOR_SHIFT_LEFT
,
204 VIS_ACTION_OPERATOR_SHIFT_RIGHT
,
205 VIS_ACTION_OPERATOR_CASE_LOWER
,
206 VIS_ACTION_OPERATOR_CASE_UPPER
,
207 VIS_ACTION_OPERATOR_CASE_SWAP
,
208 VIS_ACTION_OPERATOR_FILTER
,
209 VIS_ACTION_OPERATOR_FILTER_FMT
,
211 VIS_ACTION_INSERT_NEWLINE
,
212 VIS_ACTION_INSERT_TAB
,
213 VIS_ACTION_INSERT_VERBATIM
,
214 VIS_ACTION_INSERT_REGISTER
,
215 VIS_ACTION_WINDOW_NEXT
,
216 VIS_ACTION_WINDOW_PREV
,
217 VIS_ACTION_APPEND_CHAR_NEXT
,
218 VIS_ACTION_APPEND_LINE_END
,
219 VIS_ACTION_INSERT_LINE_START
,
220 VIS_ACTION_OPEN_LINE_ABOVE
,
221 VIS_ACTION_OPEN_LINE_BELOW
,
222 VIS_ACTION_JOIN_LINE_BELOW
,
223 VIS_ACTION_JOIN_LINES
,
224 VIS_ACTION_PROMPT_SHOW
,
225 VIS_ACTION_PROMPT_SHOW_VISUAL
,
227 VIS_ACTION_SELECTION_FLIP
,
228 VIS_ACTION_SELECTION_RESTORE
,
229 VIS_ACTION_WINDOW_REDRAW_TOP
,
230 VIS_ACTION_WINDOW_REDRAW_CENTER
,
231 VIS_ACTION_WINDOW_REDRAW_BOTTOM
,
232 VIS_ACTION_WINDOW_SLIDE_UP
,
233 VIS_ACTION_WINDOW_SLIDE_DOWN
,
234 VIS_ACTION_PUT_AFTER
,
235 VIS_ACTION_PUT_BEFORE
,
236 VIS_ACTION_PUT_AFTER_END
,
237 VIS_ACTION_PUT_BEFORE_END
,
238 VIS_ACTION_CURSOR_SELECT_WORD
,
239 VIS_ACTION_CURSORS_NEW_LINE_ABOVE
,
240 VIS_ACTION_CURSORS_NEW_LINE_BELOW
,
241 VIS_ACTION_CURSORS_NEW_LINES_BEGIN
,
242 VIS_ACTION_CURSORS_NEW_LINES_END
,
243 VIS_ACTION_CURSORS_NEW_MATCH_NEXT
,
244 VIS_ACTION_CURSORS_NEW_MATCH_SKIP
,
245 VIS_ACTION_CURSORS_ALIGN
,
246 VIS_ACTION_CURSORS_ALIGN_INDENT
,
247 VIS_ACTION_CURSORS_REMOVE_ALL
,
248 VIS_ACTION_CURSORS_REMOVE_LAST
,
249 VIS_ACTION_CURSORS_PREV
,
250 VIS_ACTION_CURSORS_NEXT
,
251 VIS_ACTION_TEXT_OBJECT_WORD_OUTER
,
252 VIS_ACTION_TEXT_OBJECT_WORD_INNER
,
253 VIS_ACTION_TEXT_OBJECT_LONGWORD_OUTER
,
254 VIS_ACTION_TEXT_OBJECT_LONGWORD_INNER
,
255 VIS_ACTION_TEXT_OBJECT_SENTENCE
,
256 VIS_ACTION_TEXT_OBJECT_PARAGRAPH
,
257 VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_OUTER
,
258 VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_INNER
,
259 VIS_ACTION_TEXT_OBJECT_PARANTHESE_OUTER
,
260 VIS_ACTION_TEXT_OBJECT_PARANTHESE_INNER
,
261 VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_OUTER
,
262 VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_INNER
,
263 VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_OUTER
,
264 VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_INNER
,
265 VIS_ACTION_TEXT_OBJECT_QUOTE_OUTER
,
266 VIS_ACTION_TEXT_OBJECT_QUOTE_INNER
,
267 VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_OUTER
,
268 VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_INNER
,
269 VIS_ACTION_TEXT_OBJECT_BACKTICK_OUTER
,
270 VIS_ACTION_TEXT_OBJECT_BACKTICK_INNER
,
271 VIS_ACTION_TEXT_OBJECT_ENTIRE_OUTER
,
272 VIS_ACTION_TEXT_OBJECT_ENTIRE_INNER
,
273 VIS_ACTION_TEXT_OBJECT_FUNCTION_OUTER
,
274 VIS_ACTION_TEXT_OBJECT_FUNCTION_INNER
,
275 VIS_ACTION_TEXT_OBJECT_LINE_OUTER
,
276 VIS_ACTION_TEXT_OBJECT_LINE_INNER
,
277 VIS_ACTION_TEXT_OBJECT_INDENTATION
,
278 VIS_ACTION_TEXT_OBJECT_SEARCH_FORWARD
,
279 VIS_ACTION_TEXT_OBJECT_SEARCH_BACKWARD
,
280 VIS_ACTION_MOTION_CHARWISE
,
281 VIS_ACTION_MOTION_LINEWISE
,
282 VIS_ACTION_UNICODE_INFO
,
283 VIS_ACTION_NUMBER_INCREMENT
,
284 VIS_ACTION_NUMBER_DECREMENT
,
285 VIS_ACTION_OPEN_FILE_UNDER_CURSOR
,
286 VIS_ACTION_OPEN_FILE_UNDER_CURSOR_NEW_WINDOW
,
290 static const KeyAction vis_action
[] = {
291 [VIS_ACTION_EDITOR_SUSPEND
] = {
293 "Suspend the editor",
296 [VIS_ACTION_CURSOR_CHAR_PREV
] = {
298 "Move cursor left, to the previous character",
299 movement
, { .i
= VIS_MOVE_CHAR_PREV
}
301 [VIS_ACTION_CURSOR_CHAR_NEXT
] = {
303 "Move cursor right, to the next character",
304 movement
, { .i
= VIS_MOVE_CHAR_NEXT
}
306 [VIS_ACTION_CURSOR_WORD_START_PREV
] = {
307 "cursor-word-start-prev",
308 "Move cursor words backwards",
309 movement
, { .i
= VIS_MOVE_WORD_START_PREV
}
311 [VIS_ACTION_CURSOR_WORD_START_NEXT
] = {
312 "cursor-word-start-next",
313 "Move cursor words forwards",
314 movement
, { .i
= VIS_MOVE_WORD_START_NEXT
}
316 [VIS_ACTION_CURSOR_WORD_END_PREV
] = {
317 "cursor-word-end-prev",
318 "Move cursor backwards to the end of word",
319 movement
, { .i
= VIS_MOVE_WORD_END_PREV
}
321 [VIS_ACTION_CURSOR_WORD_END_NEXT
] = {
322 "cursor-word-end-next",
323 "Move cursor forward to the end of word",
324 movement
, { .i
= VIS_MOVE_WORD_END_NEXT
}
326 [VIS_ACTION_CURSOR_LONGWORD_START_PREV
] = {
327 "cursor-longword-start-prev",
328 "Move cursor WORDS backwards",
329 movement
, { .i
= VIS_MOVE_LONGWORD_START_PREV
}
331 [VIS_ACTION_CURSOR_LONGWORD_START_NEXT
] = {
332 "cursor-longword-start-next",
333 "Move cursor WORDS forwards",
334 movement
, { .i
= VIS_MOVE_LONGWORD_START_NEXT
}
336 [VIS_ACTION_CURSOR_LONGWORD_END_PREV
] = {
337 "cursor-longword-end-prev",
338 "Move cursor backwards to the end of WORD",
339 movement
, { .i
= VIS_MOVE_LONGWORD_END_PREV
}
341 [VIS_ACTION_CURSOR_LONGWORD_END_NEXT
] = {
342 "cursor-longword-end-next",
343 "Move cursor forward to the end of WORD",
344 movement
, { .i
= VIS_MOVE_LONGWORD_END_NEXT
}
346 [VIS_ACTION_CURSOR_LINE_UP
] = {
348 "Move cursor line upwards",
349 movement
, { .i
= VIS_MOVE_LINE_UP
}
351 [VIS_ACTION_CURSOR_LINE_DOWN
] = {
353 "Move cursor line downwards",
354 movement
, { .i
= VIS_MOVE_LINE_DOWN
}
356 [VIS_ACTION_CURSOR_LINE_START
] = {
358 "Move cursor to first non-blank character of the line",
359 movement
, { .i
= VIS_MOVE_LINE_START
}
361 [VIS_ACTION_CURSOR_LINE_FINISH
] = {
362 "cursor-line-finish",
363 "Move cursor to last non-blank character of the line",
364 movement
, { .i
= VIS_MOVE_LINE_FINISH
}
366 [VIS_ACTION_CURSOR_LINE_BEGIN
] = {
368 "Move cursor to first character of the line",
369 movement
, { .i
= VIS_MOVE_LINE_BEGIN
}
371 [VIS_ACTION_CURSOR_LINE_END
] = {
373 "Move cursor to end of the line",
374 movement
, { .i
= VIS_MOVE_LINE_END
}
376 [VIS_ACTION_CURSOR_LINE_LASTCHAR
] = {
377 "cursor-line-lastchar",
378 "Move cursor to last character of the line",
379 movement
, { .i
= VIS_MOVE_LINE_LASTCHAR
}
381 [VIS_ACTION_CURSOR_SCREEN_LINE_UP
] = {
382 "cursor-sceenline-up",
383 "Move cursor screen/display line upwards",
384 movement
, { .i
= VIS_MOVE_SCREEN_LINE_UP
}
386 [VIS_ACTION_CURSOR_SCREEN_LINE_DOWN
] = {
387 "cursor-screenline-down",
388 "Move cursor screen/display line downwards",
389 movement
, { .i
= VIS_MOVE_SCREEN_LINE_DOWN
}
391 [VIS_ACTION_CURSOR_SCREEN_LINE_BEGIN
] = {
392 "cursor-screenline-begin",
393 "Move cursor to beginning of screen/display line",
394 movement
, { .i
= VIS_MOVE_SCREEN_LINE_BEGIN
}
396 [VIS_ACTION_CURSOR_SCREEN_LINE_MIDDLE
] = {
397 "cursor-screenline-middle",
398 "Move cursor to middle of screen/display line",
399 movement
, { .i
= VIS_MOVE_SCREEN_LINE_MIDDLE
}
401 [VIS_ACTION_CURSOR_SCREEN_LINE_END
] = {
402 "cursor-screenline-end",
403 "Move cursor to end of screen/display line",
404 movement
, { .i
= VIS_MOVE_SCREEN_LINE_END
}
406 [VIS_ACTION_CURSOR_PERCENT
] = {
408 "Move to count % of file or matching item",
411 [VIS_ACTION_CURSOR_PARAGRAPH_PREV
] = {
412 "cursor-paragraph-prev",
413 "Move cursor paragraph backward",
414 movement
, { .i
= VIS_MOVE_PARAGRAPH_PREV
}
416 [VIS_ACTION_CURSOR_PARAGRAPH_NEXT
] = {
417 "cursor-paragraph-next",
418 "Move cursor paragraph forward",
419 movement
, { .i
= VIS_MOVE_PARAGRAPH_NEXT
}
421 [VIS_ACTION_CURSOR_SENTENCE_PREV
] = {
422 "cursor-sentence-prev",
423 "Move cursor sentence backward",
424 movement
, { .i
= VIS_MOVE_SENTENCE_PREV
}
426 [VIS_ACTION_CURSOR_SENTENCE_NEXT
] = {
427 "cursor-sentence-next",
428 "Move cursor sentence forward",
429 movement
, { .i
= VIS_MOVE_SENTENCE_NEXT
}
431 [VIS_ACTION_CURSOR_FUNCTION_START_PREV
] = {
432 "cursor-function-start-prev",
433 "Move cursor backwards to start of function",
434 movement
, { .i
= VIS_MOVE_FUNCTION_START_PREV
}
436 [VIS_ACTION_CURSOR_FUNCTION_START_NEXT
] = {
437 "cursor-function-start-next",
438 "Move cursor forwards to start of function",
439 movement
, { .i
= VIS_MOVE_FUNCTION_START_NEXT
}
441 [VIS_ACTION_CURSOR_FUNCTION_END_PREV
] = {
442 "cursor-function-end-prev",
443 "Move cursor backwards to end of function",
444 movement
, { .i
= VIS_MOVE_FUNCTION_END_PREV
}
446 [VIS_ACTION_CURSOR_FUNCTION_END_NEXT
] = {
447 "cursor-function-end-next",
448 "Move cursor forwards to end of function",
449 movement
, { .i
= VIS_MOVE_FUNCTION_END_NEXT
}
451 [VIS_ACTION_CURSOR_COLUMN
] = {
453 "Move cursor to given column of current line",
454 movement
, { .i
= VIS_MOVE_COLUMN
}
456 [VIS_ACTION_CURSOR_LINE_FIRST
] = {
458 "Move cursor to given line (defaults to first)",
459 gotoline
, { .i
= -1 }
461 [VIS_ACTION_CURSOR_LINE_LAST
] = {
463 "Move cursor to given line (defaults to last)",
464 gotoline
, { .i
= +1 }
466 [VIS_ACTION_CURSOR_WINDOW_LINE_TOP
] = {
467 "cursor-window-line-top",
468 "Move cursor to top line of the window",
469 movement
, { .i
= VIS_MOVE_WINDOW_LINE_TOP
}
471 [VIS_ACTION_CURSOR_WINDOW_LINE_MIDDLE
] = {
472 "cursor-window-line-middle",
473 "Move cursor to middle line of the window",
474 movement
, { .i
= VIS_MOVE_WINDOW_LINE_MIDDLE
}
476 [VIS_ACTION_CURSOR_WINDOW_LINE_BOTTOM
] = {
477 "cursor-window-line-bottom",
478 "Move cursor to bottom line of the window",
479 movement
, { .i
= VIS_MOVE_WINDOW_LINE_BOTTOM
}
481 [VIS_ACTION_CURSOR_SEARCH_NEXT
] = {
482 "cursor-search-forward",
483 "Move cursor to bottom line of the window",
484 movement
, { .i
= VIS_MOVE_SEARCH_NEXT
}
486 [VIS_ACTION_CURSOR_SEARCH_PREV
] = {
487 "cursor-search-backward",
488 "Move cursor to bottom line of the window",
489 movement
, { .i
= VIS_MOVE_SEARCH_PREV
}
491 [VIS_ACTION_CURSOR_SEARCH_WORD_FORWARD
] = {
492 "cursor-search-word-forward",
493 "Move cursor to next occurence of the word under cursor",
494 movement
, { .i
= VIS_MOVE_SEARCH_WORD_FORWARD
}
496 [VIS_ACTION_CURSOR_SEARCH_WORD_BACKWARD
] = {
497 "cursor-search-word-backward",
498 "Move cursor to previous occurence of the word under cursor",
499 movement
, { .i
= VIS_MOVE_SEARCH_WORD_BACKWARD
}
501 [VIS_ACTION_WINDOW_PAGE_UP
] = {
503 "Scroll window pages backwards (upwards)",
504 wscroll
, { .i
= -PAGE
}
506 [VIS_ACTION_WINDOW_HALFPAGE_UP
] = {
507 "window-halfpage-up",
508 "Scroll window half pages backwards (upwards)",
509 wscroll
, { .i
= -PAGE_HALF
}
511 [VIS_ACTION_WINDOW_PAGE_DOWN
] = {
513 "Scroll window pages forwards (downwards)",
514 wscroll
, { .i
= +PAGE
}
516 [VIS_ACTION_WINDOW_HALFPAGE_DOWN
] = {
517 "window-halfpage-down",
518 "Scroll window half pages forwards (downwards)",
519 wscroll
, { .i
= +PAGE_HALF
}
521 [VIS_ACTION_MODE_NORMAL
] = {
524 switchmode
, { .i
= VIS_MODE_NORMAL
}
526 [VIS_ACTION_MODE_VISUAL
] = {
527 "vis-mode-visual-charwise",
528 "Enter characterwise visual mode",
529 switchmode
, { .i
= VIS_MODE_VISUAL
}
531 [VIS_ACTION_MODE_VISUAL_LINE
] = {
532 "vis-mode-visual-linewise",
533 "Enter linewise visual mode",
534 switchmode
, { .i
= VIS_MODE_VISUAL_LINE
}
536 [VIS_ACTION_MODE_INSERT
] = {
539 switchmode
, { .i
= VIS_MODE_INSERT
}
541 [VIS_ACTION_MODE_REPLACE
] = {
543 "Enter replace mode",
544 switchmode
, { .i
= VIS_MODE_REPLACE
}
546 [VIS_ACTION_MODE_OPERATOR_PENDING
] = {
547 "vis-mode-operator-pending",
548 "Enter to operator pending mode",
549 switchmode
, { .i
= VIS_MODE_OPERATOR_PENDING
}
551 [VIS_ACTION_DELETE_CHAR_PREV
] = {
553 "Delete the previous character",
554 delete, { .i
= VIS_MOVE_CHAR_PREV
}
556 [VIS_ACTION_DELETE_CHAR_NEXT
] = {
558 "Delete the next character",
559 delete, { .i
= VIS_MOVE_CHAR_NEXT
}
561 [VIS_ACTION_DELETE_LINE_BEGIN
] = {
563 "Delete until the start of the current line",
564 delete, { .i
= VIS_MOVE_LINE_BEGIN
}
566 [VIS_ACTION_DELETE_WORD_PREV
] = {
568 "Delete the previous WORD",
569 delete, { .i
= VIS_MOVE_LONGWORD_START_PREV
}
571 [VIS_ACTION_JUMPLIST_PREV
] = {
573 "Go to older cursor position in jump list",
574 movement
, { .i
= VIS_MOVE_JUMPLIST_PREV
}
576 [VIS_ACTION_JUMPLIST_NEXT
] = {
578 "Go to newer cursor position in jump list",
579 movement
, { .i
= VIS_MOVE_JUMPLIST_NEXT
}
581 [VIS_ACTION_CHANGELIST_PREV
] = {
583 "Go to older cursor position in change list",
584 movement
, { .i
= VIS_MOVE_CHANGELIST_PREV
}
586 [VIS_ACTION_CHANGELIST_NEXT
] = {
588 "Go to newer cursor position in change list",
589 movement
, { .i
= VIS_MOVE_CHANGELIST_NEXT
}
591 [VIS_ACTION_UNDO
] = {
596 [VIS_ACTION_REDO
] = {
601 [VIS_ACTION_EARLIER
] = {
603 "Goto older text state",
606 [VIS_ACTION_LATER
] = {
608 "Goto newer text state",
611 [VIS_ACTION_MACRO_RECORD
] = {
613 "Record macro into given register",
616 [VIS_ACTION_MACRO_REPLAY
] = {
618 "Replay macro, execute the content of the given register",
621 [VIS_ACTION_MARK_SET
] = {
623 "Set given mark at current cursor position",
626 [VIS_ACTION_MARK_GOTO
] = {
628 "Goto the position of the given mark",
629 mark_motion
, { .i
= VIS_MOVE_MARK
}
631 [VIS_ACTION_MARK_GOTO_LINE
] = {
633 "Goto first non-blank character of the line containing the given mark",
634 mark_motion
, { .i
= VIS_MOVE_MARK_LINE
}
636 [VIS_ACTION_REDRAW
] = {
638 "Redraw current editor content",
639 call
, { .f
= vis_redraw
}
641 [VIS_ACTION_REPLACE_CHAR
] = {
643 "Replace the character under the cursor",
646 [VIS_ACTION_TOTILL_REPEAT
] = {
648 "Repeat latest to/till motion",
649 movement
, { .i
= VIS_MOVE_TOTILL_REPEAT
}
651 [VIS_ACTION_TOTILL_REVERSE
] = {
653 "Repeat latest to/till motion but in opposite direction",
654 movement
, { .i
= VIS_MOVE_TOTILL_REVERSE
}
656 [VIS_ACTION_PROMPT_SEARCH_FORWARD
] = {
659 prompt_show
, { .s
= "/" }
661 [VIS_ACTION_PROMPT_SEARCH_BACKWARD
] = {
664 prompt_show
, { .s
= "?" }
666 [VIS_ACTION_TILL_LEFT
] = {
668 "Till after the occurrence of character to the left",
669 movement_key
, { .i
= VIS_MOVE_LEFT_TILL
}
671 [VIS_ACTION_TILL_RIGHT
] = {
673 "Till before the occurrence of character to the right",
674 movement_key
, { .i
= VIS_MOVE_RIGHT_TILL
}
676 [VIS_ACTION_TO_LEFT
] = {
678 "To the first occurrence of character to the left",
679 movement_key
, { .i
= VIS_MOVE_LEFT_TO
}
681 [VIS_ACTION_TO_RIGHT
] = {
683 "To the first occurrence of character to the right",
684 movement_key
, { .i
= VIS_MOVE_RIGHT_TO
}
686 [VIS_ACTION_REGISTER
] = {
688 "Use given register for next operator",
691 [VIS_ACTION_OPERATOR_CHANGE
] = {
692 "vis-operator-change",
694 operator, { .i
= VIS_OP_CHANGE
}
696 [VIS_ACTION_OPERATOR_DELETE
] = {
697 "vis-operator-delete",
699 operator, { .i
= VIS_OP_DELETE
}
701 [VIS_ACTION_OPERATOR_YANK
] = {
704 operator, { .i
= VIS_OP_YANK
}
706 [VIS_ACTION_OPERATOR_SHIFT_LEFT
] = {
707 "vis-operator-shift-left",
708 "Shift left operator",
709 operator, { .i
= VIS_OP_SHIFT_LEFT
}
711 [VIS_ACTION_OPERATOR_SHIFT_RIGHT
] = {
712 "vis-operator-shift-right",
713 "Shift right operator",
714 operator, { .i
= VIS_OP_SHIFT_RIGHT
}
716 [VIS_ACTION_OPERATOR_CASE_LOWER
] = {
717 "vis-operator-case-lower",
718 "Lowercase operator",
719 operator, { .i
= VIS_OP_CASE_LOWER
}
721 [VIS_ACTION_OPERATOR_CASE_UPPER
] = {
722 "vis-operator-case-upper",
723 "Uppercase operator",
724 operator, { .i
= VIS_OP_CASE_UPPER
}
726 [VIS_ACTION_OPERATOR_CASE_SWAP
] = {
727 "vis-operator-case-swap",
728 "Swap case operator",
729 operator, { .i
= VIS_OP_CASE_SWAP
}
731 [VIS_ACTION_OPERATOR_FILTER
] = {
732 "vis-operator-filter",
736 [VIS_ACTION_OPERATOR_FILTER_FMT
] = {
737 "vis-operator-filter-format",
738 "Formating operator, filter range through fmt(1)",
739 operator_filter
, { .s
= "'<,'>!fmt" }
741 [VIS_ACTION_COUNT
] = {
746 [VIS_ACTION_INSERT_NEWLINE
] = {
748 "Insert a line break (depending on file type)",
749 call
, { .f
= vis_insert_nl
}
751 [VIS_ACTION_INSERT_TAB
] = {
753 "Insert a tab (might be converted to spaces)",
754 call
, { .f
= vis_insert_tab
}
756 [VIS_ACTION_INSERT_VERBATIM
] = {
758 "Insert Unicode character based on code point",
761 [VIS_ACTION_INSERT_REGISTER
] = {
763 "Insert specified register content",
766 [VIS_ACTION_WINDOW_NEXT
] = {
769 call
, { .f
= vis_window_next
}
771 [VIS_ACTION_WINDOW_PREV
] = {
773 "Focus previous window",
774 call
, { .f
= vis_window_prev
}
776 [VIS_ACTION_APPEND_CHAR_NEXT
] = {
778 "Append text after the cursor",
779 insertmode
, { .i
= VIS_MOVE_CHAR_NEXT
}
781 [VIS_ACTION_APPEND_LINE_END
] = {
783 "Append text after the end of the line",
784 insertmode
, { .i
= VIS_MOVE_LINE_END
},
786 [VIS_ACTION_INSERT_LINE_START
] = {
788 "Insert text before the first non-blank in the line",
789 insertmode
, { .i
= VIS_MOVE_LINE_START
},
791 [VIS_ACTION_OPEN_LINE_ABOVE
] = {
793 "Begin a new line above the cursor",
794 openline
, { .i
= -1 }
796 [VIS_ACTION_OPEN_LINE_BELOW
] = {
798 "Begin a new line below the cursor",
799 openline
, { .i
= +1 }
801 [VIS_ACTION_JOIN_LINE_BELOW
] = {
804 join
, { .i
= VIS_MOVE_LINE_NEXT
},
806 [VIS_ACTION_JOIN_LINES
] = {
808 "Join selected lines",
809 operator, { .i
= VIS_OP_JOIN
}
811 [VIS_ACTION_PROMPT_SHOW
] = {
813 "Show editor command line prompt",
814 prompt_show
, { .s
= ":" }
816 [VIS_ACTION_PROMPT_SHOW_VISUAL
] = {
817 "prompt-show-visual",
818 "Show editor command line prompt in visual mode",
819 prompt_show
, { .s
= ":'<,'>" }
821 [VIS_ACTION_REPEAT
] = {
823 "Repeat latest editor command",
826 [VIS_ACTION_SELECTION_FLIP
] = {
828 "Flip selection, move cursor to other end",
831 [VIS_ACTION_SELECTION_RESTORE
] = {
833 "Restore last selection",
836 [VIS_ACTION_WINDOW_REDRAW_TOP
] = {
838 "Redraw cursor line at the top of the window",
839 window
, { .w
= view_redraw_top
}
841 [VIS_ACTION_WINDOW_REDRAW_CENTER
] = {
842 "window-redraw-center",
843 "Redraw cursor line at the center of the window",
844 window
, { .w
= view_redraw_center
}
846 [VIS_ACTION_WINDOW_REDRAW_BOTTOM
] = {
847 "window-redraw-bottom",
848 "Redraw cursor line at the bottom of the window",
849 window
, { .w
= view_redraw_bottom
}
851 [VIS_ACTION_WINDOW_SLIDE_UP
] = {
853 "Slide window content upwards",
856 [VIS_ACTION_WINDOW_SLIDE_DOWN
] = {
858 "Slide window content downwards",
861 [VIS_ACTION_PUT_AFTER
] = {
863 "Put text after the cursor",
864 operator, { .i
= VIS_OP_PUT_AFTER
}
866 [VIS_ACTION_PUT_BEFORE
] = {
868 "Put text before the cursor",
869 operator, { .i
= VIS_OP_PUT_BEFORE
}
871 [VIS_ACTION_PUT_AFTER_END
] = {
873 "Put text after the cursor, place cursor after new text",
874 operator, { .i
= VIS_OP_PUT_AFTER_END
}
876 [VIS_ACTION_PUT_BEFORE_END
] = {
878 "Put text before the cursor, place cursor after new text",
879 operator, { .i
= VIS_OP_PUT_BEFORE_END
}
881 [VIS_ACTION_CURSOR_SELECT_WORD
] = {
882 "cursors-select-word",
883 "Select word under cursor",
886 [VIS_ACTION_CURSORS_NEW_LINE_ABOVE
] = {
887 "cursors-new-lines-above",
888 "Create a new cursor on the line above",
889 cursors_new
, { .i
= -1 }
891 [VIS_ACTION_CURSORS_NEW_LINE_BELOW
] = {
892 "cursor-new-lines-below",
893 "Create a new cursor on the line below",
894 cursors_new
, { .i
= +1 }
896 [VIS_ACTION_CURSORS_NEW_LINES_BEGIN
] = {
897 "cursors-new-lines-begin",
898 "Create a new cursor at the start of every line covered by selection",
899 operator, { .i
= VIS_OP_CURSOR_SOL
}
901 [VIS_ACTION_CURSORS_NEW_LINES_END
] = {
902 "cursors-new-lines-end",
903 "Create a new cursor at the end of every line covered by selection",
904 operator, { .i
= VIS_OP_CURSOR_EOL
}
906 [VIS_ACTION_CURSORS_NEW_MATCH_NEXT
] = {
907 "cursors-new-match-next",
908 "Select the next region matching the current selection",
911 [VIS_ACTION_CURSORS_NEW_MATCH_SKIP
] = {
912 "cursors-new-match-skip",
913 "Clear current selection, but select next match",
916 [VIS_ACTION_CURSORS_ALIGN
] = {
918 "Try to align all cursors on the same column",
921 [VIS_ACTION_CURSORS_ALIGN_INDENT
] = {
922 "cursors-align-indent",
923 "Try to align all cursors by inserting spaces",
924 cursors_align_indent
,
926 [VIS_ACTION_CURSORS_REMOVE_ALL
] = {
927 "cursors-remove-all",
928 "Remove all but the primary cursor",
931 [VIS_ACTION_CURSORS_REMOVE_LAST
] = {
932 "cursors-remove-last",
933 "Remove least recently created cursor",
936 [VIS_ACTION_CURSORS_PREV
] = {
938 "Move to the previous cursor",
939 cursors_navigate
, { .i
= -PAGE_HALF
}
941 [VIS_ACTION_CURSORS_NEXT
] = {
943 "Move to the next cursor",
944 cursors_navigate
, { .i
= +PAGE_HALF
}
946 [VIS_ACTION_TEXT_OBJECT_WORD_OUTER
] = {
947 "text-object-word-outer",
948 "A word leading and trailing whitespace included",
949 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_WORD
}
951 [VIS_ACTION_TEXT_OBJECT_WORD_INNER
] = {
952 "text-object-word-inner",
953 "A word leading and trailing whitespace excluded",
954 textobj
, { .i
= VIS_TEXTOBJECT_INNER_WORD
}
956 [VIS_ACTION_TEXT_OBJECT_LONGWORD_OUTER
] = {
957 "text-object-longword-outer",
958 "A WORD leading and trailing whitespace included",
959 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_LONGWORD
}
961 [VIS_ACTION_TEXT_OBJECT_LONGWORD_INNER
] = {
962 "text-object-longword-inner",
963 "A WORD leading and trailing whitespace excluded",
964 textobj
, { .i
= VIS_TEXTOBJECT_INNER_LONGWORD
}
966 [VIS_ACTION_TEXT_OBJECT_SENTENCE
] = {
967 "text-object-sentence",
969 textobj
, { .i
= VIS_TEXTOBJECT_SENTENCE
}
971 [VIS_ACTION_TEXT_OBJECT_PARAGRAPH
] = {
972 "text-object-paragraph",
974 textobj
, { .i
= VIS_TEXTOBJECT_PARAGRAPH
}
976 [VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_OUTER
] = {
977 "text-object-square-bracket-outer",
978 "[] block (outer variant)",
979 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_SQUARE_BRACKET
}
981 [VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_INNER
] = {
982 "text-object-square-bracket-inner",
983 "[] block (inner variant)",
984 textobj
, { .i
= VIS_TEXTOBJECT_INNER_SQUARE_BRACKET
}
986 [VIS_ACTION_TEXT_OBJECT_PARANTHESE_OUTER
] = {
987 "text-object-parentheses-outer",
988 "() block (outer variant)",
989 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_PARANTHESE
}
991 [VIS_ACTION_TEXT_OBJECT_PARANTHESE_INNER
] = {
992 "text-object-parentheses-inner",
993 "() block (inner variant)",
994 textobj
, { .i
= VIS_TEXTOBJECT_INNER_PARANTHESE
}
996 [VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_OUTER
] = {
997 "text-object-angle-bracket-outer",
998 "<> block (outer variant)",
999 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_ANGLE_BRACKET
}
1001 [VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_INNER
] = {
1002 "text-object-angle-bracket-inner",
1003 "<> block (inner variant)",
1004 textobj
, { .i
= VIS_TEXTOBJECT_INNER_ANGLE_BRACKET
}
1006 [VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_OUTER
] = {
1007 "text-object-curly-bracket-outer",
1008 "{} block (outer variant)",
1009 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_CURLY_BRACKET
}
1011 [VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_INNER
] = {
1012 "text-object-curly-bracket-inner",
1013 "{} block (inner variant)",
1014 textobj
, { .i
= VIS_TEXTOBJECT_INNER_CURLY_BRACKET
}
1016 [VIS_ACTION_TEXT_OBJECT_QUOTE_OUTER
] = {
1017 "text-object-quote-outer",
1018 "A quoted string, including the quotation marks",
1019 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_QUOTE
}
1021 [VIS_ACTION_TEXT_OBJECT_QUOTE_INNER
] = {
1022 "text-object-quote-inner",
1023 "A quoted string, excluding the quotation marks",
1024 textobj
, { .i
= VIS_TEXTOBJECT_INNER_QUOTE
}
1026 [VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_OUTER
] = {
1027 "text-object-single-quote-outer",
1028 "A single quoted string, including the quotation marks",
1029 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_SINGLE_QUOTE
}
1031 [VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_INNER
] = {
1032 "text-object-single-quote-inner",
1033 "A single quoted string, excluding the quotation marks",
1034 textobj
, { .i
= VIS_TEXTOBJECT_INNER_SINGLE_QUOTE
}
1036 [VIS_ACTION_TEXT_OBJECT_BACKTICK_OUTER
] = {
1037 "text-object-backtick-outer",
1038 "A backtick delimited string (outer variant)",
1039 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_BACKTICK
}
1041 [VIS_ACTION_TEXT_OBJECT_BACKTICK_INNER
] = {
1042 "text-object-backtick-inner",
1043 "A backtick delimited string (inner variant)",
1044 textobj
, { .i
= VIS_TEXTOBJECT_INNER_BACKTICK
}
1046 [VIS_ACTION_TEXT_OBJECT_ENTIRE_OUTER
] = {
1047 "text-object-entire-outer",
1048 "The whole text content",
1049 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_ENTIRE
}
1051 [VIS_ACTION_TEXT_OBJECT_ENTIRE_INNER
] = {
1052 "text-object-entire-inner",
1053 "The whole text content, except for leading and trailing empty lines",
1054 textobj
, { .i
= VIS_TEXTOBJECT_INNER_ENTIRE
}
1056 [VIS_ACTION_TEXT_OBJECT_FUNCTION_OUTER
] = {
1057 "text-object-function-outer",
1058 "A whole C-like function",
1059 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_FUNCTION
}
1061 [VIS_ACTION_TEXT_OBJECT_FUNCTION_INNER
] = {
1062 "text-object-function-inner",
1063 "A whole C-like function body",
1064 textobj
, { .i
= VIS_TEXTOBJECT_INNER_FUNCTION
}
1066 [VIS_ACTION_TEXT_OBJECT_LINE_OUTER
] = {
1067 "text-object-line-outer",
1069 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_LINE
}
1071 [VIS_ACTION_TEXT_OBJECT_LINE_INNER
] = {
1072 "text-object-line-inner",
1073 "The whole line, excluding leading and trailing whitespace",
1074 textobj
, { .i
= VIS_TEXTOBJECT_INNER_LINE
}
1076 [VIS_ACTION_TEXT_OBJECT_INDENTATION
] = {
1077 "text-object-indentation",
1078 "All adjacent lines with the same indentation level as the current one",
1079 textobj
, { .i
= VIS_TEXTOBJECT_INDENTATION
}
1081 [VIS_ACTION_TEXT_OBJECT_SEARCH_FORWARD
] = {
1082 "text-object-search-forward",
1083 "The next search match in forward direction",
1084 textobj
, { .i
= VIS_TEXTOBJECT_SEARCH_FORWARD
}
1086 [VIS_ACTION_TEXT_OBJECT_SEARCH_BACKWARD
] = {
1087 "text-object-search-backward",
1088 "The next search match in backward direction",
1089 textobj
, { .i
= VIS_TEXTOBJECT_SEARCH_BACKWARD
}
1091 [VIS_ACTION_MOTION_CHARWISE
] = {
1093 "Force motion to be charwise",
1094 motiontype
, { .i
= VIS_MOTIONTYPE_CHARWISE
}
1096 [VIS_ACTION_MOTION_LINEWISE
] = {
1098 "Force motion to be linewise",
1099 motiontype
, { .i
= VIS_MOTIONTYPE_LINEWISE
}
1101 [VIS_ACTION_UNICODE_INFO
] = {
1103 "Show Unicode codepoint(s) of character under cursor",
1106 [VIS_ACTION_NUMBER_INCREMENT
] = {
1108 "Increment number under cursor",
1109 number_increment_decrement
, { .i
= +1 }
1111 [VIS_ACTION_NUMBER_DECREMENT
] = {
1113 "Decrement number under cursor",
1114 number_increment_decrement
, { .i
= -1 }
1116 [VIS_ACTION_OPEN_FILE_UNDER_CURSOR
] = {
1117 "open-file-under-cursor",
1118 "Open file under the cursor",
1119 open_file_under_cursor
, { .b
= false }
1121 [VIS_ACTION_OPEN_FILE_UNDER_CURSOR_NEW_WINDOW
] = {
1122 "open-file-under-cursor-new-cursor",
1123 "Open file under the cursor in a new window",
1124 open_file_under_cursor
, { .b
= true }
1126 [VIS_ACTION_NOP
] = {
1128 "Ignore key, do nothing",
1135 /** key bindings functions */
1137 static const char *nop(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1141 static const char *key2register(Vis
*vis
, const char *keys
, enum VisRegister
*reg
) {
1142 *reg
= VIS_REG_INVALID
;
1145 if ('a' <= keys
[0] && keys
[0] <= 'z')
1146 *reg
= keys
[0] - 'a';
1147 else if ('A' <= keys
[0] && keys
[0] <= 'Z')
1148 *reg
= VIS_REG_A
+ keys
[0] - 'A';
1149 else if (keys
[0] == '*' || keys
[0] == '+')
1150 *reg
= VIS_REG_CLIPBOARD
;
1151 else if (keys
[0] == '_')
1152 *reg
= VIS_REG_BLACKHOLE
;
1153 else if (keys
[0] == '0')
1154 *reg
= VIS_REG_ZERO
;
1155 else if (keys
[0] == '@')
1156 *reg
= VIS_MACRO_LAST_RECORDED
;
1157 else if (keys
[0] == '/')
1158 *reg
= VIS_REG_SEARCH
;
1159 else if (keys
[0] == ':')
1160 *reg
= VIS_REG_COMMAND
;
1164 static const char *macro_record(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1165 if (!vis_macro_record_stop(vis
)) {
1166 enum VisRegister reg
;
1167 keys
= key2register(vis
, keys
, ®
);
1168 vis_macro_record(vis
, reg
);
1174 static const char *macro_replay(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1175 enum VisRegister reg
;
1176 keys
= key2register(vis
, keys
, ®
);
1177 vis_macro_replay(vis
, reg
);
1181 static const char *suspend(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1186 static const char *repeat(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1191 static const char *cursors_new(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1192 View
*view
= vis_view(vis
);
1193 size_t pos
= view_cursor_get(view
);
1194 Cursor
*cursor
= view_cursors_new(view
);
1196 view_cursors_to(cursor
, pos
);
1198 view_line_down(cursor
);
1199 else if (arg
->i
< 0)
1200 view_line_up(cursor
);
1205 static const char *cursors_align(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1206 View
*view
= vis_view(vis
);
1207 Text
*txt
= vis_text(vis
);
1208 int mincol
= INT_MAX
;
1209 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
)) {
1210 int col
= view_cursors_cell_get(c
);
1211 if (col
>= 0 && col
< mincol
)
1214 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
)) {
1215 if (view_cursors_cell_set(c
, mincol
) == -1) {
1216 size_t pos
= view_cursors_pos(c
);
1217 size_t col
= text_line_width_set(txt
, pos
, mincol
);
1218 view_cursors_to(c
, col
);
1224 static const char *cursors_align_indent(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1225 View
*view
= vis_view(vis
);
1226 Text
*txt
= vis_text(vis
);
1227 int mincol
= INT_MAX
, maxcol
= 0;
1229 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
)) {
1230 int col
= text_line_width_get(txt
, view_cursors_pos(c
));
1237 size_t len
= maxcol
- mincol
;
1238 char *buf
= malloc(len
+1);
1241 memset(buf
, ' ', len
);
1243 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
)) {
1244 size_t pos
= view_cursors_pos(c
);
1245 int col
= text_line_width_get(txt
, pos
);
1247 size_t off
= maxcol
- col
;
1249 text_insert(txt
, pos
, buf
, off
);
1258 static const char *cursors_clear(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1259 View
*view
= vis_view(vis
);
1260 if (view_cursors_multiple(view
))
1261 view_cursors_clear(view
);
1263 view_cursors_selection_clear(view_cursors_primary_get(view
));
1267 static const char *cursors_select(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1268 Text
*txt
= vis_text(vis
);
1269 View
*view
= vis_view(vis
);
1270 for (Cursor
*cursor
= view_cursors(view
); cursor
; cursor
= view_cursors_next(cursor
)) {
1271 Filerange sel
= view_cursors_selection_get(cursor
);
1272 Filerange word
= text_object_word(txt
, view_cursors_pos(cursor
));
1273 if (!text_range_valid(&sel
) && text_range_valid(&word
)) {
1274 view_cursors_selection_set(cursor
, &word
);
1275 view_cursors_to(cursor
, text_char_prev(txt
, word
.end
));
1278 vis_mode_switch(vis
, VIS_MODE_VISUAL
);
1282 static const char *cursors_select_next(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1283 Text
*txt
= vis_text(vis
);
1284 View
*view
= vis_view(vis
);
1285 Cursor
*cursor
= view_cursors_primary_get(view
);
1286 Filerange sel
= view_cursors_selection_get(cursor
);
1287 if (!text_range_valid(&sel
))
1290 char *buf
= text_bytes_alloc0(txt
, sel
.start
, text_range_size(&sel
));
1293 Filerange word
= text_object_word_find_next(txt
, sel
.end
, buf
);
1296 if (text_range_valid(&word
)) {
1297 cursor
= view_cursors_new(view
);
1300 view_cursors_selection_set(cursor
, &word
);
1301 view_cursors_to(cursor
, text_char_prev(txt
, word
.end
));
1306 static const char *cursors_select_skip(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1307 View
*view
= vis_view(vis
);
1308 Cursor
*cursor
= view_cursors_primary_get(view
);
1309 keys
= cursors_select_next(vis
, keys
, arg
);
1310 if (cursor
!= view_cursors_primary_get(view
))
1311 view_cursors_dispose(cursor
);
1315 static const char *cursors_remove(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1316 View
*view
= vis_view(vis
);
1317 view_cursors_dispose(view_cursors_primary_get(view
));
1318 view_cursor_to(view
, view_cursor_get(view
));
1322 static const char *cursors_navigate(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1323 View
*view
= vis_view(vis
);
1324 if (!view_cursors_multiple(view
))
1325 return wscroll(vis
, keys
, arg
);
1326 Cursor
*c
= view_cursors_primary_get(view
);
1327 for (int count
= vis_count_get_default(vis
, 1); count
> 0; count
--) {
1329 c
= view_cursors_next(c
);
1331 c
= view_cursors(view
);
1333 c
= view_cursors_prev(c
);
1335 c
= view_cursors(view
);
1336 for (Cursor
*n
= c
; n
; n
= view_cursors_next(n
))
1341 view_cursors_primary_set(c
);
1342 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
1346 static const char *replace(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1349 const char *next
= vis_keys_next(vis
, keys
);
1352 size_t len
= next
- keys
;
1354 memcpy(key
, keys
, len
);
1356 vis_operator(vis
, VIS_OP_REPLACE
);
1357 vis_motion(vis
, VIS_MOVE_NOP
);
1358 vis_keys_inject(vis
, next
, key
);
1359 vis_keys_inject(vis
, next
+len
, "<Escape>");
1363 static const char *count(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1364 int digit
= keys
[-1] - '0';
1365 int count
= vis_count_get_default(vis
, 0);
1366 if (0 <= digit
&& digit
<= 9) {
1367 if (digit
== 0 && count
== 0)
1368 vis_motion(vis
, VIS_MOVE_LINE_BEGIN
);
1369 vis_count_set(vis
, count
* 10 + digit
);
1374 static const char *gotoline(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1375 if (vis_count_get(vis
) != VIS_COUNT_UNKNOWN
)
1376 vis_motion(vis
, VIS_MOVE_LINE
);
1377 else if (arg
->i
< 0)
1378 vis_motion(vis
, VIS_MOVE_FILE_BEGIN
);
1380 vis_motion(vis
, VIS_MOVE_FILE_END
);
1384 static const char *motiontype(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1385 vis_motion_type(vis
, arg
->i
);
1389 static const char *operator(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1390 vis_operator(vis
, arg
->i
);
1394 static const char *operator_filter(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1395 vis_operator(vis
, VIS_OP_FILTER
, arg
->s
);
1399 static const char *movement_key(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1402 if (!keys
[0] || !(next
= vis_keys_next(vis
, keys
)))
1404 size_t len
= next
- keys
;
1405 if (len
< sizeof key
) {
1406 strncpy(key
, keys
, len
);
1408 vis_motion(vis
, arg
->i
, key
);
1413 static const char *movement(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1414 vis_motion(vis
, arg
->i
);
1418 static const char *textobj(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1419 vis_textobject(vis
, arg
->i
);
1423 static const char *selection_end(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1424 for (Cursor
*c
= view_cursors(vis_view(vis
)); c
; c
= view_cursors_next(c
))
1425 view_cursors_selection_swap(c
);
1429 static const char *selection_restore(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1430 Text
*txt
= vis_text(vis
);
1431 View
*view
= vis_view(vis
);
1432 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
))
1433 view_cursors_selection_restore(c
);
1434 Filerange sel
= view_selection_get(view
);
1435 if (text_range_is_linewise(txt
, &sel
))
1436 vis_mode_switch(vis
, VIS_MODE_VISUAL_LINE
);
1438 vis_mode_switch(vis
, VIS_MODE_VISUAL
);
1442 static const char *reg(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1443 enum VisRegister reg
;
1444 keys
= key2register(vis
, keys
, ®
);
1445 vis_register_set(vis
, reg
);
1449 static const char *key2mark(Vis
*vis
, const char *keys
, int *mark
) {
1450 *mark
= VIS_MARK_INVALID
;
1453 if (keys
[0] >= 'a' && keys
[0] <= 'z')
1454 *mark
= keys
[0] - 'a';
1455 else if (keys
[0] == '<')
1456 *mark
= VIS_MARK_SELECTION_START
;
1457 else if (keys
[0] == '>')
1458 *mark
= VIS_MARK_SELECTION_END
;
1462 static const char *mark_set(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1464 keys
= key2mark(vis
, keys
, &mark
);
1465 vis_mark_set(vis
, mark
, view_cursor_get(vis_view(vis
)));
1469 static const char *mark_motion(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1471 keys
= key2mark(vis
, keys
, &mark
);
1472 vis_motion(vis
, arg
->i
, mark
);
1476 static const char *undo(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1477 size_t pos
= text_undo(vis_text(vis
));
1479 View
*view
= vis_view(vis
);
1480 if (!view_cursors_multiple(view
))
1481 view_cursor_to(view
, pos
);
1482 /* redraw all windows in case some display the same file */
1488 static const char *redo(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1489 size_t pos
= text_redo(vis_text(vis
));
1491 View
*view
= vis_view(vis
);
1492 if (!view_cursors_multiple(view
))
1493 view_cursor_to(view
, pos
);
1494 /* redraw all windows in case some display the same file */
1500 static const char *earlier(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1501 size_t pos
= text_earlier(vis_text(vis
), vis_count_get_default(vis
, 1));
1503 view_cursor_to(vis_view(vis
), pos
);
1504 /* redraw all windows in case some display the same file */
1510 static const char *later(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1511 size_t pos
= text_later(vis_text(vis
), vis_count_get_default(vis
, 1));
1513 view_cursor_to(vis_view(vis
), pos
);
1514 /* redraw all windows in case some display the same file */
1520 static const char *delete(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1521 vis_operator(vis
, VIS_OP_DELETE
);
1522 vis_motion(vis
, arg
->i
);
1526 static const char *insert_register(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1527 enum VisRegister regid
;
1528 keys
= key2register(vis
, keys
, ®id
);
1530 const char *data
= vis_register_get(vis
, regid
, &len
);
1531 vis_insert_key(vis
, data
, len
);
1535 static const char *prompt_show(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1536 vis_prompt_show(vis
, arg
->s
);
1540 static const char *insert_verbatim(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1542 char buf
[4], type
= keys
[0];
1543 const char *data
= NULL
;
1544 int len
= 0, count
= 0, base
= 0;
1566 if ('0' <= type
&& type
<= '9') {
1575 for (keys
++; keys
[0] && count
> 0; keys
++, count
--) {
1577 if (base
== 8 && '0' <= keys
[0] && keys
[0] <= '7') {
1579 } else if ((base
== 10 || base
== 16) && '0' <= keys
[0] && keys
[0] <= '9') {
1581 } else if (base
== 16 && 'a' <= keys
[0] && keys
[0] <= 'f') {
1582 v
= 10 + keys
[0] - 'a';
1583 } else if (base
== 16 && 'A' <= keys
[0] && keys
[0] <= 'F') {
1584 v
= 10 + keys
[0] - 'A';
1589 rune
= rune
* base
+ v
;
1594 if (type
== 'u' || type
== 'U') {
1595 len
= runetochar(buf
, &rune
);
1603 const char *next
= vis_keys_next(vis
, keys
);
1606 size_t keylen
= next
- keys
;
1608 memcpy(key
, keys
, keylen
);
1611 static const char *keysym
[] = {
1614 "<Backspace>", "\b",
1620 for (const char **k
= keysym
; k
[0]; k
+= 2) {
1621 if (strcmp(k
[0], key
) == 0) {
1631 vis_insert_key(vis
, data
, len
);
1635 static int argi2lines(Vis
*vis
, const Arg
*arg
) {
1636 int count
= vis_count_get(vis
);
1640 return view_height_get(vis_view(vis
));
1643 return view_height_get(vis_view(vis
))/2;
1645 if (count
!= VIS_COUNT_UNKNOWN
)
1647 return arg
->i
< 0 ? -arg
->i
: arg
->i
;
1651 static const char *wscroll(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1653 view_scroll_down(vis_view(vis
), argi2lines(vis
, arg
));
1655 view_scroll_up(vis_view(vis
), argi2lines(vis
, arg
));
1659 static const char *wslide(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1661 view_slide_down(vis_view(vis
), argi2lines(vis
, arg
));
1663 view_slide_up(vis_view(vis
), argi2lines(vis
, arg
));
1667 static const char *call(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1672 static const char *window(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1673 arg
->w(vis_view(vis
));
1677 static const char *openline(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1678 vis_operator(vis
, VIS_OP_INSERT
);
1680 vis_motion(vis
, VIS_MOVE_LINE_END
);
1681 vis_keys_inject(vis
, keys
, "<insert-newline>");
1683 vis_motion(vis
, VIS_MOVE_LINE_BEGIN
);
1684 vis_keys_inject(vis
, keys
, "<insert-newline><Up>");
1689 static const char *join(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1690 int count
= vis_count_get_default(vis
, 0);
1692 vis_count_set(vis
, count
-1);
1693 vis_operator(vis
, VIS_OP_JOIN
);
1694 vis_motion(vis
, arg
->i
);
1698 static const char *switchmode(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1699 vis_mode_switch(vis
, arg
->i
);
1703 static const char *insertmode(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1704 vis_operator(vis
, VIS_OP_INSERT
);
1705 vis_motion(vis
, arg
->i
);
1709 static const char *unicode_info(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1710 View
*view
= vis_view(vis
);
1711 Text
*txt
= vis_text(vis
);
1712 size_t start
= view_cursor_get(view
);
1713 size_t end
= text_char_next(txt
, start
);
1714 char data
[end
-start
], *data_cur
= data
;
1715 text_bytes_get(txt
, start
, end
- start
, data
);
1716 Iterator it
= text_iterator_get(txt
, start
);
1717 char info
[255] = "", *info_cur
= info
;
1718 for (size_t pos
= start
; it
.pos
< end
; pos
= it
.pos
) {
1719 text_iterator_codepoint_next(&it
, NULL
);
1720 size_t len
= it
.pos
- pos
;
1721 wchar_t wc
= 0xFFFD;
1722 mbtowc(&wc
, data_cur
, len
);
1723 int width
= wcwidth(wc
);
1724 info_cur
+= snprintf(info_cur
, sizeof(info
) - (info_cur
- info
) - 1,
1725 "<%s%.*s> U+%04x ", width
== 0 ? " " : "", (int)len
, data_cur
, wc
);
1728 vis_info_show(vis
, "%s", info
);
1732 static const char *percent(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1733 if (vis_count_get(vis
) == VIS_COUNT_UNKNOWN
)
1734 vis_motion(vis
, VIS_MOVE_BRACKET_MATCH
);
1736 vis_motion(vis
, VIS_MOVE_PERCENT
);
1740 static const char *number_increment_decrement(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1741 View
*view
= vis_view(vis
);
1742 Text
*txt
= vis_text(vis
);
1745 int count
= vis_count_get(vis
);
1746 if (count
!= 0 && count
!= VIS_COUNT_UNKNOWN
)
1749 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
)) {
1750 Filerange r
= text_object_number(txt
, view_cursors_pos(c
));
1751 if (!text_range_valid(&r
))
1753 char *buf
= text_bytes_alloc0(txt
, r
.start
, text_range_size(&r
));
1755 char *number
= buf
, fmt
[255];
1756 if (number
[0] == '-')
1758 bool octal
= number
[0] == '0' && ('0' <= number
[1] && number
[1] <= '7');
1759 bool hex
= number
[0] == '0' && (number
[1] == 'x' || number
[1] == 'X');
1760 bool dec
= !hex
&& !octal
;
1762 long long value
= strtoll(buf
, NULL
, 0);
1765 snprintf(fmt
, sizeof fmt
, "%lld", value
);
1767 size_t len
= strlen(number
) - 2;
1768 snprintf(fmt
, sizeof fmt
, "0x%0*llx", (int)len
, value
);
1770 size_t len
= strlen(number
) - 1;
1771 snprintf(fmt
, sizeof fmt
, "0%0*llo", (int)len
, value
);
1773 text_delete_range(txt
, &r
);
1774 text_insert(txt
, r
.start
, fmt
, strlen(fmt
));
1775 view_cursors_to(c
, r
.start
);
1785 static const char *open_file_under_cursor(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1786 Win
*win
= vis_window(vis
);
1787 View
*view
= vis_view(vis
);
1788 Text
*txt
= vis_text(vis
);
1790 if (!arg
->b
&& !vis_window_closable(win
)) {
1791 vis_info_show(vis
, "No write since last change");
1795 for (Cursor
*c
= view_cursors(view
); c
; c
= view_cursors_next(c
)) {
1796 Filerange r
= text_object_filename(txt
, view_cursors_pos(c
));
1797 if (!text_range_valid(&r
))
1799 char *name
= text_bytes_alloc0(txt
, r
.start
, text_range_size(&r
));
1804 if (stat(name
, &st
) == -1) {
1805 vis_info_show(vis
, "File `%s' not found", name
);
1810 if (!vis_window_new(vis
, name
)) {
1811 vis_info_show(vis
, "Failed to open `%s': %s", name
, strerror(errno
));
1814 } else if (!arg
->b
) {
1815 vis_window_close(win
);
1828 static void signal_handler(int signum
, siginfo_t
*siginfo
, void *context
) {
1829 vis_signal_handler(vis
, signum
, siginfo
, context
);
1832 int main(int argc
, char *argv
[]) {
1835 .vis_start
= vis_lua_start
,
1836 .vis_quit
= vis_lua_quit
,
1837 .file_open
= vis_lua_file_open
,
1838 .file_save
= vis_lua_file_save
,
1839 .file_close
= vis_lua_file_close
,
1840 .win_open
= vis_lua_win_open
,
1841 .win_close
= vis_lua_win_close
,
1844 vis
= vis_new(ui_curses_new(), &event
);
1846 return EXIT_FAILURE
;
1848 for (int i
= 0; i
< LENGTH(vis_action
); i
++) {
1849 const KeyAction
*action
= &vis_action
[i
];
1850 if (!vis_action_register(vis
, action
))
1851 vis_die(vis
, "Could not register action: %s\n", action
->name
);
1854 for (int i
= 0; i
< LENGTH(default_bindings
); i
++) {
1855 for (const KeyBinding
**binding
= default_bindings
[i
]; binding
&& *binding
; binding
++) {
1856 for (const KeyBinding
*kb
= *binding
; kb
->key
; kb
++) {
1857 vis_mode_map(vis
, i
, kb
->key
, kb
);
1862 for (const char **k
= keymaps
; k
[0]; k
+= 2)
1863 vis_keymap_add(vis
, k
[0], k
[1]);
1865 /* install signal handlers etc. */
1866 struct sigaction sa
;
1867 memset(&sa
, 0, sizeof sa
);
1868 sa
.sa_flags
= SA_SIGINFO
;
1869 sa
.sa_sigaction
= signal_handler
;
1870 if (sigaction(SIGBUS
, &sa
, NULL
) || sigaction(SIGINT
, &sa
, NULL
))
1871 vis_die(vis
, "sigaction: %s", strerror(errno
));
1874 sigemptyset(&blockset
);
1875 sigaddset(&blockset
, SIGWINCH
);
1876 sigprocmask(SIG_BLOCK
, &blockset
, NULL
);
1877 signal(SIGPIPE
, SIG_IGN
);
1879 int status
= vis_run(vis
, argc
, argv
);