summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c99
1 files changed, 80 insertions, 19 deletions
diff --git a/main.c b/main.c
index 70a25a6..cee28a8 100644
--- a/main.c
+++ b/main.c
@@ -54,7 +54,8 @@ typedef struct {
EditMode mode;
u32 count;
Str input_line, input_prompt;
- Str last_search;
+ Str search;
+ int search_dir;
} Editor;
Editor e = { 0 };
@@ -522,8 +523,60 @@ search_from_start:
return 0;
}
+int search_prev_regex(TxtLoc start, Str src, TxtLoc *out) {
+ RegEx re = { 0 };
+ ReSearch s = { 0 };
+ if (re_comp_ex(&re, src, &e.scratch, &e.scratch, RE_COMP_NO_GROUPS)) {
+ /* TODO: report parse error */
+ return 0;
+ }
+ int match_found = 0;
+ TxtLoc end = txt_end(start.t);
+ TxtLoc l = start;
+search_from_end:
+ for (;;) {
+ ReMatch m;
+ Arena a = e.scratch;
+ re_search_start(&s, &re, &e.scratch);
+ TxtLoc t = l;
+ while (!at_end(t)) {
+ TxtLoc p = t;
+ Str chnk = txt_next_chunk(&t);
+ re_search_chunk(&s, chnk.s, chnk.n);
+ if (at_end(t)) re_search_last_chunk(&s);
+ if (re_search_match_at_start(&s, &m) && m.extent.start == 0) {
+ *out = (TxtLoc) { p.t, p.p, p.i + m.extent.start };
+ return 1;
+ }
+ if (~s.flags & RE_SEARCH_MID_MATCH) {
+ if (chnk.n > 0) break;
+ if (txt_after(t, end)) break;
+ }
+ }
+ e.scratch = a;
+ if (at_start(l)) break;
+ l = cprev(l);
+ }
+ if (match_found == 0) {
+ match_found = -1;
+ l = txt_end(l.t);
+ end = start;
+ goto search_from_end;
+ }
+ return 0;
+}
+
+int read_search(void) {
+ Str src = get_input_line(S("Search: "));
+ if (!src.n) return 0;
+ e.search.s = malloc(src.n);
+ if (!e.search.s) FAIL_WITH_MSG("failed to allocate search");
+ memcpy(e.search.s, src.s, src.n);
+ e.search.n = src.n;
+ return 1;
+}
+
int motion(TxtLoc *lp, u32 c) {
- static Str last_search = { 0 };
TxtLoc l = *lp;
TxtLoc last_loc = l;
@@ -657,25 +710,33 @@ loop:
}
} break;
- case '/': {
- if (last_search.s) free(last_search.s);
- last_search = (Str) { 0, 0 };
- Str src = get_input_line(S("Search: "));
- if (!src.n) return 0;
- last_search.s = malloc(src.n);
- if (!last_search.s) FAIL_WITH_MSG("failed to allocate search");
- memcpy(last_search.s, src.s, src.n);
- last_search.n = src.n;
- TxtLoc r;
- if (search_next_regex(l, src, &r)) {
- l = r;
+ case '/':
+ if (read_search()) {
+ TxtLoc r;
+ if (search_next_regex(l, e.search, &r)) l = r;
+ e.search_dir = 1;
}
- } break;
+ break;
- case 'n': {
- TxtLoc r;
- if (last_search.n > 0 && search_next_regex(cnext(l), last_search, &r)) l = r;
- } break;
+ case '?':
+ if (read_search()) {
+ TxtLoc r;
+ if (search_prev_regex(l, e.search, &r)) l = r;
+ e.search_dir = -1;
+ }
+ break;
+
+ case 'n':
+ if (!e.search.n) return 0;
+ if (e.search_dir > 0 && !search_next_regex(cnext(l), e.search, &l)) return 0;
+ if (e.search_dir < 0 && !search_prev_regex(cprev(l), e.search, &l)) return 0;
+ break;
+
+ case 'N':
+ if (!e.search.n) return 0;
+ if (e.search_dir < 0 && !search_next_regex(cnext(l), e.search, &l)) return 0;
+ if (e.search_dir > 0 && !search_prev_regex(cprev(l), e.search, &l)) return 0;
+ break;
default:
return 0;