vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

vis-text-objects.c

(4928B)


      1 #include "vis-core.h"
      2 #include "text-objects.h"
      3 #include "util.h"
      4 
      5 int vis_textobject_register(Vis *vis, int type, void *data, VisTextObjectFunction *textobject) {
      6 
      7 	TextObject *obj = calloc(1, sizeof *obj);
      8 	if (!obj)
      9 		return -1;
     10 
     11 	obj->user = textobject;
     12 	obj->type = type;
     13 	obj->data = data;
     14 
     15 	if (array_add_ptr(&vis->textobjects, obj))
     16 		return LENGTH(vis_textobjects) + vis->textobjects.len - 1;
     17 	free(obj);
     18 	return -1;
     19 }
     20 
     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;
     30 }
     31 
     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);
     35 	if (regex)
     36 		range = text_object_search_forward(txt, pos, regex);
     37 	text_regex_free(regex);
     38 	return range;
     39 }
     40 
     41 static Filerange search_backward(Vis *vis, Text *txt, size_t pos) {
     42 	Filerange range = text_range_empty();
     43 	Regex *regex = vis_regex(vis, NULL);
     44 	if (regex)
     45 		range = text_object_search_backward(txt, pos, regex);
     46 	text_regex_free(regex);
     47 	return range;
     48 }
     49 
     50 static Filerange object_unpaired(Text *txt, size_t pos, char obj) {
     51 	char c;
     52 	bool before = false;
     53 	Iterator it = text_iterator_get(txt, pos), rit = it;
     54 
     55 	while (text_iterator_byte_get(&rit, &c) && c != '\n') {
     56 		if (c == obj) {
     57 			before = true;
     58 			break;
     59 		}
     60 		text_iterator_byte_prev(&rit, NULL);
     61 	}
     62 
     63 	/* if there is no previous occurrence on the same line, advance starting position */
     64 	if (!before) {
     65 		while (text_iterator_byte_get(&it, &c) && c != '\n') {
     66 			if (c == obj) {
     67 				pos = it.pos;
     68 				break;
     69 			}
     70 			text_iterator_byte_next(&it, NULL);
     71 		}
     72 	}
     73 
     74 	switch (obj) {
     75 	case '"':
     76 		return text_object_quote(txt, pos);
     77 	case '\'':
     78 		return text_object_single_quote(txt, pos);
     79 	case '`':
     80 		return text_object_backtick(txt, pos);
     81 	default:
     82 		return text_range_empty();
     83 	}
     84 }
     85 
     86 static Filerange object_quote(Text *txt, size_t pos) {
     87 	return object_unpaired(txt, pos, '"');
     88 }
     89 
     90 static Filerange object_single_quote(Text *txt, size_t pos) {
     91 	return object_unpaired(txt, pos, '\'');
     92 }
     93 
     94 static Filerange object_backtick(Text *txt, size_t pos) {
     95 	return object_unpaired(txt, pos, '`');
     96 }
     97 
     98 const TextObject vis_textobjects[] = {
     99 	[VIS_TEXTOBJECT_INNER_WORD] = {
    100 		.txt = text_object_word,
    101 	},
    102 	[VIS_TEXTOBJECT_OUTER_WORD] = {
    103 		.txt = text_object_word_outer,
    104 	},
    105 	[VIS_TEXTOBJECT_INNER_LONGWORD] = {
    106 		.txt = text_object_longword,
    107 	},
    108 	[VIS_TEXTOBJECT_OUTER_LONGWORD] = {
    109 		.txt = text_object_longword_outer,
    110 	},
    111 	[VIS_TEXTOBJECT_SENTENCE] = {
    112 		.txt = text_object_sentence,
    113 	},
    114 	[VIS_TEXTOBJECT_PARAGRAPH] = {
    115 		.txt = text_object_paragraph,
    116 	},
    117 	[VIS_TEXTOBJECT_PARAGRAPH_OUTER] = {
    118 		.txt = text_object_paragraph_outer,
    119 	},
    120 	[VIS_TEXTOBJECT_OUTER_SQUARE_BRACKET] = {
    121 		.txt = text_object_square_bracket,
    122 		.type = TEXTOBJECT_DELIMITED_OUTER,
    123 	},
    124 	[VIS_TEXTOBJECT_INNER_SQUARE_BRACKET] = {
    125 		.txt = text_object_square_bracket,
    126 		.type = TEXTOBJECT_DELIMITED_INNER,
    127 	},
    128 	[VIS_TEXTOBJECT_OUTER_CURLY_BRACKET] = {
    129 		.txt = text_object_curly_bracket,
    130 		.type = TEXTOBJECT_DELIMITED_OUTER,
    131 	},
    132 	[VIS_TEXTOBJECT_INNER_CURLY_BRACKET] = {
    133 		.txt = text_object_curly_bracket,
    134 		.type = TEXTOBJECT_DELIMITED_INNER,
    135 	},
    136 	[VIS_TEXTOBJECT_OUTER_ANGLE_BRACKET] = {
    137 		.txt = text_object_angle_bracket,
    138 		.type = TEXTOBJECT_DELIMITED_OUTER,
    139 	},
    140 	[VIS_TEXTOBJECT_INNER_ANGLE_BRACKET] = {
    141 		.txt = text_object_angle_bracket,
    142 		.type = TEXTOBJECT_DELIMITED_INNER,
    143 	},
    144 	[VIS_TEXTOBJECT_OUTER_PARENTHESIS] = {
    145 		.txt = text_object_parenthesis,
    146 		.type = TEXTOBJECT_DELIMITED_OUTER,
    147 	},
    148 	[VIS_TEXTOBJECT_INNER_PARENTHESIS] = {
    149 		.txt = text_object_parenthesis,
    150 		.type = TEXTOBJECT_DELIMITED_INNER,
    151 	},
    152 	[VIS_TEXTOBJECT_OUTER_QUOTE] = {
    153 		.txt = object_quote,
    154 		.type = TEXTOBJECT_DELIMITED_OUTER,
    155 	},
    156 	[VIS_TEXTOBJECT_INNER_QUOTE] = {
    157 		.txt = object_quote,
    158 		.type = TEXTOBJECT_DELIMITED_INNER,
    159 	},
    160 	[VIS_TEXTOBJECT_OUTER_SINGLE_QUOTE] = {
    161 		.txt = object_single_quote,
    162 		.type = TEXTOBJECT_DELIMITED_OUTER,
    163 	},
    164 	[VIS_TEXTOBJECT_INNER_SINGLE_QUOTE] = {
    165 		.txt = object_single_quote,
    166 		.type = TEXTOBJECT_DELIMITED_INNER,
    167 	},
    168 	[VIS_TEXTOBJECT_OUTER_BACKTICK] = {
    169 		.txt = object_backtick,
    170 		.type = TEXTOBJECT_DELIMITED_OUTER,
    171 	},
    172 	[VIS_TEXTOBJECT_INNER_BACKTICK] = {
    173 		.txt = object_backtick,
    174 		.type = TEXTOBJECT_DELIMITED_INNER,
    175 	},
    176 	[VIS_TEXTOBJECT_OUTER_LINE] = {
    177 		.txt = text_object_line,
    178 	},
    179 	[VIS_TEXTOBJECT_INNER_LINE] = {
    180 		.txt = text_object_line_inner,
    181 	},
    182 	[VIS_TEXTOBJECT_INDENTATION] = {
    183 		.txt = text_object_indentation,
    184 	},
    185 	[VIS_TEXTOBJECT_SEARCH_FORWARD] = {
    186 		.vis = search_forward,
    187 		.type = TEXTOBJECT_NON_CONTIGUOUS|TEXTOBJECT_EXTEND_FORWARD,
    188 	},
    189 	[VIS_TEXTOBJECT_SEARCH_BACKWARD] = {
    190 		.vis = search_backward,
    191 		.type = TEXTOBJECT_NON_CONTIGUOUS|TEXTOBJECT_EXTEND_BACKWARD,
    192 	},
    193 };
    194