diff options
author | Jakob Kaivo <jkk@ung.org> | 2022-04-29 21:13:37 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2022-04-29 21:13:37 -0400 |
commit | 444de9085aa591240671f704eb9b9ff91736dca1 (patch) | |
tree | e70ceb1036a63b74cd171c05f104226f5ea667f0 | |
parent | c1ea45ea7c694202b5eaf0b188c8c1d7342e424b (diff) |
implement basic searching
-rw-r--r-- | more.c | 65 |
1 files changed, 56 insertions, 9 deletions
@@ -27,6 +27,7 @@ #include <errno.h> #include <libgen.h> #include <locale.h> +#include <regex.h> #include <spawn.h> #include <stdarg.h> #include <stdio.h> @@ -99,7 +100,6 @@ static void more_echo(int on) tcsetattr(fileno(more_in), TCSANOW, &ti); } - static void more_status(const char *fmt, ...) { va_list ap; @@ -316,7 +316,7 @@ static void more_scroll(struct more_file *mf, int count, int multiple) } } -static void mark(struct more_file *mf) +static void more_mark(struct more_file *mf) { int c = fgetc(more_in); if (islower(c)) { @@ -324,7 +324,7 @@ static void mark(struct more_file *mf) } } -static void jump(struct more_file *mf) +static void more_jump(struct more_file *mf) { int c = fgetc(more_in); if (islower(c)) { @@ -495,6 +495,53 @@ static struct more_file * more_next(struct more_file *mf, int n) return mf; } +static void more_search(struct more_file *mf, int count, int reuse) +{ + static regex_t re; + static enum { UNDEF = -1, MATCH = 0, NOMATCH = REG_NOMATCH } match = UNDEF; + + if (!reuse) { + char *buf = NULL; + size_t blen = 0; + more_echo(1); + printf("%c", (count > 0) ? '/' : '?'); + getline(&buf, &blen, more_in); + more_echo(0); + + if (buf[0] != '\n') { + char *nl = strchr(buf, '\n'); + *nl = '\0'; + regfree(&re); + if (regcomp(&re, buf, REG_NOSUB) != 0) { + fprintf(stderr, "more: invalid expression"); + match = UNDEF; + } else if (buf[0] == '!') { + match = NOMATCH; + } else { + match = MATCH; + } + } + } + + if (match == UNDEF) { + return; + } + + while (count != 0) { + mf->topline += (count > 0) ? 1 : -1; + if (more_getline(mf, mf->topline) == -1) { + fprintf(stderr, "more: expression not found"); + return; + } + + if (regexec(&re, mf->buf, 0, NULL, 0) == match) { + count += (count > 0) ? -1 : 1; + } + } + + more_refresh(mf); +} + static int more(struct more_file *mf) { if (more_open(mf) != 0) { @@ -603,27 +650,27 @@ static int more(struct more_file *mf) break; case 'm': - mark(mf); + more_mark(mf); break; case '\'': - jump(mf); + more_jump(mf); break; case '/': - //search(count); + more_search(mf, count ? count : 1, 0); break; case '?': - //search(-count); + more_search(mf, count ? -count : -1, 0); break; case 'n': - //repeatsearch(count); + more_search(mf, count ? count : 1, 1); break; case 'N': - //repeatsearch(-count); + more_search(mf, count ? -count : -1, 1); break; case ':': |