1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#include "vis-core.h"
#include "text-objects.h"
#include "util.h"
int vis_textobject_register(Vis *vis, int type, void *data,
Filerange (*textobject)(Vis*, Win*, void*, size_t pos)) {
TextObject *obj = calloc(1, sizeof *obj);
if (!obj)
return -1;
obj->user = textobject;
obj->type = type;
obj->data = data;
if (array_add_ptr(&vis->textobjects, obj))
return LENGTH(vis_textobjects) + array_length(&vis->textobjects) - 1;
free(obj);
return -1;
}
bool vis_textobject(Vis *vis, enum VisTextObject id) {
if (id < LENGTH(vis_textobjects))
vis->action.textobj = &vis_textobjects[id];
else
vis->action.textobj = array_get_ptr(&vis->textobjects, id - LENGTH(vis_textobjects));
if (!vis->action.textobj)
return false;
action_do(vis, &vis->action);
return true;
}
static Filerange search_forward(Vis *vis, Text *txt, size_t pos) {
Filerange range = text_range_empty();
Regex *regex = vis_regex(vis, NULL);
if (regex)
range = text_object_search_forward(txt, pos, regex);
text_regex_free(regex);
return range;
}
static Filerange search_backward(Vis *vis, Text *txt, size_t pos) {
Filerange range = text_range_empty();
Regex *regex = vis_regex(vis, NULL);
if (regex)
range = text_object_search_backward(txt, pos, regex);
text_regex_free(regex);
return range;
}
static Filerange object_unpaired(Text *txt, size_t pos, char obj) {
char c;
bool before = false;
Iterator it = text_iterator_get(txt, pos), rit = it;
while (text_iterator_byte_get(&rit, &c) && c != '\n') {
if (c == obj) {
before = true;
break;
}
text_iterator_byte_prev(&rit, NULL);
}
/* if there is no previous occurence on the same line, advance starting position */
if (!before) {
while (text_iterator_byte_get(&it, &c) && c != '\n') {
if (c == obj) {
pos = it.pos;
break;
}
text_iterator_byte_next(&it, NULL);
}
}
switch (obj) {
case '"':
return text_object_quote(txt, pos);
case '\'':
return text_object_single_quote(txt, pos);
case '`':
return text_object_backtick(txt, pos);
default:
return text_range_empty();
}
}
static Filerange object_quote(Text *txt, size_t pos) {
return object_unpaired(txt, pos, '"');
}
static Filerange object_single_quote(Text *txt, size_t pos) {
return object_unpaired(txt, pos, '\'');
}
static Filerange object_backtick(Text *txt, size_t pos) {
return object_unpaired(txt, pos, '`');
}
const TextObject vis_textobjects[] = {
[VIS_TEXTOBJECT_INNER_WORD] = { .txt = text_object_word },
[VIS_TEXTOBJECT_OUTER_WORD] = { .txt = text_object_word_outer },
[VIS_TEXTOBJECT_INNER_LONGWORD] = { .txt = text_object_longword },
[VIS_TEXTOBJECT_OUTER_LONGWORD] = { .txt = text_object_longword_outer },
[VIS_TEXTOBJECT_SENTENCE] = { .txt = text_object_sentence },
[VIS_TEXTOBJECT_PARAGRAPH] = { .txt = text_object_paragraph },
[VIS_TEXTOBJECT_OUTER_SQUARE_BRACKET] = { .txt = text_object_square_bracket, .type = OUTER },
[VIS_TEXTOBJECT_INNER_SQUARE_BRACKET] = { .txt = text_object_square_bracket, .type = INNER },
[VIS_TEXTOBJECT_OUTER_CURLY_BRACKET] = { .txt = text_object_curly_bracket, .type = OUTER },
[VIS_TEXTOBJECT_INNER_CURLY_BRACKET] = { .txt = text_object_curly_bracket, .type = INNER },
[VIS_TEXTOBJECT_OUTER_ANGLE_BRACKET] = { .txt = text_object_angle_bracket, .type = OUTER },
[VIS_TEXTOBJECT_INNER_ANGLE_BRACKET] = { .txt = text_object_angle_bracket, .type = INNER },
[VIS_TEXTOBJECT_OUTER_PARANTHESE] = { .txt = text_object_paranthese, .type = OUTER },
[VIS_TEXTOBJECT_INNER_PARANTHESE] = { .txt = text_object_paranthese, .type = INNER },
[VIS_TEXTOBJECT_OUTER_QUOTE] = { .txt = object_quote, .type = OUTER },
[VIS_TEXTOBJECT_INNER_QUOTE] = { .txt = object_quote, .type = INNER },
[VIS_TEXTOBJECT_OUTER_SINGLE_QUOTE] = { .txt = object_single_quote, .type = OUTER },
[VIS_TEXTOBJECT_INNER_SINGLE_QUOTE] = { .txt = object_single_quote, .type = INNER },
[VIS_TEXTOBJECT_OUTER_BACKTICK] = { .txt = object_backtick, .type = OUTER },
[VIS_TEXTOBJECT_INNER_BACKTICK] = { .txt = object_backtick, .type = INNER },
[VIS_TEXTOBJECT_OUTER_ENTIRE] = { .txt = text_object_entire, },
[VIS_TEXTOBJECT_INNER_ENTIRE] = { .txt = text_object_entire_inner, },
[VIS_TEXTOBJECT_OUTER_FUNCTION] = { .txt = text_object_function, },
[VIS_TEXTOBJECT_INNER_FUNCTION] = { .txt = text_object_function_inner, },
[VIS_TEXTOBJECT_OUTER_LINE] = { .txt = text_object_line, },
[VIS_TEXTOBJECT_INNER_LINE] = { .txt = text_object_line_inner, },
[VIS_TEXTOBJECT_INDENTATION] = { .txt = text_object_indentation, },
[VIS_TEXTOBJECT_SEARCH_FORWARD] = { .vis = search_forward, .type = SPLIT },
[VIS_TEXTOBJECT_SEARCH_BACKWARD] = { .vis = search_backward, .type = SPLIT },
};
|