aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2016-08-20 16:08:57 +0200
committerMarc André Tanner <mat@brain-dump.org>2016-08-24 11:10:00 +0200
commit349e5f4150ea9fdc27d523060e62d93f44a212ba (patch)
tree039b76efedaaa995687176f8c8c7a07c95765a7c
parent928a55e2433a780d75f997ecc1f9ff956b6220d8 (diff)
downloadvis-349e5f4150ea9fdc27d523060e62d93f44a212ba.tar.gz
vis-349e5f4150ea9fdc27d523060e62d93f44a212ba.tar.xz
text-motions: improve matching quotation marks heuristic
Prefer quotation marks on the same line to when looking for matching pairs. Improves #358.
-rw-r--r--text-motions.c87
1 files changed, 55 insertions, 32 deletions
diff --git a/text-motions.c b/text-motions.c
index 1bf6611..8af6b7b 100644
--- a/text-motions.c
+++ b/text-motions.c
@@ -610,42 +610,13 @@ size_t text_bracket_match(Text *txt, size_t pos) {
return text_bracket_match_symbol(txt, pos, NULL);
}
-size_t text_bracket_match_symbol(Text *txt, size_t pos, const char *symbols) {
- int direction, count = 1;
- char search, current, c;
+static size_t match_symbol(Text *txt, size_t pos, char search, int direction) {
+ char c, current;
+ int count = 1;
bool instring = false;
Iterator it = text_iterator_get(txt, pos);
if (!text_iterator_byte_get(&it, &current))
return pos;
- if (symbols && !memchr(symbols, current, strlen(symbols)))
- return pos;
- switch (current) {
- case '(': search = ')'; direction = 1; break;
- case ')': search = '('; direction = -1; break;
- case '{': search = '}'; direction = 1; break;
- case '}': search = '{'; direction = -1; break;
- case '[': search = ']'; direction = 1; break;
- case ']': search = '['; direction = -1; break;
- case '<': search = '>'; direction = 1; break;
- case '>': search = '<'; direction = -1; break;
- case '"':
- case '`':
- case '\'': {
- char special[] = " \n)}]>.,:;";
- search = current;
- direction = 1;
- if (text_iterator_byte_next(&it, &c)) {
- /* if a single or double quote is followed by
- * a special character, search backwards */
- if (memchr(special, c, sizeof(special)))
- direction = -1;
- text_iterator_byte_prev(&it, NULL);
- }
- break;
- }
- default: return pos;
- }
-
if (direction >= 0) { /* forward search */
while (text_iterator_byte_next(&it, &c)) {
if (c != current && c == '"')
@@ -673,6 +644,58 @@ size_t text_bracket_match_symbol(Text *txt, size_t pos, const char *symbols) {
return pos; /* no match found */
}
+size_t text_bracket_match_symbol(Text *txt, size_t pos, const char *symbols) {
+ int direction;
+ char search, current, c;
+ Iterator it = text_iterator_get(txt, pos);
+ if (!text_iterator_byte_get(&it, &current))
+ return pos;
+ if (symbols && !memchr(symbols, current, strlen(symbols)))
+ return pos;
+ switch (current) {
+ case '(': search = ')'; direction = 1; break;
+ case ')': search = '('; direction = -1; break;
+ case '{': search = '}'; direction = 1; break;
+ case '}': search = '{'; direction = -1; break;
+ case '[': search = ']'; direction = 1; break;
+ case ']': search = '['; direction = -1; break;
+ case '<': search = '>'; direction = 1; break;
+ case '>': search = '<'; direction = -1; break;
+ case '"':
+ case '`':
+ case '\'':
+ {
+ /* prefer matches on the same line */
+ size_t fw = match_symbol(txt, pos, current, +1);
+ size_t bw = match_symbol(txt, pos, current, -1);
+ if (fw == pos)
+ return bw;
+ if (bw == pos)
+ return fw;
+ size_t line = text_lineno_by_pos(txt, pos);
+ size_t line_fw = text_lineno_by_pos(txt, fw);
+ size_t line_bw = text_lineno_by_pos(txt, bw);
+ if (line != line_fw)
+ return bw;
+ if (line != line_bw)
+ return fw;
+ direction = +1;
+ if (text_iterator_byte_next(&it, &c)) {
+ /* if a single or double quote is followed by
+ * a special character, search backwards */
+ char special[] = " \n)}]>.,:;";
+ if (memchr(special, c, sizeof(special)))
+ direction = -1;
+ }
+ return direction >= 0 ? fw : bw;
+ }
+ default:
+ return pos;
+ }
+
+ return match_symbol(txt, pos, search, direction);
+}
+
size_t text_search_forward(Text *txt, size_t pos, Regex *regex) {
size_t start = pos + 1;
size_t end = text_size(txt);