aboutsummaryrefslogtreecommitdiff
path: root/text-objects.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-08-28 16:58:33 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-08-28 16:58:33 +0200
commit7c04ebd1309ea8e9032003a21c1d7594a8a75207 (patch)
treece05b005bc4961a35ff8c1ad01bbe3014130641b /text-objects.c
parentac4570c5534fbc9499d15eb58d97fbb2048e5fc6 (diff)
downloadvis-7c04ebd1309ea8e9032003a21c1d7594a8a75207.tar.gz
vis-7c04ebd1309ea8e9032003a21c1d7594a8a75207.tar.xz
text-objects: add objects delimited by brackets or quotes
Diffstat (limited to 'text-objects.c')
-rw-r--r--text-objects.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/text-objects.c b/text-objects.c
index 121811d..7595ac7 100644
--- a/text-objects.c
+++ b/text-objects.c
@@ -1,6 +1,7 @@
#include <ctype.h>
#include "text-motions.h"
#include "text-objects.h"
+#include "util.h"
static Filerange empty = {
.start = -1,
@@ -8,8 +9,8 @@ static Filerange empty = {
};
Filerange text_object_word(Text *txt, size_t pos) {
- char c, prev = '0', next = '0';
Filerange r;
+ char c, prev = '0', next = '0';
Iterator it = text_iterator_get(txt, pos);
if (!text_iterator_byte_get(&it, &c))
return empty;
@@ -53,3 +54,53 @@ Filerange text_object_paragraph(Text *txt, size_t pos) {
r.end = text_paragraph_next(txt, pos);
return r;
}
+
+Filerange text_object_bracket(Text *txt, size_t pos, char type) {
+ char c, open, close;
+ int opened = 1, closed = 1;
+
+ switch (type) {
+ case '(': case ')': open = '('; close = ')'; break;
+ case '{': case '}': open = '{'; close = '}'; break;
+ case '[': case ']': open = '['; close = ']'; break;
+ case '<': case '>': open = '<'; close = '>'; break;
+ case '"': open = '"'; close = '"'; break;
+ case '\'': open = '\''; close = '\''; break;
+ default: return empty;
+ }
+
+ Filerange r = empty;
+ Iterator it = text_iterator_get(txt, pos);
+
+ if (open == close && text_iterator_byte_get(&it, &c) && (c == '"' || c == '\'')) {
+ size_t match = text_bracket_match(txt, pos);
+ r.start = MIN(pos, match) + 1;
+ r.end = MAX(pos, match);
+ return r;
+ }
+
+ while (text_iterator_byte_get(&it, &c)) {
+ if (c == open && --opened == 0) {
+ r.start = it.pos + 1;
+ break;
+ } else if (c == close && it.pos != pos) {
+ opened++;
+ }
+ text_iterator_byte_prev(&it, NULL);
+ }
+
+ it = text_iterator_get(txt, pos);
+ while (text_iterator_byte_get(&it, &c)) {
+ if (c == close && --closed == 0) {
+ r.end = it.pos;
+ break;
+ } else if (c == open && it.pos != pos) {
+ closed++;
+ }
+ text_iterator_byte_next(&it, NULL);
+ }
+
+ if (r.start == (size_t)-1 || r.end == (size_t)-1 || r.start > r.end)
+ return empty;
+ return r;
+}