vis: make paragraph textobjects linewise
[vis/gkirilov.git] / vis-text-objects.c
blob8f75c709fc79b49426bbac1a32d686877e7ea802
1 #include "vis-core.h"
2 #include "text-objects.h"
3 #include "util.h"
5 int vis_textobject_register(Vis *vis, int type, void *data, VisTextObjectFunction *textobject) {
7 TextObject *obj = calloc(1, sizeof *obj);
8 if (!obj)
9 return -1;
11 obj->user = textobject;
12 obj->type = type;
13 obj->data = data;
15 if (array_add_ptr(&vis->textobjects, obj))
16 return LENGTH(vis_textobjects) + array_length(&vis->textobjects) - 1;
17 free(obj);
18 return -1;
21 bool vis_textobject(Vis *vis, enum VisTextObject id) {
22 if (id < LENGTH(vis_textobjects))
23 vis->action.textobj = &vis_textobjects[id];
24 else
25 vis->action.textobj = array_get_ptr(&vis->textobjects, id - LENGTH(vis_textobjects));
26 if (!vis->action.textobj)
27 return false;
28 vis_do(vis);
29 return true;
32 static Filerange search_forward(Vis *vis, Text *txt, size_t pos) {
33 Filerange range = text_range_empty();
34 Regex *regex = vis_regex(vis, NULL, 0);
35 if (regex)
36 range = text_object_search_forward(txt, pos, regex);
37 return range;
40 static Filerange search_backward(Vis *vis, Text *txt, size_t pos) {
41 Filerange range = text_range_empty();
42 Regex *regex = vis_regex(vis, NULL, 0);
43 if (regex)
44 range = text_object_search_backward(txt, pos, regex);
45 return range;
48 static Filerange object_unpaired(Text *txt, size_t pos, char obj) {
49 char c;
50 bool before = false;
51 Iterator it = text_iterator_get(txt, pos), rit = it;
53 while (text_iterator_byte_get(&rit, &c) && c != '\n') {
54 if (c == obj) {
55 before = true;
56 break;
58 text_iterator_byte_prev(&rit, NULL);
61 /* if there is no previous occurrence on the same line, advance starting position */
62 if (!before) {
63 while (text_iterator_byte_get(&it, &c) && c != '\n') {
64 if (c == obj) {
65 pos = it.pos;
66 break;
68 text_iterator_byte_next(&it, NULL);
72 switch (obj) {
73 case '"':
74 return text_object_quote(txt, pos);
75 case '\'':
76 return text_object_single_quote(txt, pos);
77 case '`':
78 return text_object_backtick(txt, pos);
79 default:
80 return text_range_empty();
84 static Filerange object_quote(Text *txt, size_t pos) {
85 return object_unpaired(txt, pos, '"');
88 static Filerange object_single_quote(Text *txt, size_t pos) {
89 return object_unpaired(txt, pos, '\'');
92 static Filerange object_backtick(Text *txt, size_t pos) {
93 return object_unpaired(txt, pos, '`');
96 const TextObject vis_textobjects[] = {
97 [VIS_TEXTOBJECT_INNER_WORD] = {
98 .txt = text_object_word,
100 [VIS_TEXTOBJECT_OUTER_WORD] = {
101 .txt = text_object_word_outer,
103 [VIS_TEXTOBJECT_INNER_LONGWORD] = {
104 .txt = text_object_longword,
106 [VIS_TEXTOBJECT_OUTER_LONGWORD] = {
107 .txt = text_object_longword_outer,
109 [VIS_TEXTOBJECT_SENTENCE] = {
110 .txt = text_object_sentence,
112 [VIS_TEXTOBJECT_PARAGRAPH] = {
113 .txt = text_object_paragraph,
114 .type = TEXTOBJECT_LINEWISE,
116 [VIS_TEXTOBJECT_PARAGRAPH_OUTER] = {
117 .txt = text_object_paragraph_outer,
118 .type = TEXTOBJECT_LINEWISE,
120 [VIS_TEXTOBJECT_OUTER_SQUARE_BRACKET] = {
121 .txt = text_object_square_bracket,
122 .type = TEXTOBJECT_DELIMITED_OUTER,
124 [VIS_TEXTOBJECT_INNER_SQUARE_BRACKET] = {
125 .txt = text_object_square_bracket,
126 .type = TEXTOBJECT_DELIMITED_INNER,
128 [VIS_TEXTOBJECT_OUTER_CURLY_BRACKET] = {
129 .txt = text_object_curly_bracket,
130 .type = TEXTOBJECT_DELIMITED_OUTER,
132 [VIS_TEXTOBJECT_INNER_CURLY_BRACKET] = {
133 .txt = text_object_curly_bracket,
134 .type = TEXTOBJECT_DELIMITED_INNER,
136 [VIS_TEXTOBJECT_OUTER_ANGLE_BRACKET] = {
137 .txt = text_object_angle_bracket,
138 .type = TEXTOBJECT_DELIMITED_OUTER,
140 [VIS_TEXTOBJECT_INNER_ANGLE_BRACKET] = {
141 .txt = text_object_angle_bracket,
142 .type = TEXTOBJECT_DELIMITED_INNER,
144 [VIS_TEXTOBJECT_OUTER_PARENTHESIS] = {
145 .txt = text_object_parenthesis,
146 .type = TEXTOBJECT_DELIMITED_OUTER,
148 [VIS_TEXTOBJECT_INNER_PARENTHESIS] = {
149 .txt = text_object_parenthesis,
150 .type = TEXTOBJECT_DELIMITED_INNER,
152 [VIS_TEXTOBJECT_OUTER_QUOTE] = {
153 .txt = object_quote,
154 .type = TEXTOBJECT_DELIMITED_OUTER,
156 [VIS_TEXTOBJECT_INNER_QUOTE] = {
157 .txt = object_quote,
158 .type = TEXTOBJECT_DELIMITED_INNER,
160 [VIS_TEXTOBJECT_OUTER_SINGLE_QUOTE] = {
161 .txt = object_single_quote,
162 .type = TEXTOBJECT_DELIMITED_OUTER,
164 [VIS_TEXTOBJECT_INNER_SINGLE_QUOTE] = {
165 .txt = object_single_quote,
166 .type = TEXTOBJECT_DELIMITED_INNER,
168 [VIS_TEXTOBJECT_OUTER_BACKTICK] = {
169 .txt = object_backtick,
170 .type = TEXTOBJECT_DELIMITED_OUTER,
172 [VIS_TEXTOBJECT_INNER_BACKTICK] = {
173 .txt = object_backtick,
174 .type = TEXTOBJECT_DELIMITED_INNER,
176 [VIS_TEXTOBJECT_OUTER_LINE] = {
177 .txt = text_object_line,
179 [VIS_TEXTOBJECT_INNER_LINE] = {
180 .txt = text_object_line_inner,
182 [VIS_TEXTOBJECT_INDENTATION] = {
183 .txt = text_object_indentation,
185 [VIS_TEXTOBJECT_SEARCH_FORWARD] = {
186 .vis = search_forward,
187 .type = TEXTOBJECT_NON_CONTIGUOUS|TEXTOBJECT_EXTEND_FORWARD,
189 [VIS_TEXTOBJECT_SEARCH_BACKWARD] = {
190 .vis = search_backward,
191 .type = TEXTOBJECT_NON_CONTIGUOUS|TEXTOBJECT_EXTEND_BACKWARD,