summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-04-29 21:13:37 -0400
committerJakob Kaivo <jkk@ung.org>2022-04-29 21:13:37 -0400
commit444de9085aa591240671f704eb9b9ff91736dca1 (patch)
treee70ceb1036a63b74cd171c05f104226f5ea667f0
parentc1ea45ea7c694202b5eaf0b188c8c1d7342e424b (diff)
implement basic searching
-rw-r--r--more.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/more.c b/more.c
index 3461bc0..059af4c 100644
--- a/more.c
+++ b/more.c
@@ -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 ':':