size_t text_search_forward(Text *txt, size_t pos, Regex *regex) { size_t start = pos + 1; size_t end = text_size(txt); RegexMatch match[1]; bool found = start < end && !text_search_range_forward(txt, start, end - start, regex, 1, match, 0); if (!found) { start = 0; end = pos; found = !text_search_range_forward(txt, start, end, regex, 1, match, 0); } return found ? match[0].start : pos; }
Filerange text_object_search_forward(Text *txt, size_t pos, Regex *regex) { size_t start = pos; size_t end = text_size(txt); RegexMatch match[1]; bool found = start < end && !text_search_range_forward(txt, start, end - start, regex, 1, match, 0); if (found) return text_range_new(match[0].start, match[0].end); return text_range_empty(); }
static bool cmd_guard(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) { if (!win) return false; bool match = !text_search_range_forward(win->file->text, range->start, text_range_size(range), cmd->regex, 0, NULL, 0); if (match ^ (argv[0][0] == 'v')) return sam_execute(vis, win, cmd->cmd, cur, range); view_cursors_dispose(cur); return true; }
static bool cmd_extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) { if (!win) return false; bool ret = true; Text *txt = win->file->text; if (cmd->regex) { size_t start = range->start, end = range->end, last_start = EPOS; RegexMatch match[1]; while (start < end) { bool found = text_search_range_forward(txt, start, end - start, cmd->regex, 1, match, start > range->start ? REG_NOTBOL : 0) == 0; Filerange r = text_range_empty(); if (found) { if (argv[0][0] == 'x') r = text_range_new(match[0].start, match[0].end); else r = text_range_new(start, match[0].start); if (match[0].start == match[0].end) { if (last_start == match[0].start) { start++; continue; } /* in Plan 9's regexp library ^ matches the beginning * of a line, however in POSIX with REG_NEWLINE ^ * matches the zero-length string immediately after a * newline. Try filtering out the last such match at EOF. */ if (end == match[0].start && start > range->start) break; } start = match[0].end; } else { if (argv[0][0] == 'y') r = text_range_new(start, end); start = end; } if (text_range_valid(&r)) { Mark mark_start = text_mark_set(txt, start); Mark mark_end = text_mark_set(txt, end); ret &= sam_execute(vis, win, cmd->cmd, NULL, &r); last_start = start = text_mark_get(txt, mark_start); if (start == EPOS && last_start != r.end) last_start = start = r.end; end = text_mark_get(txt, mark_end); if (start == EPOS || end == EPOS) { ret = false; break; } } } } else { size_t start = range->start, end = range->end; while (start < end) { size_t next = text_line_next(txt, start); if (next > end) next = end; Filerange r = text_range_new(start, next); if (start == next || !text_range_valid(&r)) break; start = next; Mark mark_start = text_mark_set(txt, start); Mark mark_end = text_mark_set(txt, end); ret &= sam_execute(vis, win, cmd->cmd, NULL, &r); start = text_mark_get(txt, mark_start); if (start == EPOS) start = r.end; end = text_mark_get(txt, mark_end); if (end == EPOS) { ret = false; break; } } } view_cursors_dispose(cur); return ret; }