11 #include <sys/types.h>
13 #include "ui-terminal.h"
16 #include "text-util.h"
17 #include "text-motions.h"
18 #include "text-objects.h"
25 #define PAGE_HALF (INT_MAX-1)
27 /** functions to be called from keybindings */
28 /* ignore key, do nothing */
29 static const char *nop(Vis
*, const char *keys
, const Arg
*arg
);
30 /* record/replay macro indicated by keys */
31 static const char *macro_record(Vis
*, const char *keys
, const Arg
*arg
);
32 static const char *macro_replay(Vis
*, const char *keys
, const Arg
*arg
);
33 /* temporarily suspend the editor and return to the shell, type 'fg' to get back */
34 static const char *suspend(Vis
*, const char *keys
, const Arg
*arg
);
35 /* switch to mode indicated by arg->i */
36 static const char *switchmode(Vis
*, const char *keys
, const Arg
*arg
);
37 /* switch to insert mode after performing movement indicated by arg->i */
38 static const char *insertmode(Vis
*, const char *keys
, const Arg
*arg
);
39 /* switch to replace mode after performing movement indicated by arg->i */
40 static const char *replacemode(Vis
*, const char *keys
, const Arg
*arg
);
41 /* add a new line either before or after the one where the cursor currently is */
42 static const char *openline(Vis
*, const char *keys
, const Arg
*arg
);
43 /* join lines from current cursor position to movement indicated by arg */
44 static const char *join(Vis
*, const char *keys
, const Arg
*arg
);
45 /* perform last action i.e. action_prev again */
46 static const char *repeat(Vis
*, const char *keys
, const Arg
*arg
);
47 /* replace character at cursor with one from keys */
48 static const char *replace(Vis
*, const char *keys
, const Arg
*arg
);
49 /* create a new cursor on the previous (arg->i < 0) or next (arg->i > 0) line */
50 static const char *selections_new(Vis
*, const char *keys
, const Arg
*arg
);
51 /* try to align all selections on the same column */
52 static const char *selections_align(Vis
*, const char *keys
, const Arg
*arg
);
53 /* try to align all selections by inserting the correct amount of white spaces */
54 static const char *selections_align_indent(Vis
*, const char *keys
, const Arg
*arg
);
55 /* remove all but the primary cursor and their selections */
56 static const char *selections_clear(Vis
*, const char *keys
, const Arg
*arg
);
57 /* remove the least recently added selection */
58 static const char *selections_remove(Vis
*, const char *keys
, const Arg
*arg
);
59 /* remove count (or arg->i)-th selection column */
60 static const char *selections_remove_column(Vis
*, const char *keys
, const Arg
*arg
);
61 /* remove all but the count (or arg->i)-th selection column */
62 static const char *selections_remove_column_except(Vis
*, const char *keys
, const Arg
*arg
);
63 /* move to the previous (arg->i < 0) or next (arg->i > 0) selection */
64 static const char *selections_navigate(Vis
*, const char *keys
, const Arg
*arg
);
65 /* select the word the selection is currently over */
66 static const char *selections_match_word(Vis
*, const char *keys
, const Arg
*arg
);
67 /* select the next region matching the current selection */
68 static const char *selections_match_next(Vis
*, const char *keys
, const Arg
*arg
);
69 /* clear current selection but select next match */
70 static const char *selections_match_skip(Vis
*, const char *keys
, const Arg
*arg
);
71 /* rotate selection content count times left (arg->i < 0) or right (arg->i > 0) */
72 static const char *selections_rotate(Vis
*, const char *keys
, const Arg
*arg
);
73 /* remove leading and trailing white spaces from selections */
74 static const char *selections_trim(Vis
*, const char *keys
, const Arg
*arg
);
75 /* save active selections to register */
76 static const char *selections_save(Vis
*, const char *keys
, const Arg
*arg
);
77 /* restore selections from register */
78 static const char *selections_restore(Vis
*, const char *keys
, const Arg
*arg
);
79 /* union selections */
80 static const char *selections_union(Vis
*, const char *keys
, const Arg
*arg
);
81 /* intersect selections */
82 static const char *selections_intersect(Vis
*, const char *keys
, const Arg
*arg
);
83 /* perform complement of current active selections */
84 static const char *selections_complement(Vis
*, const char *keys
, const Arg
*arg
);
85 /* subtract selections from register */
86 static const char *selections_minus(Vis
*, const char *keys
, const Arg
*arg
);
87 /* pairwise combine selections */
88 static const char *selections_combine(Vis
*, const char *keys
, const Arg
*arg
);
89 static Filerange
combine_union(const Filerange
*, const Filerange
*);
90 static Filerange
combine_intersect(const Filerange
*, const Filerange
*);
91 static Filerange
combine_longer(const Filerange
*, const Filerange
*);
92 static Filerange
combine_shorter(const Filerange
*, const Filerange
*);
93 static Filerange
combine_leftmost(const Filerange
*, const Filerange
*);
94 static Filerange
combine_rightmost(const Filerange
*, const Filerange
*);
95 /* adjust current used count according to keys */
96 static const char *count(Vis
*, const char *keys
, const Arg
*arg
);
97 /* move to the count-th line or if not given either to the first (arg->i < 0)
98 * or last (arg->i > 0) line of file */
99 static const char *gotoline(Vis
*, const char *keys
, const Arg
*arg
);
100 /* set motion type either LINEWISE or CHARWISE via arg->i */
101 static const char *motiontype(Vis
*, const char *keys
, const Arg
*arg
);
102 /* make the current action use the operator indicated by arg->i */
103 static const char *operator(Vis
*, const char *keys
, const Arg
*arg
);
104 /* blocks to read a key and performs movement indicated by arg->i which
105 * should be one of VIS_MOVE_{RIGHT,LEFT}_{TO,TILL} */
106 static const char *movement_key(Vis
*, const char *keys
, const Arg
*arg
);
107 /* perform the movement as indicated by arg->i */
108 static const char *movement(Vis
*, const char *keys
, const Arg
*arg
);
109 /* let the current operator affect the range indicated by the text object arg->i */
110 static const char *textobj(Vis
*, const char *keys
, const Arg
*arg
);
111 /* move to the other end of selected text */
112 static const char *selection_end(Vis
*, const char *keys
, const Arg
*arg
);
113 /* use register indicated by keys for the current operator */
114 static const char *reg(Vis
*, const char *keys
, const Arg
*arg
);
115 /* use mark indicated by keys for the current action */
116 static const char *mark(Vis
*, const char *keys
, const Arg
*arg
);
117 /* {un,re}do last action, redraw window */
118 static const char *undo(Vis
*, const char *keys
, const Arg
*arg
);
119 static const char *redo(Vis
*, const char *keys
, const Arg
*arg
);
120 /* earlier, later action chronologically, redraw window */
121 static const char *earlier(Vis
*, const char *keys
, const Arg
*arg
);
122 static const char *later(Vis
*, const char *keys
, const Arg
*arg
);
123 /* delete from the current cursor position to the end of
124 * movement as indicated by arg->i */
125 static const char *delete(Vis
*, const char *keys
, const Arg
*arg
);
126 /* insert register content indicated by keys at current cursor position */
127 static const char *insert_register(Vis
*, const char *keys
, const Arg
*arg
);
128 /* show a user prompt to get input with title arg->s */
129 static const char *prompt_show(Vis
*, const char *keys
, const Arg
*arg
);
130 /* blocks to read 3 consecutive digits and inserts the corresponding byte value */
131 static const char *insert_verbatim(Vis
*, const char *keys
, const Arg
*arg
);
132 /* scroll window content according to arg->i which can be either PAGE, PAGE_HALF,
133 * or an arbitrary number of lines. a multiplier overrides what is given in arg->i.
134 * negative values scroll back, positive forward. */
135 static const char *wscroll(Vis
*, const char *keys
, const Arg
*arg
);
136 /* similar to scroll, but do only move window content not cursor position */
137 static const char *wslide(Vis
*, const char *keys
, const Arg
*arg
);
138 /* call editor function as indicated by arg->f */
139 static const char *call(Vis
*, const char *keys
, const Arg
*arg
);
140 /* call window function as indicated by arg->w */
141 static const char *window(Vis
*, const char *keys
, const Arg
*arg
);
142 /* show info about Unicode character at cursor position */
143 static const char *unicode_info(Vis
*, const char *keys
, const Arg
*arg
);
144 /* either go to count % of file or to matching item */
145 static const char *percent(Vis
*, const char *keys
, const Arg
*arg
);
146 /* navigate jumplist next (arg->i > 0), prev (arg->i < 0), save (arg->i = 0) */
147 static const char *jumplist(Vis
*, const char *keys
, const Arg
*arg
);
150 VIS_ACTION_EDITOR_SUSPEND
,
151 VIS_ACTION_CURSOR_CHAR_PREV
,
152 VIS_ACTION_CURSOR_CHAR_NEXT
,
153 VIS_ACTION_CURSOR_LINE_CHAR_PREV
,
154 VIS_ACTION_CURSOR_LINE_CHAR_NEXT
,
155 VIS_ACTION_CURSOR_CODEPOINT_PREV
,
156 VIS_ACTION_CURSOR_CODEPOINT_NEXT
,
157 VIS_ACTION_CURSOR_WORD_START_PREV
,
158 VIS_ACTION_CURSOR_WORD_START_NEXT
,
159 VIS_ACTION_CURSOR_WORD_END_PREV
,
160 VIS_ACTION_CURSOR_WORD_END_NEXT
,
161 VIS_ACTION_CURSOR_LONGWORD_START_PREV
,
162 VIS_ACTION_CURSOR_LONGWORD_START_NEXT
,
163 VIS_ACTION_CURSOR_LONGWORD_END_PREV
,
164 VIS_ACTION_CURSOR_LONGWORD_END_NEXT
,
165 VIS_ACTION_CURSOR_LINE_UP
,
166 VIS_ACTION_CURSOR_LINE_DOWN
,
167 VIS_ACTION_CURSOR_LINE_START
,
168 VIS_ACTION_CURSOR_LINE_FINISH
,
169 VIS_ACTION_CURSOR_LINE_BEGIN
,
170 VIS_ACTION_CURSOR_LINE_END
,
171 VIS_ACTION_CURSOR_SCREEN_LINE_UP
,
172 VIS_ACTION_CURSOR_SCREEN_LINE_DOWN
,
173 VIS_ACTION_CURSOR_SCREEN_LINE_BEGIN
,
174 VIS_ACTION_CURSOR_SCREEN_LINE_MIDDLE
,
175 VIS_ACTION_CURSOR_SCREEN_LINE_END
,
176 VIS_ACTION_CURSOR_PERCENT
,
177 VIS_ACTION_CURSOR_BYTE
,
178 VIS_ACTION_CURSOR_BYTE_LEFT
,
179 VIS_ACTION_CURSOR_BYTE_RIGHT
,
180 VIS_ACTION_CURSOR_PARAGRAPH_PREV
,
181 VIS_ACTION_CURSOR_PARAGRAPH_NEXT
,
182 VIS_ACTION_CURSOR_SENTENCE_PREV
,
183 VIS_ACTION_CURSOR_SENTENCE_NEXT
,
184 VIS_ACTION_CURSOR_BLOCK_START
,
185 VIS_ACTION_CURSOR_BLOCK_END
,
186 VIS_ACTION_CURSOR_PARENTHESIS_START
,
187 VIS_ACTION_CURSOR_PARENTHESIS_END
,
188 VIS_ACTION_CURSOR_COLUMN
,
189 VIS_ACTION_CURSOR_LINE_FIRST
,
190 VIS_ACTION_CURSOR_LINE_LAST
,
191 VIS_ACTION_CURSOR_WINDOW_LINE_TOP
,
192 VIS_ACTION_CURSOR_WINDOW_LINE_MIDDLE
,
193 VIS_ACTION_CURSOR_WINDOW_LINE_BOTTOM
,
194 VIS_ACTION_CURSOR_SEARCH_REPEAT_FORWARD
,
195 VIS_ACTION_CURSOR_SEARCH_REPEAT_BACKWARD
,
196 VIS_ACTION_CURSOR_SEARCH_REPEAT
,
197 VIS_ACTION_CURSOR_SEARCH_REPEAT_REVERSE
,
198 VIS_ACTION_CURSOR_SEARCH_WORD_FORWARD
,
199 VIS_ACTION_CURSOR_SEARCH_WORD_BACKWARD
,
200 VIS_ACTION_WINDOW_PAGE_UP
,
201 VIS_ACTION_WINDOW_PAGE_DOWN
,
202 VIS_ACTION_WINDOW_HALFPAGE_UP
,
203 VIS_ACTION_WINDOW_HALFPAGE_DOWN
,
204 VIS_ACTION_MODE_NORMAL
,
205 VIS_ACTION_MODE_VISUAL
,
206 VIS_ACTION_MODE_VISUAL_LINE
,
207 VIS_ACTION_MODE_INSERT
,
208 VIS_ACTION_MODE_REPLACE
,
209 VIS_ACTION_DELETE_CHAR_PREV
,
210 VIS_ACTION_DELETE_CHAR_NEXT
,
211 VIS_ACTION_DELETE_LINE_BEGIN
,
212 VIS_ACTION_DELETE_WORD_PREV
,
213 VIS_ACTION_JUMPLIST_PREV
,
214 VIS_ACTION_JUMPLIST_NEXT
,
215 VIS_ACTION_JUMPLIST_SAVE
,
220 VIS_ACTION_MACRO_RECORD
,
221 VIS_ACTION_MACRO_REPLAY
,
224 VIS_ACTION_REPLACE_CHAR
,
225 VIS_ACTION_TOTILL_REPEAT
,
226 VIS_ACTION_TOTILL_REVERSE
,
227 VIS_ACTION_PROMPT_SEARCH_FORWARD
,
228 VIS_ACTION_PROMPT_SEARCH_BACKWARD
,
229 VIS_ACTION_TILL_LEFT
,
230 VIS_ACTION_TILL_RIGHT
,
234 VIS_ACTION_OPERATOR_CHANGE
,
235 VIS_ACTION_OPERATOR_DELETE
,
236 VIS_ACTION_OPERATOR_YANK
,
237 VIS_ACTION_OPERATOR_SHIFT_LEFT
,
238 VIS_ACTION_OPERATOR_SHIFT_RIGHT
,
239 VIS_ACTION_OPERATOR_CASE_LOWER
,
240 VIS_ACTION_OPERATOR_CASE_UPPER
,
241 VIS_ACTION_OPERATOR_CASE_SWAP
,
243 VIS_ACTION_INSERT_NEWLINE
,
244 VIS_ACTION_INSERT_TAB
,
245 VIS_ACTION_INSERT_VERBATIM
,
246 VIS_ACTION_INSERT_REGISTER
,
247 VIS_ACTION_WINDOW_NEXT
,
248 VIS_ACTION_WINDOW_PREV
,
249 VIS_ACTION_APPEND_CHAR_NEXT
,
250 VIS_ACTION_APPEND_LINE_END
,
251 VIS_ACTION_INSERT_LINE_START
,
252 VIS_ACTION_OPEN_LINE_ABOVE
,
253 VIS_ACTION_OPEN_LINE_BELOW
,
254 VIS_ACTION_JOIN_LINES
,
255 VIS_ACTION_JOIN_LINES_TRIM
,
256 VIS_ACTION_PROMPT_SHOW
,
258 VIS_ACTION_SELECTION_FLIP
,
259 VIS_ACTION_WINDOW_REDRAW_TOP
,
260 VIS_ACTION_WINDOW_REDRAW_CENTER
,
261 VIS_ACTION_WINDOW_REDRAW_BOTTOM
,
262 VIS_ACTION_WINDOW_SLIDE_UP
,
263 VIS_ACTION_WINDOW_SLIDE_DOWN
,
264 VIS_ACTION_PUT_AFTER
,
265 VIS_ACTION_PUT_BEFORE
,
266 VIS_ACTION_PUT_AFTER_END
,
267 VIS_ACTION_PUT_BEFORE_END
,
268 VIS_ACTION_SELECTIONS_MATCH_WORD
,
269 VIS_ACTION_SELECTIONS_NEW_LINE_ABOVE
,
270 VIS_ACTION_SELECTIONS_NEW_LINE_ABOVE_FIRST
,
271 VIS_ACTION_SELECTIONS_NEW_LINE_BELOW
,
272 VIS_ACTION_SELECTIONS_NEW_LINE_BELOW_LAST
,
273 VIS_ACTION_SELECTIONS_NEW_LINES_BEGIN
,
274 VIS_ACTION_SELECTIONS_NEW_LINES_END
,
275 VIS_ACTION_SELECTIONS_NEW_MATCH_NEXT
,
276 VIS_ACTION_SELECTIONS_NEW_MATCH_SKIP
,
277 VIS_ACTION_SELECTIONS_ALIGN
,
278 VIS_ACTION_SELECTIONS_ALIGN_INDENT_LEFT
,
279 VIS_ACTION_SELECTIONS_ALIGN_INDENT_RIGHT
,
280 VIS_ACTION_SELECTIONS_REMOVE_ALL
,
281 VIS_ACTION_SELECTIONS_REMOVE_LAST
,
282 VIS_ACTION_SELECTIONS_REMOVE_COLUMN
,
283 VIS_ACTION_SELECTIONS_REMOVE_COLUMN_EXCEPT
,
284 VIS_ACTION_SELECTIONS_PREV
,
285 VIS_ACTION_SELECTIONS_NEXT
,
286 VIS_ACTION_SELECTIONS_ROTATE_LEFT
,
287 VIS_ACTION_SELECTIONS_ROTATE_RIGHT
,
288 VIS_ACTION_SELECTIONS_TRIM
,
289 VIS_ACTION_SELECTIONS_SAVE
,
290 VIS_ACTION_SELECTIONS_RESTORE
,
291 VIS_ACTION_SELECTIONS_UNION
,
292 VIS_ACTION_SELECTIONS_INTERSECT
,
293 VIS_ACTION_SELECTIONS_COMPLEMENT
,
294 VIS_ACTION_SELECTIONS_MINUS
,
295 VIS_ACTION_SELECTIONS_COMBINE_UNION
,
296 VIS_ACTION_SELECTIONS_COMBINE_INTERSECT
,
297 VIS_ACTION_SELECTIONS_COMBINE_LONGER
,
298 VIS_ACTION_SELECTIONS_COMBINE_SHORTER
,
299 VIS_ACTION_SELECTIONS_COMBINE_LEFTMOST
,
300 VIS_ACTION_SELECTIONS_COMBINE_RIGHTMOST
,
301 VIS_ACTION_TEXT_OBJECT_WORD_OUTER
,
302 VIS_ACTION_TEXT_OBJECT_WORD_INNER
,
303 VIS_ACTION_TEXT_OBJECT_LONGWORD_OUTER
,
304 VIS_ACTION_TEXT_OBJECT_LONGWORD_INNER
,
305 VIS_ACTION_TEXT_OBJECT_SENTENCE
,
306 VIS_ACTION_TEXT_OBJECT_PARAGRAPH
,
307 VIS_ACTION_TEXT_OBJECT_PARAGRAPH_OUTER
,
308 VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_OUTER
,
309 VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_INNER
,
310 VIS_ACTION_TEXT_OBJECT_PARENTHESIS_OUTER
,
311 VIS_ACTION_TEXT_OBJECT_PARENTHESIS_INNER
,
312 VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_OUTER
,
313 VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_INNER
,
314 VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_OUTER
,
315 VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_INNER
,
316 VIS_ACTION_TEXT_OBJECT_QUOTE_OUTER
,
317 VIS_ACTION_TEXT_OBJECT_QUOTE_INNER
,
318 VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_OUTER
,
319 VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_INNER
,
320 VIS_ACTION_TEXT_OBJECT_BACKTICK_OUTER
,
321 VIS_ACTION_TEXT_OBJECT_BACKTICK_INNER
,
322 VIS_ACTION_TEXT_OBJECT_ENTIRE_OUTER
,
323 VIS_ACTION_TEXT_OBJECT_ENTIRE_INNER
,
324 VIS_ACTION_TEXT_OBJECT_LINE_OUTER
,
325 VIS_ACTION_TEXT_OBJECT_LINE_INNER
,
326 VIS_ACTION_TEXT_OBJECT_INDENTATION
,
327 VIS_ACTION_TEXT_OBJECT_SEARCH_FORWARD
,
328 VIS_ACTION_TEXT_OBJECT_SEARCH_BACKWARD
,
329 VIS_ACTION_MOTION_CHARWISE
,
330 VIS_ACTION_MOTION_LINEWISE
,
331 VIS_ACTION_UNICODE_INFO
,
332 VIS_ACTION_UTF8_INFO
,
336 static const KeyAction vis_action
[] = {
337 [VIS_ACTION_EDITOR_SUSPEND
] = {
339 VIS_HELP("Suspend the editor")
342 [VIS_ACTION_CURSOR_CHAR_PREV
] = {
343 "vis-motion-char-prev",
344 VIS_HELP("Move cursor left, to the previous character")
345 movement
, { .i
= VIS_MOVE_CHAR_PREV
}
347 [VIS_ACTION_CURSOR_CHAR_NEXT
] = {
348 "vis-motion-char-next",
349 VIS_HELP("Move cursor right, to the next character")
350 movement
, { .i
= VIS_MOVE_CHAR_NEXT
}
352 [VIS_ACTION_CURSOR_LINE_CHAR_PREV
] = {
353 "vis-motion-line-char-prev",
354 VIS_HELP("Move cursor left, to the previous character on the same line")
355 movement
, { .i
= VIS_MOVE_LINE_CHAR_PREV
}
357 [VIS_ACTION_CURSOR_LINE_CHAR_NEXT
] = {
358 "vis-motion-line-char-next",
359 VIS_HELP("Move cursor right, to the next character on the same line")
360 movement
, { .i
= VIS_MOVE_LINE_CHAR_NEXT
}
362 [VIS_ACTION_CURSOR_CODEPOINT_PREV
] = {
363 "vis-motion-codepoint-prev",
364 VIS_HELP("Move to the previous Unicode codepoint")
365 movement
, { .i
= VIS_MOVE_CODEPOINT_PREV
}
367 [VIS_ACTION_CURSOR_CODEPOINT_NEXT
] = {
368 "vis-motion-codepoint-next",
369 VIS_HELP("Move to the next Unicode codepoint")
370 movement
, { .i
= VIS_MOVE_CODEPOINT_NEXT
}
372 [VIS_ACTION_CURSOR_WORD_START_PREV
] = {
373 "vis-motion-word-start-prev",
374 VIS_HELP("Move cursor words backwards")
375 movement
, { .i
= VIS_MOVE_WORD_START_PREV
}
377 [VIS_ACTION_CURSOR_WORD_START_NEXT
] = {
378 "vis-motion-word-start-next",
379 VIS_HELP("Move cursor words forwards")
380 movement
, { .i
= VIS_MOVE_WORD_START_NEXT
}
382 [VIS_ACTION_CURSOR_WORD_END_PREV
] = {
383 "vis-motion-word-end-prev",
384 VIS_HELP("Move cursor backwards to the end of word")
385 movement
, { .i
= VIS_MOVE_WORD_END_PREV
}
387 [VIS_ACTION_CURSOR_WORD_END_NEXT
] = {
388 "vis-motion-word-end-next",
389 VIS_HELP("Move cursor forward to the end of word")
390 movement
, { .i
= VIS_MOVE_WORD_END_NEXT
}
392 [VIS_ACTION_CURSOR_LONGWORD_START_PREV
] = {
393 "vis-motion-bigword-start-prev",
394 VIS_HELP("Move cursor WORDS backwards")
395 movement
, { .i
= VIS_MOVE_LONGWORD_START_PREV
}
397 [VIS_ACTION_CURSOR_LONGWORD_START_NEXT
] = {
398 "vis-motion-bigword-start-next",
399 VIS_HELP("Move cursor WORDS forwards")
400 movement
, { .i
= VIS_MOVE_LONGWORD_START_NEXT
}
402 [VIS_ACTION_CURSOR_LONGWORD_END_PREV
] = {
403 "vis-motion-bigword-end-prev",
404 VIS_HELP("Move cursor backwards to the end of WORD")
405 movement
, { .i
= VIS_MOVE_LONGWORD_END_PREV
}
407 [VIS_ACTION_CURSOR_LONGWORD_END_NEXT
] = {
408 "vis-motion-bigword-end-next",
409 VIS_HELP("Move cursor forward to the end of WORD")
410 movement
, { .i
= VIS_MOVE_LONGWORD_END_NEXT
}
412 [VIS_ACTION_CURSOR_LINE_UP
] = {
413 "vis-motion-line-up",
414 VIS_HELP("Move cursor line upwards")
415 movement
, { .i
= VIS_MOVE_LINE_UP
}
417 [VIS_ACTION_CURSOR_LINE_DOWN
] = {
418 "vis-motion-line-down",
419 VIS_HELP("Move cursor line downwards")
420 movement
, { .i
= VIS_MOVE_LINE_DOWN
}
422 [VIS_ACTION_CURSOR_LINE_START
] = {
423 "vis-motion-line-start",
424 VIS_HELP("Move cursor to first non-blank character of the line")
425 movement
, { .i
= VIS_MOVE_LINE_START
}
427 [VIS_ACTION_CURSOR_LINE_FINISH
] = {
428 "vis-motion-line-finish",
429 VIS_HELP("Move cursor to last non-blank character of the line")
430 movement
, { .i
= VIS_MOVE_LINE_FINISH
}
432 [VIS_ACTION_CURSOR_LINE_BEGIN
] = {
433 "vis-motion-line-begin",
434 VIS_HELP("Move cursor to first character of the line")
435 movement
, { .i
= VIS_MOVE_LINE_BEGIN
}
437 [VIS_ACTION_CURSOR_LINE_END
] = {
438 "vis-motion-line-end",
439 VIS_HELP("Move cursor to end of the line")
440 movement
, { .i
= VIS_MOVE_LINE_END
}
442 [VIS_ACTION_CURSOR_SCREEN_LINE_UP
] = {
443 "vis-motion-screenline-up",
444 VIS_HELP("Move cursor screen/display line upwards")
445 movement
, { .i
= VIS_MOVE_SCREEN_LINE_UP
}
447 [VIS_ACTION_CURSOR_SCREEN_LINE_DOWN
] = {
448 "vis-motion-screenline-down",
449 VIS_HELP("Move cursor screen/display line downwards")
450 movement
, { .i
= VIS_MOVE_SCREEN_LINE_DOWN
}
452 [VIS_ACTION_CURSOR_SCREEN_LINE_BEGIN
] = {
453 "vis-motion-screenline-begin",
454 VIS_HELP("Move cursor to beginning of screen/display line")
455 movement
, { .i
= VIS_MOVE_SCREEN_LINE_BEGIN
}
457 [VIS_ACTION_CURSOR_SCREEN_LINE_MIDDLE
] = {
458 "vis-motion-screenline-middle",
459 VIS_HELP("Move cursor to middle of screen/display line")
460 movement
, { .i
= VIS_MOVE_SCREEN_LINE_MIDDLE
}
462 [VIS_ACTION_CURSOR_SCREEN_LINE_END
] = {
463 "vis-motion-screenline-end",
464 VIS_HELP("Move cursor to end of screen/display line")
465 movement
, { .i
= VIS_MOVE_SCREEN_LINE_END
}
467 [VIS_ACTION_CURSOR_PERCENT
] = {
468 "vis-motion-percent",
469 VIS_HELP("Move to count % of file or matching item")
472 [VIS_ACTION_CURSOR_BYTE
] = {
474 VIS_HELP("Move to absolute byte position")
475 movement
, { .i
= VIS_MOVE_BYTE
}
477 [VIS_ACTION_CURSOR_BYTE_LEFT
] = {
478 "vis-motion-byte-left",
479 VIS_HELP("Move count bytes to the left")
480 movement
, { .i
= VIS_MOVE_BYTE_LEFT
}
482 [VIS_ACTION_CURSOR_BYTE_RIGHT
] = {
483 "vis-motion-byte-right",
484 VIS_HELP("Move count bytes to the right")
485 movement
, { .i
= VIS_MOVE_BYTE_RIGHT
}
487 [VIS_ACTION_CURSOR_PARAGRAPH_PREV
] = {
488 "vis-motion-paragraph-prev",
489 VIS_HELP("Move cursor paragraph backward")
490 movement
, { .i
= VIS_MOVE_PARAGRAPH_PREV
}
492 [VIS_ACTION_CURSOR_PARAGRAPH_NEXT
] = {
493 "vis-motion-paragraph-next",
494 VIS_HELP("Move cursor paragraph forward")
495 movement
, { .i
= VIS_MOVE_PARAGRAPH_NEXT
}
497 [VIS_ACTION_CURSOR_SENTENCE_PREV
] = {
498 "vis-motion-sentence-prev",
499 VIS_HELP("Move cursor sentence backward")
500 movement
, { .i
= VIS_MOVE_SENTENCE_PREV
}
502 [VIS_ACTION_CURSOR_SENTENCE_NEXT
] = {
503 "vis-motion-sentence-next",
504 VIS_HELP("Move cursor sentence forward")
505 movement
, { .i
= VIS_MOVE_SENTENCE_NEXT
}
507 [VIS_ACTION_CURSOR_BLOCK_START
] = {
508 "vis-motion-block-start",
509 VIS_HELP("Move cursor to the opening curly brace in a block")
510 movement
, { .i
= VIS_MOVE_BLOCK_START
}
512 [VIS_ACTION_CURSOR_BLOCK_END
] = {
513 "vis-motion-block-end",
514 VIS_HELP("Move cursor to the closing curly brace in a block")
515 movement
, { .i
= VIS_MOVE_BLOCK_END
}
517 [VIS_ACTION_CURSOR_PARENTHESIS_START
] = {
518 "vis-motion-parenthesis-start",
519 VIS_HELP("Move cursor to the opening parenthesis inside a pair of parentheses")
520 movement
, { .i
= VIS_MOVE_PARENTHESIS_START
}
522 [VIS_ACTION_CURSOR_PARENTHESIS_END
] = {
523 "vis-motion-parenthesis-end",
524 VIS_HELP("Move cursor to the closing parenthesis inside a pair of parentheses")
525 movement
, { .i
= VIS_MOVE_PARENTHESIS_END
}
527 [VIS_ACTION_CURSOR_COLUMN
] = {
529 VIS_HELP("Move cursor to given column of current line")
530 movement
, { .i
= VIS_MOVE_COLUMN
}
532 [VIS_ACTION_CURSOR_LINE_FIRST
] = {
533 "vis-motion-line-first",
534 VIS_HELP("Move cursor to given line (defaults to first)")
535 gotoline
, { .i
= -1 }
537 [VIS_ACTION_CURSOR_LINE_LAST
] = {
538 "vis-motion-line-last",
539 VIS_HELP("Move cursor to given line (defaults to last)")
540 gotoline
, { .i
= +1 }
542 [VIS_ACTION_CURSOR_WINDOW_LINE_TOP
] = {
543 "vis-motion-window-line-top",
544 VIS_HELP("Move cursor to top line of the window")
545 movement
, { .i
= VIS_MOVE_WINDOW_LINE_TOP
}
547 [VIS_ACTION_CURSOR_WINDOW_LINE_MIDDLE
] = {
548 "vis-motion-window-line-middle",
549 VIS_HELP("Move cursor to middle line of the window")
550 movement
, { .i
= VIS_MOVE_WINDOW_LINE_MIDDLE
}
552 [VIS_ACTION_CURSOR_WINDOW_LINE_BOTTOM
] = {
553 "vis-motion-window-line-bottom",
554 VIS_HELP("Move cursor to bottom line of the window")
555 movement
, { .i
= VIS_MOVE_WINDOW_LINE_BOTTOM
}
557 [VIS_ACTION_CURSOR_SEARCH_REPEAT_FORWARD
] = {
558 "vis-motion-search-repeat-forward",
559 VIS_HELP("Move cursor to next match in forward direction")
560 movement
, { .i
= VIS_MOVE_SEARCH_REPEAT_FORWARD
}
562 [VIS_ACTION_CURSOR_SEARCH_REPEAT_BACKWARD
] = {
563 "vis-motion-search-repeat-backward",
564 VIS_HELP("Move cursor to previous match in backward direction")
565 movement
, { .i
= VIS_MOVE_SEARCH_REPEAT_BACKWARD
}
567 [VIS_ACTION_CURSOR_SEARCH_REPEAT
] = {
568 "vis-motion-search-repeat",
569 VIS_HELP("Move cursor to next match")
570 movement
, { .i
= VIS_MOVE_SEARCH_REPEAT
}
572 [VIS_ACTION_CURSOR_SEARCH_REPEAT_REVERSE
] = {
573 "vis-motion-search-repeat-reverse",
574 VIS_HELP("Move cursor to next match in opposite direction")
575 movement
, { .i
= VIS_MOVE_SEARCH_REPEAT_REVERSE
}
577 [VIS_ACTION_CURSOR_SEARCH_WORD_FORWARD
] = {
578 "vis-motion-search-word-forward",
579 VIS_HELP("Move cursor to next occurrence of the word under cursor")
580 movement
, { .i
= VIS_MOVE_SEARCH_WORD_FORWARD
}
582 [VIS_ACTION_CURSOR_SEARCH_WORD_BACKWARD
] = {
583 "vis-motion-search-word-backward",
584 VIS_HELP("Move cursor to previous occurrence of the word under cursor")
585 movement
, { .i
= VIS_MOVE_SEARCH_WORD_BACKWARD
}
587 [VIS_ACTION_WINDOW_PAGE_UP
] = {
588 "vis-window-page-up",
589 VIS_HELP("Scroll window pages backwards (upwards)")
590 wscroll
, { .i
= -PAGE
}
592 [VIS_ACTION_WINDOW_HALFPAGE_UP
] = {
593 "vis-window-halfpage-up",
594 VIS_HELP("Scroll window half pages backwards (upwards)")
595 wscroll
, { .i
= -PAGE_HALF
}
597 [VIS_ACTION_WINDOW_PAGE_DOWN
] = {
598 "vis-window-page-down",
599 VIS_HELP("Scroll window pages forwards (downwards)")
600 wscroll
, { .i
= +PAGE
}
602 [VIS_ACTION_WINDOW_HALFPAGE_DOWN
] = {
603 "vis-window-halfpage-down",
604 VIS_HELP("Scroll window half pages forwards (downwards)")
605 wscroll
, { .i
= +PAGE_HALF
}
607 [VIS_ACTION_MODE_NORMAL
] = {
609 VIS_HELP("Enter normal mode")
610 switchmode
, { .i
= VIS_MODE_NORMAL
}
612 [VIS_ACTION_MODE_VISUAL
] = {
613 "vis-mode-visual-charwise",
614 VIS_HELP("Enter characterwise visual mode")
615 switchmode
, { .i
= VIS_MODE_VISUAL
}
617 [VIS_ACTION_MODE_VISUAL_LINE
] = {
618 "vis-mode-visual-linewise",
619 VIS_HELP("Enter linewise visual mode")
620 switchmode
, { .i
= VIS_MODE_VISUAL_LINE
}
622 [VIS_ACTION_MODE_INSERT
] = {
624 VIS_HELP("Enter insert mode")
625 insertmode
, { .i
= VIS_MOVE_NOP
}
627 [VIS_ACTION_MODE_REPLACE
] = {
629 VIS_HELP("Enter replace mode")
630 replacemode
, { .i
= VIS_MOVE_NOP
}
632 [VIS_ACTION_DELETE_CHAR_PREV
] = {
633 "vis-delete-char-prev",
634 VIS_HELP("Delete the previous character")
635 delete, { .i
= VIS_MOVE_CHAR_PREV
}
637 [VIS_ACTION_DELETE_CHAR_NEXT
] = {
638 "vis-delete-char-next",
639 VIS_HELP("Delete the next character")
640 delete, { .i
= VIS_MOVE_CHAR_NEXT
}
642 [VIS_ACTION_DELETE_LINE_BEGIN
] = {
643 "vis-delete-line-begin",
644 VIS_HELP("Delete until the start of the current line")
645 delete, { .i
= VIS_MOVE_LINE_BEGIN
}
647 [VIS_ACTION_DELETE_WORD_PREV
] = {
648 "vis-delete-word-prev",
649 VIS_HELP("Delete the previous WORD")
650 delete, { .i
= VIS_MOVE_WORD_START_PREV
}
652 [VIS_ACTION_JUMPLIST_PREV
] = {
654 VIS_HELP("Go to older cursor position in jump list")
655 jumplist
, { .i
= -1 }
657 [VIS_ACTION_JUMPLIST_NEXT
] = {
659 VIS_HELP("Go to newer cursor position in jump list")
660 jumplist
, { .i
= +1 }
662 [VIS_ACTION_JUMPLIST_SAVE
] = {
664 VIS_HELP("Save current selections in jump list")
667 [VIS_ACTION_UNDO
] = {
669 VIS_HELP("Undo last change")
672 [VIS_ACTION_REDO
] = {
674 VIS_HELP("Redo last change")
677 [VIS_ACTION_EARLIER
] = {
679 VIS_HELP("Goto older text state")
682 [VIS_ACTION_LATER
] = {
684 VIS_HELP("Goto newer text state")
687 [VIS_ACTION_MACRO_RECORD
] = {
689 VIS_HELP("Record macro into given register")
692 [VIS_ACTION_MACRO_REPLAY
] = {
694 VIS_HELP("Replay macro, execute the content of the given register")
697 [VIS_ACTION_MARK
] = {
699 VIS_HELP("Use given mark for next action")
702 [VIS_ACTION_REDRAW
] = {
704 VIS_HELP("Redraw current editor content")
705 call
, { .f
= vis_redraw
}
707 [VIS_ACTION_REPLACE_CHAR
] = {
709 VIS_HELP("Replace the character under the cursor")
712 [VIS_ACTION_TOTILL_REPEAT
] = {
713 "vis-motion-totill-repeat",
714 VIS_HELP("Repeat latest to/till motion")
715 movement
, { .i
= VIS_MOVE_TOTILL_REPEAT
}
717 [VIS_ACTION_TOTILL_REVERSE
] = {
718 "vis-motion-totill-reverse",
719 VIS_HELP("Repeat latest to/till motion but in opposite direction")
720 movement
, { .i
= VIS_MOVE_TOTILL_REVERSE
}
722 [VIS_ACTION_PROMPT_SEARCH_FORWARD
] = {
723 "vis-search-forward",
724 VIS_HELP("Search forward")
725 prompt_show
, { .s
= "/" }
727 [VIS_ACTION_PROMPT_SEARCH_BACKWARD
] = {
728 "vis-search-backward",
729 VIS_HELP("Search backward")
730 prompt_show
, { .s
= "?" }
732 [VIS_ACTION_TILL_LEFT
] = {
733 "vis-motion-till-left",
734 VIS_HELP("Till after the occurrence of character to the left")
735 movement_key
, { .i
= VIS_MOVE_LEFT_TILL
}
737 [VIS_ACTION_TILL_RIGHT
] = {
738 "vis-motion-till-right",
739 VIS_HELP("Till before the occurrence of character to the right")
740 movement_key
, { .i
= VIS_MOVE_RIGHT_TILL
}
742 [VIS_ACTION_TO_LEFT
] = {
743 "vis-motion-to-left",
744 VIS_HELP("To the first occurrence of character to the left")
745 movement_key
, { .i
= VIS_MOVE_LEFT_TO
}
747 [VIS_ACTION_TO_RIGHT
] = {
748 "vis-motion-to-right",
749 VIS_HELP("To the first occurrence of character to the right")
750 movement_key
, { .i
= VIS_MOVE_RIGHT_TO
}
752 [VIS_ACTION_REGISTER
] = {
754 VIS_HELP("Use given register for next operator")
757 [VIS_ACTION_OPERATOR_CHANGE
] = {
758 "vis-operator-change",
759 VIS_HELP("Change operator")
760 operator, { .i
= VIS_OP_CHANGE
}
762 [VIS_ACTION_OPERATOR_DELETE
] = {
763 "vis-operator-delete",
764 VIS_HELP("Delete operator")
765 operator, { .i
= VIS_OP_DELETE
}
767 [VIS_ACTION_OPERATOR_YANK
] = {
769 VIS_HELP("Yank operator")
770 operator, { .i
= VIS_OP_YANK
}
772 [VIS_ACTION_OPERATOR_SHIFT_LEFT
] = {
773 "vis-operator-shift-left",
774 VIS_HELP("Shift left operator")
775 operator, { .i
= VIS_OP_SHIFT_LEFT
}
777 [VIS_ACTION_OPERATOR_SHIFT_RIGHT
] = {
778 "vis-operator-shift-right",
779 VIS_HELP("Shift right operator")
780 operator, { .i
= VIS_OP_SHIFT_RIGHT
}
782 [VIS_ACTION_OPERATOR_CASE_LOWER
] = {
783 "vis-operator-case-lower",
784 VIS_HELP("Lowercase operator")
785 operator, { .i
= VIS_OP_CASE_LOWER
}
787 [VIS_ACTION_OPERATOR_CASE_UPPER
] = {
788 "vis-operator-case-upper",
789 VIS_HELP("Uppercase operator")
790 operator, { .i
= VIS_OP_CASE_UPPER
}
792 [VIS_ACTION_OPERATOR_CASE_SWAP
] = {
793 "vis-operator-case-swap",
794 VIS_HELP("Swap case operator")
795 operator, { .i
= VIS_OP_CASE_SWAP
}
797 [VIS_ACTION_COUNT
] = {
799 VIS_HELP("Count specifier")
802 [VIS_ACTION_INSERT_NEWLINE
] = {
803 "vis-insert-newline",
804 VIS_HELP("Insert a line break (depending on file type)")
805 call
, { .f
= vis_insert_nl
}
807 [VIS_ACTION_INSERT_TAB
] = {
809 VIS_HELP("Insert a tab (might be converted to spaces)")
810 call
, { .f
= vis_insert_tab
}
812 [VIS_ACTION_INSERT_VERBATIM
] = {
813 "vis-insert-verbatim",
814 VIS_HELP("Insert Unicode character based on code point")
817 [VIS_ACTION_INSERT_REGISTER
] = {
818 "vis-insert-register",
819 VIS_HELP("Insert specified register content")
822 [VIS_ACTION_WINDOW_NEXT
] = {
824 VIS_HELP("Focus next window")
825 call
, { .f
= vis_window_next
}
827 [VIS_ACTION_WINDOW_PREV
] = {
829 VIS_HELP("Focus previous window")
830 call
, { .f
= vis_window_prev
}
832 [VIS_ACTION_APPEND_CHAR_NEXT
] = {
833 "vis-append-char-next",
834 VIS_HELP("Append text after the cursor")
835 insertmode
, { .i
= VIS_MOVE_LINE_CHAR_NEXT
}
837 [VIS_ACTION_APPEND_LINE_END
] = {
838 "vis-append-line-end",
839 VIS_HELP("Append text after the end of the line")
840 insertmode
, { .i
= VIS_MOVE_LINE_END
},
842 [VIS_ACTION_INSERT_LINE_START
] = {
843 "vis-insert-line-start",
844 VIS_HELP("Insert text before the first non-blank in the line")
845 insertmode
, { .i
= VIS_MOVE_LINE_START
},
847 [VIS_ACTION_OPEN_LINE_ABOVE
] = {
848 "vis-open-line-above",
849 VIS_HELP("Begin a new line above the cursor")
850 openline
, { .i
= -1 }
852 [VIS_ACTION_OPEN_LINE_BELOW
] = {
853 "vis-open-line-below",
854 VIS_HELP("Begin a new line below the cursor")
855 openline
, { .i
= +1 }
857 [VIS_ACTION_JOIN_LINES
] = {
859 VIS_HELP("Join selected lines")
862 [VIS_ACTION_JOIN_LINES_TRIM
] = {
863 "vis-join-lines-trim",
864 VIS_HELP("Join selected lines, remove white space")
867 [VIS_ACTION_PROMPT_SHOW
] = {
869 VIS_HELP("Show editor command line prompt")
870 prompt_show
, { .s
= ":" }
872 [VIS_ACTION_REPEAT
] = {
874 VIS_HELP("Repeat latest editor command")
877 [VIS_ACTION_SELECTION_FLIP
] = {
878 "vis-selection-flip",
879 VIS_HELP("Flip selection, move cursor to other end")
882 [VIS_ACTION_WINDOW_REDRAW_TOP
] = {
883 "vis-window-redraw-top",
884 VIS_HELP("Redraw cursor line at the top of the window")
885 window
, { .w
= view_redraw_top
}
887 [VIS_ACTION_WINDOW_REDRAW_CENTER
] = {
888 "vis-window-redraw-center",
889 VIS_HELP("Redraw cursor line at the center of the window")
890 window
, { .w
= view_redraw_center
}
892 [VIS_ACTION_WINDOW_REDRAW_BOTTOM
] = {
893 "vis-window-redraw-bottom",
894 VIS_HELP("Redraw cursor line at the bottom of the window")
895 window
, { .w
= view_redraw_bottom
}
897 [VIS_ACTION_WINDOW_SLIDE_UP
] = {
898 "vis-window-slide-up",
899 VIS_HELP("Slide window content upwards")
902 [VIS_ACTION_WINDOW_SLIDE_DOWN
] = {
903 "vis-window-slide-down",
904 VIS_HELP("Slide window content downwards")
907 [VIS_ACTION_PUT_AFTER
] = {
909 VIS_HELP("Put text after the cursor")
910 operator, { .i
= VIS_OP_PUT_AFTER
}
912 [VIS_ACTION_PUT_BEFORE
] = {
914 VIS_HELP("Put text before the cursor")
915 operator, { .i
= VIS_OP_PUT_BEFORE
}
917 [VIS_ACTION_PUT_AFTER_END
] = {
919 VIS_HELP("Put text after the cursor, place cursor after new text")
920 operator, { .i
= VIS_OP_PUT_AFTER_END
}
922 [VIS_ACTION_PUT_BEFORE_END
] = {
923 "vis-put-before-end",
924 VIS_HELP("Put text before the cursor, place cursor after new text")
925 operator, { .i
= VIS_OP_PUT_BEFORE_END
}
927 [VIS_ACTION_SELECTIONS_MATCH_WORD
] = {
928 "vis-selections-select-word",
929 VIS_HELP("Select word under cursor")
930 selections_match_word
,
932 [VIS_ACTION_SELECTIONS_NEW_LINE_ABOVE
] = {
933 "vis-selection-new-lines-above",
934 VIS_HELP("Create a new selection on the line above")
935 selections_new
, { .i
= -1 }
937 [VIS_ACTION_SELECTIONS_NEW_LINE_ABOVE_FIRST
] = {
938 "vis-selection-new-lines-above-first",
939 VIS_HELP("Create a new selection on the line above the first selection")
940 selections_new
, { .i
= INT_MIN
}
942 [VIS_ACTION_SELECTIONS_NEW_LINE_BELOW
] = {
943 "vis-selection-new-lines-below",
944 VIS_HELP("Create a new selection on the line below")
945 selections_new
, { .i
= +1 }
947 [VIS_ACTION_SELECTIONS_NEW_LINE_BELOW_LAST
] = {
948 "vis-selection-new-lines-below-last",
949 VIS_HELP("Create a new selection on the line below the last selection")
950 selections_new
, { .i
= INT_MAX
}
952 [VIS_ACTION_SELECTIONS_NEW_LINES_BEGIN
] = {
953 "vis-selection-new-lines-begin",
954 VIS_HELP("Create a new selection at the start of every line covered by selection")
955 operator, { .i
= VIS_OP_CURSOR_SOL
}
957 [VIS_ACTION_SELECTIONS_NEW_LINES_END
] = {
958 "vis-selection-new-lines-end",
959 VIS_HELP("Create a new selection at the end of every line covered by selection")
960 operator, { .i
= VIS_OP_CURSOR_EOL
}
962 [VIS_ACTION_SELECTIONS_NEW_MATCH_NEXT
] = {
963 "vis-selection-new-match-next",
964 VIS_HELP("Select the next region matching the current selection")
965 selections_match_next
,
967 [VIS_ACTION_SELECTIONS_NEW_MATCH_SKIP
] = {
968 "vis-selection-new-match-skip",
969 VIS_HELP("Clear current selection, but select next match")
970 selections_match_skip
,
972 [VIS_ACTION_SELECTIONS_ALIGN
] = {
973 "vis-selections-align",
974 VIS_HELP("Try to align all selections on the same column")
977 [VIS_ACTION_SELECTIONS_ALIGN_INDENT_LEFT
] = {
978 "vis-selections-align-indent-left",
979 VIS_HELP("Left align all selections/selections by inserting spaces")
980 selections_align_indent
, { .i
= -1 }
982 [VIS_ACTION_SELECTIONS_ALIGN_INDENT_RIGHT
] = {
983 "vis-selections-align-indent-right",
984 VIS_HELP("Right align all selections/selections by inserting spaces")
985 selections_align_indent
, { .i
= +1 }
987 [VIS_ACTION_SELECTIONS_REMOVE_ALL
] = {
988 "vis-selections-remove-all",
989 VIS_HELP("Remove all but the primary selection")
992 [VIS_ACTION_SELECTIONS_REMOVE_LAST
] = {
993 "vis-selections-remove-last",
994 VIS_HELP("Remove least recently created selection")
997 [VIS_ACTION_SELECTIONS_REMOVE_COLUMN
] = {
998 "vis-selections-remove-column",
999 VIS_HELP("Remove count selection column")
1000 selections_remove_column
, { .i
= 1 }
1002 [VIS_ACTION_SELECTIONS_REMOVE_COLUMN_EXCEPT
] = {
1003 "vis-selections-remove-column-except",
1004 VIS_HELP("Remove all but the count selection column")
1005 selections_remove_column_except
, { .i
= 1 }
1007 [VIS_ACTION_SELECTIONS_PREV
] = {
1008 "vis-selection-prev",
1009 VIS_HELP("Move to the previous selection")
1010 selections_navigate
, { .i
= -PAGE_HALF
}
1012 [VIS_ACTION_SELECTIONS_NEXT
] = {
1013 "vis-selection-next",
1014 VIS_HELP("Move to the next selection")
1015 selections_navigate
, { .i
= +PAGE_HALF
}
1017 [VIS_ACTION_SELECTIONS_ROTATE_LEFT
] = {
1018 "vis-selections-rotate-left",
1019 VIS_HELP("Rotate selections left")
1020 selections_rotate
, { .i
= -1 }
1022 [VIS_ACTION_SELECTIONS_ROTATE_RIGHT
] = {
1023 "vis-selections-rotate-right",
1024 VIS_HELP("Rotate selections right")
1025 selections_rotate
, { .i
= +1 }
1027 [VIS_ACTION_SELECTIONS_TRIM
] = {
1028 "vis-selections-trim",
1029 VIS_HELP("Remove leading and trailing white space from selections")
1032 [VIS_ACTION_SELECTIONS_SAVE
] = {
1033 "vis-selections-save",
1034 VIS_HELP("Save currently active selections to register")
1037 [VIS_ACTION_SELECTIONS_RESTORE
] = {
1038 "vis-selections-restore",
1039 VIS_HELP("Restore selections from register")
1042 [VIS_ACTION_SELECTIONS_UNION
] = {
1043 "vis-selections-union",
1044 VIS_HELP("Add selections from register")
1047 [VIS_ACTION_SELECTIONS_INTERSECT
] = {
1048 "vis-selections-intersect",
1049 VIS_HELP("Intersect selections with register")
1050 selections_intersect
1052 [VIS_ACTION_SELECTIONS_COMPLEMENT
] = {
1053 "vis-selections-complement",
1054 VIS_HELP("Complement selections")
1055 selections_complement
1057 [VIS_ACTION_SELECTIONS_MINUS
] = {
1058 "vis-selections-minus",
1059 VIS_HELP("Subtract selections from register")
1062 [VIS_ACTION_SELECTIONS_COMBINE_UNION
] = {
1063 "vis-selections-combine-union",
1064 VIS_HELP("Pairwise union with selection from register")
1065 selections_combine
, { .combine
= combine_union
}
1067 [VIS_ACTION_SELECTIONS_COMBINE_INTERSECT
] = {
1068 "vis-selections-combine-intersect",
1069 VIS_HELP("Pairwise intersect with selections from register")
1070 selections_combine
, { .combine
= combine_intersect
}
1072 [VIS_ACTION_SELECTIONS_COMBINE_LONGER
] = {
1073 "vis-selections-combine-longer",
1074 VIS_HELP("Pairwise combine: take longer")
1075 selections_combine
, { .combine
= combine_longer
}
1077 [VIS_ACTION_SELECTIONS_COMBINE_SHORTER
] = {
1078 "vis-selections-combine-shorter",
1079 VIS_HELP("Pairwise combine: take shorter")
1080 selections_combine
, { .combine
= combine_shorter
}
1082 [VIS_ACTION_SELECTIONS_COMBINE_LEFTMOST
] = {
1083 "vis-selections-combine-leftmost",
1084 VIS_HELP("Pairwise combine: leftmost")
1085 selections_combine
, { .combine
= combine_leftmost
}
1087 [VIS_ACTION_SELECTIONS_COMBINE_RIGHTMOST
] = {
1088 "vis-selections-combine-rightmost",
1089 VIS_HELP("Pairwise combine: rightmost")
1090 selections_combine
, { .combine
= combine_rightmost
}
1092 [VIS_ACTION_TEXT_OBJECT_WORD_OUTER
] = {
1093 "vis-textobject-word-outer",
1094 VIS_HELP("A word leading and trailing whitespace included")
1095 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_WORD
}
1097 [VIS_ACTION_TEXT_OBJECT_WORD_INNER
] = {
1098 "vis-textobject-word-inner",
1099 VIS_HELP("A word leading and trailing whitespace excluded")
1100 textobj
, { .i
= VIS_TEXTOBJECT_INNER_WORD
}
1102 [VIS_ACTION_TEXT_OBJECT_LONGWORD_OUTER
] = {
1103 "vis-textobject-bigword-outer",
1104 VIS_HELP("A WORD leading and trailing whitespace included")
1105 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_LONGWORD
}
1107 [VIS_ACTION_TEXT_OBJECT_LONGWORD_INNER
] = {
1108 "vis-textobject-bigword-inner",
1109 VIS_HELP("A WORD leading and trailing whitespace excluded")
1110 textobj
, { .i
= VIS_TEXTOBJECT_INNER_LONGWORD
}
1112 [VIS_ACTION_TEXT_OBJECT_SENTENCE
] = {
1113 "vis-textobject-sentence",
1114 VIS_HELP("A sentence")
1115 textobj
, { .i
= VIS_TEXTOBJECT_SENTENCE
}
1117 [VIS_ACTION_TEXT_OBJECT_PARAGRAPH
] = {
1118 "vis-textobject-paragraph",
1119 VIS_HELP("A paragraph")
1120 textobj
, { .i
= VIS_TEXTOBJECT_PARAGRAPH
}
1122 [VIS_ACTION_TEXT_OBJECT_PARAGRAPH_OUTER
] = {
1123 "vis-textobject-paragraph-outer",
1124 VIS_HELP("A paragraph (outer variant)")
1125 textobj
, { .i
= VIS_TEXTOBJECT_PARAGRAPH_OUTER
}
1127 [VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_OUTER
] = {
1128 "vis-textobject-square-bracket-outer",
1129 VIS_HELP("[] block (outer variant)")
1130 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_SQUARE_BRACKET
}
1132 [VIS_ACTION_TEXT_OBJECT_SQUARE_BRACKET_INNER
] = {
1133 "vis-textobject-square-bracket-inner",
1134 VIS_HELP("[] block (inner variant)")
1135 textobj
, { .i
= VIS_TEXTOBJECT_INNER_SQUARE_BRACKET
}
1137 [VIS_ACTION_TEXT_OBJECT_PARENTHESIS_OUTER
] = {
1138 "vis-textobject-parenthesis-outer",
1139 VIS_HELP("() block (outer variant)")
1140 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_PARENTHESIS
}
1142 [VIS_ACTION_TEXT_OBJECT_PARENTHESIS_INNER
] = {
1143 "vis-textobject-parenthesis-inner",
1144 VIS_HELP("() block (inner variant)")
1145 textobj
, { .i
= VIS_TEXTOBJECT_INNER_PARENTHESIS
}
1147 [VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_OUTER
] = {
1148 "vis-textobject-angle-bracket-outer",
1149 VIS_HELP("<> block (outer variant)")
1150 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_ANGLE_BRACKET
}
1152 [VIS_ACTION_TEXT_OBJECT_ANGLE_BRACKET_INNER
] = {
1153 "vis-textobject-angle-bracket-inner",
1154 VIS_HELP("<> block (inner variant)")
1155 textobj
, { .i
= VIS_TEXTOBJECT_INNER_ANGLE_BRACKET
}
1157 [VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_OUTER
] = {
1158 "vis-textobject-curly-bracket-outer",
1159 VIS_HELP("{} block (outer variant)")
1160 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_CURLY_BRACKET
}
1162 [VIS_ACTION_TEXT_OBJECT_CURLY_BRACKET_INNER
] = {
1163 "vis-textobject-curly-bracket-inner",
1164 VIS_HELP("{} block (inner variant)")
1165 textobj
, { .i
= VIS_TEXTOBJECT_INNER_CURLY_BRACKET
}
1167 [VIS_ACTION_TEXT_OBJECT_QUOTE_OUTER
] = {
1168 "vis-textobject-quote-outer",
1169 VIS_HELP("A quoted string, including the quotation marks")
1170 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_QUOTE
}
1172 [VIS_ACTION_TEXT_OBJECT_QUOTE_INNER
] = {
1173 "vis-textobject-quote-inner",
1174 VIS_HELP("A quoted string, excluding the quotation marks")
1175 textobj
, { .i
= VIS_TEXTOBJECT_INNER_QUOTE
}
1177 [VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_OUTER
] = {
1178 "vis-textobject-single-quote-outer",
1179 VIS_HELP("A single quoted string, including the quotation marks")
1180 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_SINGLE_QUOTE
}
1182 [VIS_ACTION_TEXT_OBJECT_SINGLE_QUOTE_INNER
] = {
1183 "vis-textobject-single-quote-inner",
1184 VIS_HELP("A single quoted string, excluding the quotation marks")
1185 textobj
, { .i
= VIS_TEXTOBJECT_INNER_SINGLE_QUOTE
}
1187 [VIS_ACTION_TEXT_OBJECT_BACKTICK_OUTER
] = {
1188 "vis-textobject-backtick-outer",
1189 VIS_HELP("A backtick delimited string (outer variant)")
1190 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_BACKTICK
}
1192 [VIS_ACTION_TEXT_OBJECT_BACKTICK_INNER
] = {
1193 "vis-textobject-backtick-inner",
1194 VIS_HELP("A backtick delimited string (inner variant)")
1195 textobj
, { .i
= VIS_TEXTOBJECT_INNER_BACKTICK
}
1197 [VIS_ACTION_TEXT_OBJECT_ENTIRE_OUTER
] = {
1198 "vis-textobject-entire-outer",
1199 VIS_HELP("The whole text content")
1200 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_ENTIRE
}
1202 [VIS_ACTION_TEXT_OBJECT_ENTIRE_INNER
] = {
1203 "vis-textobject-entire-inner",
1204 VIS_HELP("The whole text content, except for leading and trailing empty lines")
1205 textobj
, { .i
= VIS_TEXTOBJECT_INNER_ENTIRE
}
1207 [VIS_ACTION_TEXT_OBJECT_LINE_OUTER
] = {
1208 "vis-textobject-line-outer",
1209 VIS_HELP("The whole line")
1210 textobj
, { .i
= VIS_TEXTOBJECT_OUTER_LINE
}
1212 [VIS_ACTION_TEXT_OBJECT_LINE_INNER
] = {
1213 "vis-textobject-line-inner",
1214 VIS_HELP("The whole line, excluding leading and trailing whitespace")
1215 textobj
, { .i
= VIS_TEXTOBJECT_INNER_LINE
}
1217 [VIS_ACTION_TEXT_OBJECT_INDENTATION
] = {
1218 "vis-textobject-indentation",
1219 VIS_HELP("All adjacent lines with the same indentation level as the current one")
1220 textobj
, { .i
= VIS_TEXTOBJECT_INDENTATION
}
1222 [VIS_ACTION_TEXT_OBJECT_SEARCH_FORWARD
] = {
1223 "vis-textobject-search-forward",
1224 VIS_HELP("The next search match in forward direction")
1225 textobj
, { .i
= VIS_TEXTOBJECT_SEARCH_FORWARD
}
1227 [VIS_ACTION_TEXT_OBJECT_SEARCH_BACKWARD
] = {
1228 "vis-textobject-search-backward",
1229 VIS_HELP("The next search match in backward direction")
1230 textobj
, { .i
= VIS_TEXTOBJECT_SEARCH_BACKWARD
}
1232 [VIS_ACTION_MOTION_CHARWISE
] = {
1233 "vis-motion-charwise",
1234 VIS_HELP("Force motion to be charwise")
1235 motiontype
, { .i
= VIS_MOTIONTYPE_CHARWISE
}
1237 [VIS_ACTION_MOTION_LINEWISE
] = {
1238 "vis-motion-linewise",
1239 VIS_HELP("Force motion to be linewise")
1240 motiontype
, { .i
= VIS_MOTIONTYPE_LINEWISE
}
1242 [VIS_ACTION_UNICODE_INFO
] = {
1244 VIS_HELP("Show Unicode codepoint(s) of character under cursor")
1245 unicode_info
, { .i
= VIS_ACTION_UNICODE_INFO
}
1247 [VIS_ACTION_UTF8_INFO
] = {
1249 VIS_HELP("Show UTF-8 encoded codepoint(s) of character under cursor")
1250 unicode_info
, { .i
= VIS_ACTION_UTF8_INFO
}
1252 [VIS_ACTION_NOP
] = {
1254 VIS_HELP("Ignore key, do nothing")
1261 /** key bindings functions */
1263 static const char *nop(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1267 static const char *macro_record(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1268 if (!vis_macro_record_stop(vis
)) {
1271 const char *next
= vis_keys_next(vis
, keys
);
1272 if (next
- keys
> 1)
1274 enum VisRegister reg
= vis_register_from(vis
, keys
[0]);
1275 vis_macro_record(vis
, reg
);
1282 static const char *macro_replay(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1285 const char *next
= vis_keys_next(vis
, keys
);
1286 if (next
- keys
> 1)
1288 enum VisRegister reg
= vis_register_from(vis
, keys
[0]);
1289 vis_macro_replay(vis
, reg
);
1293 static const char *suspend(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1298 static const char *repeat(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1303 static const char *selections_new(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1304 View
*view
= vis_view(vis
);
1305 bool anchored
= view_selections_anchored(view_selections_primary_get(view
));
1306 VisCountIterator it
= vis_count_iterator_get(vis
, 1);
1307 while (vis_count_iterator_next(&it
)) {
1308 Selection
*sel
= NULL
;
1312 sel
= view_selections_primary_get(view
);
1315 sel
= view_selections(view
);
1318 for (Selection
*s
= view_selections(view
); s
; s
= view_selections_next(s
))
1326 size_t oldpos
= view_cursors_pos(sel
);
1328 view_line_down(sel
);
1329 else if (arg
->i
< 0)
1331 size_t newpos
= view_cursors_pos(sel
);
1332 view_cursors_to(sel
, oldpos
);
1333 Selection
*sel_new
= view_selections_new(view
, newpos
);
1336 sel_new
= view_selections_prev(sel
);
1337 else if (arg
->i
== +1)
1338 sel_new
= view_selections_next(sel
);
1341 view_selections_primary_set(sel_new
);
1342 view_selections_anchor(sel_new
, anchored
);
1345 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
1349 static const char *selections_align(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1350 View
*view
= vis_view(vis
);
1351 Text
*txt
= vis_text(vis
);
1352 int mincol
= INT_MAX
;
1353 for (Selection
*s
= view_selections(view
); s
; s
= view_selections_next(s
)) {
1354 int col
= view_cursors_cell_get(s
);
1355 if (col
>= 0 && col
< mincol
)
1358 for (Selection
*s
= view_selections(view
); s
; s
= view_selections_next(s
)) {
1359 if (view_cursors_cell_set(s
, mincol
) == -1) {
1360 size_t pos
= view_cursors_pos(s
);
1361 size_t col
= text_line_width_set(txt
, pos
, mincol
);
1362 view_cursors_to(s
, col
);
1368 static const char *selections_align_indent(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1369 View
*view
= vis_view(vis
);
1370 Text
*txt
= vis_text(vis
);
1371 bool left_align
= arg
->i
< 0;
1372 int columns
= view_selections_column_count(view
);
1374 for (int i
= 0; i
< columns
; i
++) {
1375 int mincol
= INT_MAX
, maxcol
= 0;
1376 for (Selection
*s
= view_selections_column(view
, i
); s
; s
= view_selections_column_next(s
, i
)) {
1377 Filerange sel
= view_selections_get(s
);
1378 size_t pos
= left_align
? sel
.start
: sel
.end
;
1379 int col
= text_line_width_get(txt
, pos
);
1386 size_t len
= maxcol
- mincol
;
1387 char *buf
= malloc(len
+1);
1390 memset(buf
, ' ', len
);
1392 for (Selection
*s
= view_selections_column(view
, i
); s
; s
= view_selections_column_next(s
, i
)) {
1393 Filerange sel
= view_selections_get(s
);
1394 size_t pos
= left_align
? sel
.start
: sel
.end
;
1395 size_t ipos
= sel
.start
;
1396 int col
= text_line_width_get(txt
, pos
);
1398 size_t off
= maxcol
- col
;
1400 text_insert(txt
, ipos
, buf
, off
);
1411 static const char *selections_clear(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1412 View
*view
= vis_view(vis
);
1413 if (view_selections_count(view
) > 1)
1414 view_selections_dispose_all(view
);
1416 view_selection_clear(view_selections_primary_get(view
));
1420 static const char *selections_match_word(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1421 Text
*txt
= vis_text(vis
);
1422 View
*view
= vis_view(vis
);
1423 for (Selection
*s
= view_selections(view
); s
; s
= view_selections_next(s
)) {
1424 Filerange word
= text_object_word(txt
, view_cursors_pos(s
));
1425 if (text_range_valid(&word
))
1426 view_selections_set(s
, &word
);
1428 vis_mode_switch(vis
, VIS_MODE_VISUAL
);
1432 static const char *selections_match_next(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1433 Text
*txt
= vis_text(vis
);
1434 View
*view
= vis_view(vis
);
1435 Selection
*s
= view_selections_primary_get(view
);
1436 Filerange sel
= view_selections_get(s
);
1437 if (!text_range_valid(&sel
))
1440 char *buf
= text_bytes_alloc0(txt
, sel
.start
, text_range_size(&sel
));
1443 Filerange word
= text_object_word_find_next(txt
, sel
.end
, buf
);
1444 if (text_range_valid(&word
)) {
1445 size_t pos
= text_char_prev(txt
, word
.end
);
1446 if ((s
= view_selections_new(view
, pos
))) {
1447 view_selections_set(s
, &word
);
1448 view_selections_anchor(s
, true);
1449 view_selections_primary_set(s
);
1454 sel
= view_selections_get(view_selections(view
));
1455 word
= text_object_word_find_prev(txt
, sel
.start
, buf
);
1456 if (!text_range_valid(&word
))
1458 size_t pos
= text_char_prev(txt
, word
.end
);
1459 if ((s
= view_selections_new(view
, pos
))) {
1460 view_selections_set(s
, &word
);
1461 view_selections_anchor(s
, true);
1462 view_selections_primary_set(s
);
1470 static const char *selections_match_skip(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1471 View
*view
= vis_view(vis
);
1472 Selection
*sel
= view_selections_primary_get(view
);
1473 keys
= selections_match_next(vis
, keys
, arg
);
1474 if (sel
!= view_selections_primary_get(view
))
1475 view_selections_dispose(sel
);
1479 static const char *selections_remove(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1480 View
*view
= vis_view(vis
);
1481 view_selections_dispose(view_selections_primary_get(view
));
1482 view_cursor_to(view
, view_cursor_get(view
));
1486 static const char *selections_remove_column(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1487 View
*view
= vis_view(vis
);
1488 int max
= view_selections_column_count(view
);
1489 int column
= vis_count_get_default(vis
, arg
->i
) - 1;
1492 if (view_selections_count(view
) == 1) {
1493 vis_keys_feed(vis
, "<Escape>");
1497 for (Selection
*s
= view_selections_column(view
, column
), *next
; s
; s
= next
) {
1498 next
= view_selections_column_next(s
, column
);
1499 view_selections_dispose(s
);
1502 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
1506 static const char *selections_remove_column_except(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1507 View
*view
= vis_view(vis
);
1508 int max
= view_selections_column_count(view
);
1509 int column
= vis_count_get_default(vis
, arg
->i
) - 1;
1512 if (view_selections_count(view
) == 1) {
1517 Selection
*sel
= view_selections(view
);
1518 Selection
*col
= view_selections_column(view
, column
);
1519 for (Selection
*next
; sel
; sel
= next
) {
1520 next
= view_selections_next(sel
);
1522 col
= view_selections_column_next(col
, column
);
1524 view_selections_dispose(sel
);
1527 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
1531 static const char *selections_navigate(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1532 View
*view
= vis_view(vis
);
1533 if (view_selections_count(view
) == 1)
1534 return wscroll(vis
, keys
, arg
);
1535 Selection
*s
= view_selections_primary_get(view
);
1536 VisCountIterator it
= vis_count_iterator_get(vis
, 1);
1537 while (vis_count_iterator_next(&it
)) {
1539 s
= view_selections_next(s
);
1541 s
= view_selections(view
);
1543 s
= view_selections_prev(s
);
1545 s
= view_selections(view
);
1546 for (Selection
*n
= s
; n
; n
= view_selections_next(n
))
1551 view_selections_primary_set(s
);
1552 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
1556 static const char *selections_rotate(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1565 Text
*txt
= vis_text(vis
);
1566 View
*view
= vis_view(vis
);
1567 int columns
= view_selections_column_count(view
);
1568 int selections
= columns
== 1 ? view_selections_count(view
) : columns
;
1569 int count
= vis_count_get_default(vis
, 1);
1570 array_init_sized(&arr
, sizeof(Rotate
));
1571 if (!array_reserve(&arr
, selections
))
1575 for (Selection
*s
= view_selections(view
), *next
; s
; s
= next
) {
1576 next
= view_selections_next(s
);
1577 size_t line_next
= 0;
1579 Filerange sel
= view_selections_get(s
);
1582 rot
.len
= text_range_size(&sel
);
1583 if ((rot
.data
= malloc(rot
.len
)))
1584 rot
.len
= text_bytes_get(txt
, sel
.start
, rot
.len
, rot
.data
);
1587 array_add(&arr
, &rot
);
1590 line
= text_lineno_by_pos(txt
, view_cursors_pos(s
));
1592 line_next
= text_lineno_by_pos(txt
, view_cursors_pos(next
));
1593 if (!next
|| (columns
> 1 && line
!= line_next
)) {
1594 size_t len
= array_length(&arr
);
1595 size_t off
= arg
->i
> 0 ? count
% len
: len
- (count
% len
);
1596 for (size_t i
= 0; i
< len
; i
++) {
1597 size_t j
= (i
+ off
) % len
;
1598 Rotate
*oldrot
= array_get(&arr
, i
);
1599 Rotate
*newrot
= array_get(&arr
, j
);
1600 if (!oldrot
|| !newrot
|| oldrot
== newrot
)
1602 Filerange newsel
= view_selections_get(newrot
->sel
);
1603 if (!text_range_valid(&newsel
))
1605 if (!text_delete_range(txt
, &newsel
))
1607 if (!text_insert(txt
, newsel
.start
, oldrot
->data
, oldrot
->len
))
1609 newsel
.end
= newsel
.start
+ oldrot
->len
;
1610 view_selections_set(newrot
->sel
, &newsel
);
1618 array_release(&arr
);
1619 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
1623 static const char *selections_trim(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1624 Text
*txt
= vis_text(vis
);
1625 View
*view
= vis_view(vis
);
1626 for (Selection
*s
= view_selections(view
), *next
; s
; s
= next
) {
1627 next
= view_selections_next(s
);
1628 Filerange sel
= view_selections_get(s
);
1629 if (!text_range_valid(&sel
))
1631 for (char b
; sel
.start
< sel
.end
&& text_byte_get(txt
, sel
.end
-1, &b
)
1632 && isspace((unsigned char)b
); sel
.end
--);
1633 for (char b
; sel
.start
<= sel
.end
&& text_byte_get(txt
, sel
.start
, &b
)
1634 && isspace((unsigned char)b
); sel
.start
++);
1635 if (sel
.start
< sel
.end
) {
1636 view_selections_set(s
, &sel
);
1637 } else if (!view_selections_dispose(s
)) {
1638 vis_mode_switch(vis
, VIS_MODE_NORMAL
);
1644 static void selections_set(Vis
*vis
, View
*view
, Array
*sel
) {
1645 enum VisMode mode
= vis_mode_get(vis
);
1646 bool anchored
= mode
== VIS_MODE_VISUAL
|| mode
== VIS_MODE_VISUAL_LINE
;
1647 view_selections_set_all(view
, sel
, anchored
);
1649 view_selections_clear_all(view
);
1652 static const char *selections_save(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1653 Win
*win
= vis_window(vis
);
1654 View
*view
= vis_view(vis
);
1655 enum VisMark mark
= vis_mark_used(vis
);
1656 Array sel
= view_selections_get_all(view
);
1657 vis_mark_set(win
, mark
, &sel
);
1658 array_release(&sel
);
1663 static const char *selections_restore(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1664 Win
*win
= vis_window(vis
);
1665 View
*view
= vis_view(vis
);
1666 enum VisMark mark
= vis_mark_used(vis
);
1667 Array sel
= vis_mark_get(win
, mark
);
1668 selections_set(vis
, view
, &sel
);
1669 array_release(&sel
);
1674 static const char *selections_union(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1675 Win
*win
= vis_window(vis
);
1676 View
*view
= vis_view(vis
);
1677 enum VisMark mark
= vis_mark_used(vis
);
1678 Array a
= vis_mark_get(win
, mark
);
1679 Array b
= view_selections_get_all(view
);
1681 array_init_from(&sel
, &a
);
1683 size_t i
= 0, j
= 0;
1684 Filerange
*r1
= array_get(&a
, i
), *r2
= array_get(&b
, j
), cur
= text_range_empty();
1686 if (r1
&& text_range_overlap(r1
, &cur
)) {
1687 cur
= text_range_union(r1
, &cur
);
1688 r1
= array_get(&a
, ++i
);
1689 } else if (r2
&& text_range_overlap(r2
, &cur
)) {
1690 cur
= text_range_union(r2
, &cur
);
1691 r2
= array_get(&b
, ++j
);
1693 if (text_range_valid(&cur
))
1694 array_add(&sel
, &cur
);
1697 r2
= array_get(&b
, ++j
);
1700 r1
= array_get(&a
, ++i
);
1702 if (r1
->start
< r2
->start
) {
1704 r1
= array_get(&a
, ++i
);
1707 r2
= array_get(&b
, ++j
);
1713 if (text_range_valid(&cur
))
1714 array_add(&sel
, &cur
);
1716 selections_set(vis
, view
, &sel
);
1721 array_release(&sel
);
1726 static void intersect(Array
*ret
, Array
*a
, Array
*b
) {
1727 size_t i
= 0, j
= 0;
1728 Filerange
*r1
= array_get(a
, i
), *r2
= array_get(b
, j
);
1730 if (text_range_overlap(r1
, r2
)) {
1731 Filerange
new = text_range_intersect(r1
, r2
);
1732 array_add(ret
, &new);
1734 if (r1
->end
< r2
->end
)
1735 r1
= array_get(a
, ++i
);
1737 r2
= array_get(b
, ++j
);
1741 static const char *selections_intersect(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1742 Win
*win
= vis_window(vis
);
1743 View
*view
= vis_view(vis
);
1744 enum VisMark mark
= vis_mark_used(vis
);
1745 Array a
= vis_mark_get(win
, mark
);
1746 Array b
= view_selections_get_all(view
);
1748 array_init_from(&sel
, &a
);
1750 intersect(&sel
, &a
, &b
);
1751 selections_set(vis
, view
, &sel
);
1756 array_release(&sel
);
1761 static void complement(Array
*ret
, Array
*a
, Filerange
*universe
) {
1762 size_t pos
= universe
->start
;
1763 for (size_t i
= 0, len
= array_length(a
); i
< len
; i
++) {
1764 Filerange
*r
= array_get(a
, i
);
1765 if (pos
< r
->start
) {
1766 Filerange
new = text_range_new(pos
, r
->start
);
1767 array_add(ret
, &new);
1771 if (pos
< universe
->end
) {
1772 Filerange
new = text_range_new(pos
, universe
->end
);
1773 array_add(ret
, &new);
1777 static const char *selections_complement(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1778 Text
*txt
= vis_text(vis
);
1779 View
*view
= vis_view(vis
);
1780 Filerange universe
= text_object_entire(txt
, 0);
1781 Array a
= view_selections_get_all(view
);
1783 array_init_from(&sel
, &a
);
1785 complement(&sel
, &a
, &universe
);
1787 selections_set(vis
, view
, &sel
);
1789 array_release(&sel
);
1793 static const char *selections_minus(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1794 Text
*txt
= vis_text(vis
);
1795 Win
*win
= vis_window(vis
);
1796 View
*view
= vis_view(vis
);
1797 enum VisMark mark
= vis_mark_used(vis
);
1798 Array a
= view_selections_get_all(view
);
1799 Array b
= vis_mark_get(win
, mark
);
1801 array_init_from(&sel
, &a
);
1803 array_init_from(&b_complement
, &b
);
1805 Filerange universe
= text_object_entire(txt
, 0);
1806 complement(&b_complement
, &b
, &universe
);
1807 intersect(&sel
, &a
, &b_complement
);
1809 selections_set(vis
, view
, &sel
);
1814 array_release(&b_complement
);
1815 array_release(&sel
);
1820 static Filerange
combine_union(const Filerange
*r1
, const Filerange
*r2
) {
1825 return text_range_union(r1
, r2
);
1828 static Filerange
combine_intersect(const Filerange
*r1
, const Filerange
*r2
) {
1830 return text_range_empty();
1831 return text_range_intersect(r1
, r2
);
1834 static Filerange
combine_longer(const Filerange
*r1
, const Filerange
*r2
) {
1839 size_t l1
= text_range_size(r1
);
1840 size_t l2
= text_range_size(r2
);
1841 return l1
< l2
? *r2
: *r1
;
1844 static Filerange
combine_shorter(const Filerange
*r1
, const Filerange
*r2
) {
1849 size_t l1
= text_range_size(r1
);
1850 size_t l2
= text_range_size(r2
);
1851 return l1
< l2
? *r1
: *r2
;
1854 static Filerange
combine_leftmost(const Filerange
*r1
, const Filerange
*r2
) {
1859 return r1
->start
< r2
->start
|| (r1
->start
== r2
->start
&& r1
->end
< r2
->end
) ? *r1
: *r2
;
1862 static Filerange
combine_rightmost(const Filerange
*r1
, const Filerange
*r2
) {
1867 return r1
->start
< r2
->start
|| (r1
->start
== r2
->start
&& r1
->end
< r2
->end
) ? *r2
: *r1
;
1870 static const char *selections_combine(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1871 Win
*win
= vis_window(vis
);
1872 View
*view
= vis_view(vis
);
1873 enum VisMark mark
= vis_mark_used(vis
);
1874 Array a
= view_selections_get_all(view
);
1875 Array b
= vis_mark_get(win
, mark
);
1877 array_init_from(&sel
, &a
);
1879 Filerange
*r1
= array_get(&a
, 0), *r2
= array_get(&b
, 0);
1880 for (size_t i
= 0, j
= 0; r1
|| r2
; r1
= array_get(&a
, ++i
), r2
= array_get(&b
, ++j
)) {
1881 Filerange
new = arg
->combine(r1
, r2
);
1882 if (text_range_valid(&new))
1883 array_add(&sel
, &new);
1886 vis_mark_normalize(&sel
);
1887 selections_set(vis
, view
, &sel
);
1892 array_release(&sel
);
1897 static const char *replace(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1899 vis_keymap_disable(vis
);
1903 const char *next
= vis_keys_next(vis
, keys
);
1907 char replacement
[UTFmax
+1];
1908 if (!vis_keys_utf8(vis
, keys
, replacement
))
1911 if (replacement
[0] == 0x1b) /* <Escape> */
1914 vis_operator(vis
, VIS_OP_REPLACE
, replacement
);
1915 if (vis_mode_get(vis
) == VIS_MODE_OPERATOR_PENDING
)
1916 vis_motion(vis
, VIS_MOVE_CHAR_NEXT
);
1920 static const char *count(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1921 int digit
= keys
[-1] - '0';
1922 int count
= vis_count_get_default(vis
, 0);
1923 if (0 <= digit
&& digit
<= 9) {
1924 if (digit
== 0 && count
== 0)
1925 vis_motion(vis
, VIS_MOVE_LINE_BEGIN
);
1927 vis_count_set(vis
, count
* 10 + digit
);
1932 static const char *gotoline(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1933 if (vis_count_get(vis
) != VIS_COUNT_UNKNOWN
)
1934 vis_motion(vis
, VIS_MOVE_LINE
);
1935 else if (arg
->i
< 0)
1936 vis_motion(vis
, VIS_MOVE_FILE_BEGIN
);
1938 vis_motion(vis
, VIS_MOVE_FILE_END
);
1942 static const char *motiontype(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1943 vis_motion_type(vis
, arg
->i
);
1947 static const char *operator(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1948 vis_operator(vis
, arg
->i
);
1952 static const char *movement_key(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1954 vis_keymap_disable(vis
);
1958 const char *next
= vis_keys_next(vis
, keys
);
1961 char utf8
[UTFmax
+1];
1962 if (vis_keys_utf8(vis
, keys
, utf8
))
1963 vis_motion(vis
, arg
->i
, utf8
);
1967 static const char *movement(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1968 vis_motion(vis
, arg
->i
);
1972 static const char *textobj(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1973 vis_textobject(vis
, arg
->i
);
1977 static const char *selection_end(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1978 for (Selection
*s
= view_selections(vis_view(vis
)); s
; s
= view_selections_next(s
))
1979 view_selections_flip(s
);
1983 static const char *reg(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1986 const char *next
= vis_keys_next(vis
, keys
);
1987 if (next
- keys
> 1)
1989 enum VisRegister reg
= vis_register_from(vis
, keys
[0]);
1990 vis_register(vis
, reg
);
1994 static const char *mark(Vis
*vis
, const char *keys
, const Arg
*arg
) {
1997 const char *next
= vis_keys_next(vis
, keys
);
1998 if (next
- keys
> 1)
2000 enum VisMark mark
= vis_mark_from(vis
, keys
[0]);
2001 vis_mark(vis
, mark
);
2005 static const char *undo(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2006 size_t pos
= text_undo(vis_text(vis
));
2008 View
*view
= vis_view(vis
);
2009 if (view_selections_count(view
) == 1)
2010 view_cursor_to(view
, pos
);
2011 /* redraw all windows in case some display the same file */
2017 static const char *redo(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2018 size_t pos
= text_redo(vis_text(vis
));
2020 View
*view
= vis_view(vis
);
2021 if (view_selections_count(view
) == 1)
2022 view_cursor_to(view
, pos
);
2023 /* redraw all windows in case some display the same file */
2029 static const char *earlier(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2031 VisCountIterator it
= vis_count_iterator_get(vis
, 1);
2032 while (vis_count_iterator_next(&it
))
2033 pos
= text_earlier(vis_text(vis
));
2035 view_cursor_to(vis_view(vis
), pos
);
2036 /* redraw all windows in case some display the same file */
2042 static const char *later(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2044 VisCountIterator it
= vis_count_iterator_get(vis
, 1);
2045 while (vis_count_iterator_next(&it
))
2046 pos
= text_later(vis_text(vis
));
2048 view_cursor_to(vis_view(vis
), pos
);
2049 /* redraw all windows in case some display the same file */
2055 static const char *delete(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2056 vis_operator(vis
, VIS_OP_DELETE
);
2057 vis_motion(vis
, arg
->i
);
2061 static const char *insert_register(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2064 const char *next
= vis_keys_next(vis
, keys
);
2065 if (next
- keys
> 1)
2067 enum VisRegister reg
= vis_register_from(vis
, keys
[0]);
2068 if (reg
!= VIS_REG_INVALID
) {
2069 vis_register(vis
, reg
);
2070 vis_operator(vis
, VIS_OP_PUT_BEFORE_END
);
2075 static const char *prompt_show(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2076 vis_prompt_show(vis
, arg
->s
);
2080 static const char *insert_verbatim(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2082 char buf
[4], type
= keys
[0];
2083 const char *data
= NULL
;
2084 int len
= 0, count
= 0, base
= 0;
2106 if ('0' <= type
&& type
<= '9') {
2115 for (keys
++; keys
[0] && count
> 0; keys
++, count
--) {
2117 if (base
== 8 && '0' <= keys
[0] && keys
[0] <= '7') {
2119 } else if ((base
== 10 || base
== 16) && '0' <= keys
[0] && keys
[0] <= '9') {
2121 } else if (base
== 16 && 'a' <= keys
[0] && keys
[0] <= 'f') {
2122 v
= 10 + keys
[0] - 'a';
2123 } else if (base
== 16 && 'A' <= keys
[0] && keys
[0] <= 'F') {
2124 v
= 10 + keys
[0] - 'A';
2129 rune
= rune
* base
+ v
;
2134 if (type
== 'u' || type
== 'U') {
2135 len
= runetochar(buf
, &rune
);
2143 const char *next
= vis_keys_next(vis
, keys
);
2146 if ((rune
= vis_keys_codepoint(vis
, keys
)) != (Rune
)-1) {
2147 len
= runetochar(buf
, &rune
);
2150 vis_info_show(vis
, "Unknown key");
2156 vis_insert_key(vis
, data
, len
);
2160 static const char *wscroll(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2161 View
*view
= vis_view(vis
);
2162 int count
= vis_count_get(vis
);
2165 view_scroll_page_up(view
);
2168 view_scroll_page_down(view
);
2171 view_scroll_halfpage_up(view
);
2174 view_scroll_halfpage_down(view
);
2177 if (count
== VIS_COUNT_UNKNOWN
)
2178 count
= arg
->i
< 0 ? -arg
->i
: arg
->i
;
2180 view_scroll_up(view
, count
);
2182 view_scroll_down(view
, count
);
2185 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
2189 static const char *wslide(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2190 View
*view
= vis_view(vis
);
2191 int count
= vis_count_get(vis
);
2192 if (count
== VIS_COUNT_UNKNOWN
)
2193 count
= arg
->i
< 0 ? -arg
->i
: arg
->i
;
2195 view_slide_down(view
, count
);
2197 view_slide_up(view
, count
);
2198 vis_count_set(vis
, VIS_COUNT_UNKNOWN
);
2202 static const char *call(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2207 static const char *window(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2208 arg
->w(vis_view(vis
));
2212 static const char *openline(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2213 vis_operator(vis
, VIS_OP_MODESWITCH
, VIS_MODE_INSERT
);
2215 vis_motion(vis
, VIS_MOVE_LINE_END
);
2216 vis_keys_feed(vis
, "<Enter>");
2218 if (vis_get_autoindent(vis
)) {
2219 vis_motion(vis
, VIS_MOVE_LINE_START
);
2220 vis_keys_feed(vis
, "<vis-motion-line-start>");
2222 vis_motion(vis
, VIS_MOVE_LINE_BEGIN
);
2223 vis_keys_feed(vis
, "<vis-motion-line-begin>");
2225 vis_keys_feed(vis
, "<Enter><Up>");
2230 static const char *join(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2231 bool normal
= (vis_mode_get(vis
) == VIS_MODE_NORMAL
);
2232 vis_operator(vis
, VIS_OP_JOIN
, arg
->s
);
2234 int count
= vis_count_get_default(vis
, 0);
2236 vis_count_set(vis
, count
-1);
2237 vis_motion(vis
, VIS_MOVE_LINE_NEXT
);
2242 static const char *switchmode(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2243 vis_mode_switch(vis
, arg
->i
);
2247 static const char *insertmode(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2248 vis_operator(vis
, VIS_OP_MODESWITCH
, VIS_MODE_INSERT
);
2249 vis_motion(vis
, arg
->i
);
2253 static const char *replacemode(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2254 vis_operator(vis
, VIS_OP_MODESWITCH
, VIS_MODE_REPLACE
);
2255 vis_motion(vis
, arg
->i
);
2259 static const char *unicode_info(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2260 View
*view
= vis_view(vis
);
2261 Text
*txt
= vis_text(vis
);
2262 size_t start
= view_cursor_get(view
);
2263 size_t end
= text_char_next(txt
, start
);
2264 char *grapheme
= text_bytes_alloc0(txt
, start
, end
-start
), *codepoint
= grapheme
;
2269 mbstate_t ps
= { 0 };
2270 Iterator it
= text_iterator_get(txt
, start
);
2271 for (size_t pos
= start
; it
.pos
< end
; pos
= it
.pos
) {
2272 if (!text_iterator_codepoint_next(&it
, NULL
)) {
2273 vis_info_show(vis
, "Failed to parse code point");
2276 size_t len
= it
.pos
- pos
;
2277 wchar_t wc
= 0xFFFD;
2278 size_t res
= mbrtowc(&wc
, codepoint
, len
, &ps
);
2279 bool combining
= false;
2280 if (res
!= (size_t)-1 && res
!= (size_t)-2)
2281 combining
= (wc
!= L
'\0' && wcwidth(wc
) == 0);
2282 unsigned char ch
= *codepoint
;
2283 if (ch
< 128 && !isprint(ch
))
2284 buffer_appendf(&info
, "<^%c> ", ch
== 127 ? '?' : ch
+ 64);
2286 buffer_appendf(&info
, "<%s%.*s> ", combining
? " " : "", (int)len
, codepoint
);
2287 if (arg
->i
== VIS_ACTION_UNICODE_INFO
) {
2288 buffer_appendf(&info
, "U+%04"PRIX32
" ", (uint32_t)wc
);
2290 for (size_t i
= 0; i
< len
; i
++)
2291 buffer_appendf(&info
, "%02x ", (uint8_t)codepoint
[i
]);
2295 vis_info_show(vis
, "%s", buffer_content0(&info
));
2298 buffer_release(&info
);
2302 static const char *percent(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2303 if (vis_count_get(vis
) == VIS_COUNT_UNKNOWN
)
2304 vis_motion(vis
, VIS_MOVE_BRACKET_MATCH
);
2306 vis_motion(vis
, VIS_MOVE_PERCENT
);
2310 static const char *jumplist(Vis
*vis
, const char *keys
, const Arg
*arg
) {
2312 vis_jumplist_prev(vis
);
2313 else if (arg
->i
> 0)
2314 vis_jumplist_next(vis
);
2316 vis_jumplist_save(vis
);
2322 static void signal_handler(int signum
, siginfo_t
*siginfo
, void *context
) {
2323 vis_signal_handler(vis
, signum
, siginfo
, context
);
2326 int main(int argc
, char *argv
[]) {
2329 .init
= vis_lua_init
,
2330 .start
= vis_lua_start
,
2331 .quit
= vis_lua_quit
,
2332 .mode_insert_input
= vis_lua_mode_insert_input
,
2333 .mode_replace_input
= vis_lua_mode_replace_input
,
2334 .file_open
= vis_lua_file_open
,
2335 .file_save_pre
= vis_lua_file_save_pre
,
2336 .file_save_post
= vis_lua_file_save_post
,
2337 .file_close
= vis_lua_file_close
,
2338 .win_open
= vis_lua_win_open
,
2339 .win_close
= vis_lua_win_close
,
2340 .win_highlight
= vis_lua_win_highlight
,
2341 .win_status
= vis_lua_win_status
,
2344 vis
= vis_new(ui_term_new(), &event
);
2346 return EXIT_FAILURE
;
2348 for (int i
= 0; i
< LENGTH(vis_action
); i
++) {
2349 const KeyAction
*action
= &vis_action
[i
];
2350 if (!vis_action_register(vis
, action
))
2351 vis_die(vis
, "Could not register action: %s\n", action
->name
);
2354 for (int i
= 0; i
< LENGTH(default_bindings
); i
++) {
2355 for (const KeyBinding
**binding
= default_bindings
[i
]; binding
&& *binding
; binding
++) {
2356 for (const KeyBinding
*kb
= *binding
; kb
->key
; kb
++) {
2357 vis_mode_map(vis
, i
, false, kb
->key
, kb
);
2362 for (const char **k
= keymaps
; k
[0]; k
+= 2)
2363 vis_keymap_add(vis
, k
[0], k
[1]);
2365 /* install signal handlers etc. */
2366 struct sigaction sa
;
2367 memset(&sa
, 0, sizeof sa
);
2368 sigfillset(&sa
.sa_mask
);
2369 sa
.sa_flags
= SA_SIGINFO
;
2370 sa
.sa_sigaction
= signal_handler
;
2371 if (sigaction(SIGBUS
, &sa
, NULL
) == -1 ||
2372 sigaction(SIGINT
, &sa
, NULL
) == -1 ||
2373 sigaction(SIGCONT
, &sa
, NULL
) == -1 ||
2374 sigaction(SIGWINCH
, &sa
, NULL
) == -1 ||
2375 sigaction(SIGTERM
, &sa
, NULL
) == -1 ||
2376 sigaction(SIGHUP
, &sa
, NULL
) == -1) {
2377 vis_die(vis
, "Failed to set signal handler: %s\n", strerror(errno
));
2380 sa
.sa_handler
= SIG_IGN
;
2381 if (sigaction(SIGPIPE
, &sa
, NULL
) == -1 || sigaction(SIGQUIT
, &sa
, NULL
) == -1)
2382 vis_die(vis
, "Failed to ignore signals\n");
2385 sigemptyset(&blockset
);
2386 sigaddset(&blockset
, SIGBUS
);
2387 sigaddset(&blockset
, SIGCONT
);
2388 sigaddset(&blockset
, SIGWINCH
);
2389 sigaddset(&blockset
, SIGTERM
);
2390 sigaddset(&blockset
, SIGHUP
);
2391 if (sigprocmask(SIG_BLOCK
, &blockset
, NULL
) == -1)
2392 vis_die(vis
, "Failed to block signals\n");
2394 for (int i
= 1; i
< argc
; i
++) {
2395 if (argv
[i
][0] != '-') {
2397 } else if (strcmp(argv
[i
], "-") == 0) {
2399 } else if (strcmp(argv
[i
], "--") == 0) {
2401 } else if (strcmp(argv
[i
], "-v") == 0) {
2402 printf("vis %s%s%s%s%s%s%s\n", VERSION
,
2403 CONFIG_CURSES
? " +curses" : "",
2404 CONFIG_LUA
? " +lua" : "",
2405 CONFIG_LPEG
? " +lpeg" : "",
2406 CONFIG_TRE
? " +tre" : "",
2407 CONFIG_ACL
? " +acl" : "",
2408 CONFIG_SELINUX
? " +selinux" : "");
2411 fprintf(stderr
, "Unknown command option: %s\n", argv
[i
]);
2417 bool end_of_options
= false, win_created
= false;
2419 for (int i
= 1; i
< argc
; i
++) {
2420 if (argv
[i
][0] == '-' && !end_of_options
) {
2421 if (strcmp(argv
[i
], "-") == 0) {
2422 if (!vis_window_new_fd(vis
, STDOUT_FILENO
))
2423 vis_die(vis
, "Can not create empty buffer\n");
2426 Text
*txt
= vis_text(vis
);
2427 while ((len
= read(STDIN_FILENO
, buf
, sizeof buf
)) > 0)
2428 text_insert(txt
, text_size(txt
), buf
, len
);
2430 vis_die(vis
, "Can not read from stdin\n");
2432 int fd
= open("/dev/tty", O_RDWR
);
2434 vis_die(vis
, "Can not reopen stdin\n");
2435 dup2(fd
, STDIN_FILENO
);
2437 } else if (strcmp(argv
[i
], "--") == 0) {
2438 end_of_options
= true;
2441 } else if (argv
[i
][0] == '+' && !end_of_options
) {
2442 cmd
= argv
[i
] + (argv
[i
][1] == '/' || argv
[i
][1] == '?');
2444 } else if (!vis_window_new(vis
, argv
[i
])) {
2445 vis_die(vis
, "Can not load `%s': %s\n", argv
[i
], strerror(errno
));
2449 vis_prompt_cmd(vis
, cmd
);
2454 if (!vis_window(vis
) && !win_created
) {
2455 if (!vis_window_new(vis
, NULL
))
2456 vis_die(vis
, "Can not create empty buffer\n");
2458 vis_prompt_cmd(vis
, cmd
);
2461 int status
= vis_run(vis
);