aboutsummaryrefslogtreecommitdiffstats
path: root/pw.c
diff options
context:
space:
mode:
Diffstat (limited to 'pw.c')
-rw-r--r--pw.c115
1 files changed, 85 insertions, 30 deletions
diff --git a/pw.c b/pw.c
index 9960e5a..7a22523 100644
--- a/pw.c
+++ b/pw.c
@@ -23,6 +23,8 @@
#define ESC 27
#define DEL 127
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
#ifdef __GNUC__
#define printf_attr(fmtpos, vargpos) __attribute__ ((format (printf, \
fmtpos, vargpos)))
@@ -64,8 +66,10 @@ static int regex_flags = 0;
static char **snapshot;
static int snaplines;
-static char *trigpat;
-static regex_t trigex;
+
+#define maxtrig 100
+static char *trigpat[maxtrig];
+static regex_t trigex[maxtrig];
static grep grepstack[maxgrep];
static int ngrep;
@@ -296,10 +300,21 @@ static void drawstatus(int columns, unsigned stat, char *cmd)
}
}
- if ((stat & stat_htmode))
- ptr += snprintf(ptr, end - ptr, "TRIG (/%s) ", trigpat);
- else if ((stat & stat_ttmode))
- ptr += snprintf(ptr, end - ptr, "TRIG (?%s) ", trigpat);
+ if ((stat & (stat_htmode | stat_ttmode))) {
+ ptr += snprintf(ptr, end - ptr, "TRIG%c (",
+ (stat & stat_htmode) ? '/' : '?');
+ for (int i = 0, first = 1; i < maxtrig; i++) {
+ if (trigpat[i]) {
+ if (!first)
+ ptr += snprintf(ptr, end - ptr, ", ");
+ if (i > 0)
+ ptr += snprintf(ptr, end - ptr, "[%d]", i + 1);
+ ptr += snprintf(ptr, end - ptr, "%s", trigpat[i]);
+ first = 0;
+ }
+ }
+ ptr += snprintf(ptr, end - ptr, ") ");
+ }
if ((stat & stat_susp))
ptr += snprintf(ptr, end - ptr, "SUSPENDED ");
@@ -716,17 +731,32 @@ int main(int argc, char **argv)
}
}
if (line) {
- if ((stat & stat_htmode))
- if (regexec(&trigex, line, 0, NULL, 0) == 0)
- stat |= stat_trgrd;
if (nlines == maxlines) {
dsdrop(circbuf[0]);
memmove(circbuf, circbuf + 1, (nlines - 1) * sizeof *circbuf);
circbuf[nlines - 1] = line;
stat |= stat_dirty;
- if ((stat & stat_ttmode))
- if (regexec(&trigex, circbuf[0], 0, NULL, 0) == 0)
+ if ((stat & stat_ttmode)) {
+ int lim = min(maxtrig, nlines);
+ int trig = 1;
+ for (int i = 0; i < lim; i++)
+ if (trigpat[i] && regexec(&trigex[i], circbuf[i], 0, NULL, 0) != 0) {
+ trig = 0;
+ break;
+ }
+ if (trig)
stat |= stat_trgrd;
+ } else if ((stat & stat_htmode)) {
+ int trig = 1;
+ for (int j = nlines - 1, i = 0; j >= 0 && i < maxtrig; j--, i++) {
+ if (trigpat[i] && regexec(&trigex[i], circbuf[j], 0, NULL, 0) != 0) {
+ trig = 0;
+ break;
+ }
+ }
+ if (trig)
+ stat |= stat_trgrd;
+ }
} else {
circbuf[nlines++] = line;
if ((stat & stat_susp) == 0) {
@@ -944,6 +974,8 @@ int main(int argc, char **argv)
break;
case CR: case ctrl('c'):
if (ch == CR) {
+ unsigned trig = (cmdcount == UINT_MAX || cmdcount == 0
+ ? 0 : cmdcount - 1);
if (cmdbuf[1]) {
unsigned *pnhist = (kbd_state == kbd_colon
? &ncmdhist : &npathist);
@@ -960,38 +992,61 @@ int main(int argc, char **argv)
}
}
- if (kbd_state == kbd_trig) {
- if (trigpat) {
- regfree(&trigex);
- dsdrop(trigpat);
- trigpat = 0;
- }
- stat &= ~(stat_htmode | stat_ttmode);
- }
-
if (kbd_state == kbd_colon && cmdbuf[1]) {
execute(cmdbuf, &stat);
if (cmdbuf[0] != 0) {
kbd_state = kbd_result;
break;
}
- } else if (cmdbuf[1]) {
+ } else if (kbd_state == kbd_trig && (int) trig < maxlines && trig < maxtrig) {
int err;
- trigpat = dsdup(cmdbuf + 1);
- if ((err = regcomp(&trigex, trigpat,
- regex_flags | REG_NOSUB)))
- {
- regerror(err, &trigex, cmdbuf, sizeof cmdbuf);
+ char *pat = dsdup(cmdbuf + 1);
+ regex_t regex;
+
+ if (*pat && (err = regcomp(&regex, pat, regex_flags | REG_NOSUB))) {
+ regerror(err, &regex, cmdbuf, sizeof cmdbuf);
if (columns < (int) sizeof cmdbuf - 1)
cmdbuf[columns] = 0;
kbd_state = kbd_result;
- dsdrop(trigpat);
- trigpat = 0;
- break;
+ } else {
+ if ((cmdbuf[0] == '/' && (stat & stat_ttmode)) ||
+ (cmdbuf[0] == '?' && (stat & stat_htmode)))
+ {
+ for (int i = 0; i < maxtrig; i++) {
+ if (trigpat[i]) {
+ regfree(&trigex[i]);
+ dsdrop(trigpat[i]);
+ trigpat[i] = 0;
+ }
+ }
+ }
+
+ if (trigpat[trig]) {
+ regfree(&trigex[trig]);
+ dsdrop(trigpat[trig]);
+ trigpat[trig] = 0;
+ }
+
+ if (*pat) {
+ regfree(&regex);
+ regcomp(&trigex[trig], pat, regex_flags | REG_NOSUB);
+ trigpat[trig] = dsdup(pat);
+ }
+ }
+ dsdrop(pat);
+ }
+
+ if (kbd_state == kbd_trig) {
+ stat &= ~(stat_htmode | stat_ttmode);
+ for (int i = 0; i < maxtrig; i++) {
+ if (trigpat[i]) {
+ stat |= (cmdbuf[0] == '/' ? stat_htmode : stat_ttmode);
+ break;
+ }
}
- stat |= (cmdbuf[0] == '/' ? stat_htmode : stat_ttmode);
}
}
+
kbd_state = kbd_cmd;
curcmd = 0;
cmdcount = UINT_MAX;